Ruby 簡単なテスト駆動開発とリファクタリング

Rubyチュートリアル3章を試してみました。

テスト駆動開発リファクタリングを行いました
重要なとこをまとめてみました

まず静的なページに対する結合テスト(request spec) を生成します

$ rails generate integration_test static_pages
      invoke  rspec
      create    spec/requests/static_pages_spec.rb

static_pages_spec.rbが生成されました

中身はこんな感じになっていて

require 'spec_helper'

describe "Static pages" do

  describe "Home page" do

    it "should have the content 'Sample App'" do
      visit '/static_pages/home'
      expect(page).to have_content('Sample App')
    end
  end
end

it "…" doで始まるのがテストですね

visit '/static_pages/home'

上の行は、Capybaraのvisit機能を使って、ブラウザでの/static_pages/homeURLへのアクセスをシミュレーションします。

expect(page).to have_content('Sample App')

その次の行 (上のコード) では、これもCapybaraが提供するpage変数を使って、アクセスした結果のページに正しいコンテンツが表示されているかどうかをテストしています。

ちなみにテストが正常に実行されるようにするためにはspec_helper.rbに

RSpec.configure do |config|

これを追加する必要があります

実際にテストを行ってみます

$ bundle exec rspec spec/requests/static_pages_spec.rb

bundle execをrspecのコマンドの前に置くことで、Gemfile内で定義された環境でRSpecが実行されるように、明示的に指示することができるみたいです。

まずこれを実行するとテストが失敗します
Failure / Error expect (page).to have_content('Sample App') ........
... app/views/static_pages/home.html.erb
...
1 example, 1 failure
間省きますがこんな感じででます

一般的にはこれを「赤色 (Red)」
パスするコードを「緑色 (Green)」と言うそうです

テストにパスするHomeページ用コードを書きます
app/views/static_pages/home.html.erb

<h1>Sample App</h1>
<p>
    This is the home page for the
  <a href="http://railstutorial.jp/">Ruby on Rails Tutorial</a>
    sample application.
</p>

見出しがSample Appに変更されたため上のコードはパスします
もう一度見てみると

$ bundle exec rspec spec/requests/static_pages_spec.rb

Finished in.......
1 example, 0 failures
.......

とでます

ちなみに同じようなhelpページとaboutページを追加して

<!DOCTYPE html>
<html>
  <head>
    <title>Ruby on Rails Tutorial Sample App | Home</title>
  </head>
  <body>
    <h1>Sample App</h1>
    <p>
    This is the home page for the
      <a href="http://railstutorial.jp/">Ruby on Rails Tutorial</a>
    sample application.
    </p>
  </body>
</html>

このようなHTML構造で書いてます
これは
・ページのタイトルがどれもほぼ同じ。
・“Ruby on Rails Tutorial Sample App” が3つのタイトルで共通している。
・HTMLの構造全体が各ページで重複している。

このコードはDRYの原則に反しているのでまとめます

まず埋め込みrubyを使ってhome.html.erbビューのタイトルを直していきます

<% provide(:title, 'Home') %>
<!DOCTYPE html>
<html>
  <head>
    <title>Ruby on Rails Tutorial Sample App | <%= yield(:title) %></title>
  </head>

ERbと呼ばれている、Rubyの埋め込みの例です
※HTMLビューのファイルの拡張子が.html.erbとなっている理由

provide関数で関連づけてyield関数で挿入します

ちなみに<% ... %>書くと単に実行するだけで
<%= ... %>結果がテンプレートに挿入されます

<%= ... %>はphpで言うところのechoですね
同様に他のページでも編集していきます。

ここで各ページをみていくとタイトルをのぞいてだいたいこーなってます

<% provide(:title, 'Foo') %>
<!DOCTYPE html>
<html>
  <head>
    <title>Ruby on Rails Tutorial Sample App | <%= yield(:title) %></title>
  </head>
  <body>
      Contents
  </body>
</html>

同じにつくったので同じ構造になってる思いますww

Railsには、共通の構造をまとめるためのapplication.html.erbという
特別なレイアウトファイルがあるみたいなので使ってみます。

デフォルトタイトルを埋め込みRubyのコードに差し替えます。
app/views/layouts/application.html.erb

<!DOCTYPE html>
<html>
<head>
  <title>Ruby on Rails Tutorial Sample App | <%= yield(:title) %></title>
  <%= stylesheet_link_tag    "application", media: "all",
                                            "data-turbolinks-track" => true %>
  <%= javascript_include_tag "application", "data-turbolinks-track" => true %>
  <%= csrf_meta_tags %>
</head>
<body>

<%= yield %>

</body>
</html>

<%= yield %>は各ページの内容をレイアウトに挿入するためのものです。

/static_pages/homeにアクセスすると、
home.html.erbの内容がHTMLに変換され、<%= yield %>の位置に挿入されるみたいです

下のこれはそれぞれにインクルードするためのものです

<%= stylesheet_link_tag ... %>
<%= javascript_include_tag "application", ... %>
<%= csrf_meta_tags %>

ではhome.html.erbのHTML構造を抜くとこんな感じになります

<% provide(:title, 'Home') %>
<h1>Sample App</h1>
<p>
    This is the home page for the
    <a href="http://railstutorial.jp/">Ruby on Rails Tutorial</a>
    sample application.
</p>

まとめるのが難しかったためほとんどコピペのような形になってしまいました>_<