Railsチュートリアル 第5章 - レイアウトを作成する…レイアウトのリンク

# レイアウトのリンク概論

Railsにおいても、リンクを直接記述することは可能です。

```html:Aboutへのリンクを直接記述する
<a href="/static_pages/about">About</a>
```

しかし、リンクを直接記述するというのは、いかにも力押しで、Railsらしいエレガントなコードではないですね。変数・定数の定義以外では、できる限りリテラルの埋め込みは避けたいものです。

さらに、以下のような事情もあります。

* aboutページのURLは、`/static_pages/about`より`/about`のほうが好ましい
* Railsでは、aboutページのようなページへのリンクには、名前付きルートを使うのが慣例である

となると、Aboutページへのリンクは以下のように書くのがRails的です。

```erb:Aboutへのリンクの、Railsらしい記法
<%= link_to "About", about_path %>
```

前述「Railsらしい記法」には、以下のような利点があります。

* コードの意味がわかりやすくなる
* `about_path`の定義を書き換えることで、`about_path`が使われているすべてのURLを一度に変更することができるようになる

Railsチュートリアルでは、今後使う予定のURLとルーティング(route)とのマッピングを、以下のように定義しています。

|ページ名|URL|名前付きルート|
|---|---|---|
|Home|/|`root_path`|
|About|/about|`about_path`|
|Help|/help|`help_path`|
|Contact|/contact|`contact_path`|
|Sign Up|/signup|`signup_path`|
|Log In|/login|`login_path`|

# Contactページ

[演習 - サンプルアプリケーションにContact (問い合わせ先) ページを作成してみる](https://qiita.com/rapidliner00/items/5e216b6af409e3e0b26c#%E6%BC%94%E7%BF%92---%E3%82%B5%E3%83%B3%E3%83%97%E3%83%AB%E3%82%A2%E3%83%97%E3%83%AA%E3%82%B1%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%81%ABcontact-%E5%95%8F%E3%81%84%E5%90%88%E3%82%8F%E3%81%9B%E5%85%88-%E3%83%9A%E3%83%BC%E3%82%B8%E3%82%92%E4%BD%9C%E6%88%90%E3%81%97%E3%81%A6%E3%81%BF%E3%82%8B)で既に作成していました。当該項目をご参照ください。

# RailsのルートURL

名前付きルートをサンプルアプリケーションの静的ページで使うために、ルーティング用のファイル(`config/routes.rb`)を編集していきます。

現時点で、既にHomeページのルーティングは設定されています。`root`ルーティングが存在しないと、Railsアプリケーションそのものが動作しないからです。

```ruby:config/routes.rb（抜粋）
root 'static_pages#home'
```

名前付きルートを含むルートURLを設定することには、以下のような利点があります。

* ブラウザからアクセスしやすくなる
* 名前付きルートを使ってURLを参照できるようになる
    * `root`であれば、`root_path`や`root_url`といったメソッドを使えるようになる

`rails console`から`app.root_path`や`app.root_url`メソッドを使うこともできます。現時点における`app.root_path`および`app.root_url`の結果は以下の通りでした。

```
>> app.root_path
=> "/"
>> app.root_url
=> "http://www.example.com/"
```

ルーティング用のファイルの`get`ルールは、第1引数にURL、第2引数にオプションハッシュを取ります。オプションハッシュの`:to`キーに値を与えることによって、名前付きルートを定義することができます。

早速`config/routes.rb`を編集し、名前付きルートを定義しましょう。例えば、Helpページに対する記述は、以下のように変換します。

```diff:config/routes.rb（抜粋）
- get 'static_pages/help'
+ get '/help', to: 'static_pages#help'
```

Helpページに対して名前付きルートを定義したところで、`rails console`から、`help_path`メソッドや`help_url`メソッドを使ってみましょう。

```
>> app.help_path
=> "/help"
>> app.help_url 
=> "http://www.example.com/help"
```

`help_path`メソッドや`help_url`メソッドが使えるようになっていますね。

逆に、名前付きルートを定義していないページに対して、`_path`や`_url`メソッドを呼び出すことはできません。

```
>> app.about_path
...略
NoMethodError (undefined method `about_path' ...略)
```

現時点でAboutページに対しては名前付きルートを定義していないので、このようなエラーになるのですね。

最終的に、`config/routes.rb`は以下のように書き換えます。

```diff:config/routes.rb
  Rails.application.routes.draw do
    root 'static_pages#home'
-   get  'static_pages/home'
-   get  'static_pages/help'
-   get  'static_pages/about'
-   get  'static_pages/contact'
+   get  '/help',    to: 'static_pages#help'
+   get  '/about',   to: 'static_pages#about'
+   get  '/contact', to: 'static_pages#contact'
  end
```

`rails console`から、再び`about_path`メソッドを呼び出してみましょう。

```
>> app.about_path
=> "/about"
```

今度は無事呼び出すことができました。

## テストの修正

現状で`rails test`を実施すると、テストは失敗します。

```
# rails test
Running via Spring preloader in process 974
...略

ERROR["test_should_get_help", StaticPagesControllerTest, 0.26505280000856146]
 test_should_get_help#StaticPagesControllerTest (0.27s)
NameError:         NameError: undefined local variable or method `static_pages_help_url' ...略

ERROR["test_should_get_home", StaticPagesControllerTest, 0.33508309998433106]
 test_should_get_home#StaticPagesControllerTest (0.34s)
NameError:         NameError: undefined local variable or method `static_pages_home_url' ...略

ERROR["test_should_get_about", StaticPagesControllerTest, 0.39137299999129027]
 test_should_get_about#StaticPagesControllerTest (0.39s)
NameError:         NameError: undefined local variable or method `static_pages_about_url' ...略

ERROR["test_should_get_contact", StaticPagesControllerTest, 0.4491715999902226]
 test_should_get_contact#StaticPagesControllerTest (0.45s)
NameError:         NameError: undefined local variable or method `static_pages_contact_url' ...略
  4/4: [=============================================================================================================================================================] 100% Time: 00:00:00, Time: 00:00:00

Finished in 0.50959s
4 tests, 0 assertions, 0 failures, 4 errors, 0 skips
```

「`static_pages_about_url`等の名前が参照できない」というエラーですね。これらの名前は、例えば「`about_path`」等に置き換えたので、テストも相応に書き直す必要があります。

```diff:test/controllers/static_pages_controller_test.rb
  require 'test_helper'

  class StaticPagesControllerTest < ActionDispatch::IntegrationTest

    def setup
      @base_title = "Ruby on Rails Tutorial Sample App"
    end

    test "should get root" do
      get root_path
      assert_response :success
    end

    test "should get home" do
-     get static_pages_home_url
+     get root_path
      assert_response :success
      assert_select "title", "Home | #{@base_title}"
    end

    test "should get help" do
-     get static_pages_help_url
+     get help_path
      assert_response :success
      assert_select "title", "Help | #{@base_title}"
    end

    test "should get about" do
-     get static_pages_about_url
+     get about_path
      assert_response :success
      assert_select "title", "About | #{@base_title}"
    end

    test "should get contact" do
-     get static_pages_contact_url
+     get contact_path
      assert_response :success
      assert_select "title", "Contact | #{@base_title}"
    end

  end
```

以上の修正が完了すれば、テストは再び通ります。

```
# rails test
...略

  5/5: [=============================================================================================================================================================] 100% Time: 00:00:01, Time: 00:00:01

Finished in 1.31410s
5 tests, 9 assertions, 0 failures, 0 errors, 0 skips
```

# 演習 - 名前付きルートを変更してみる

## 1. 実は名前付きルートは、as:オプションを使って変更することができます。[有名なFar Sideの漫画](https://www.google.com/search?q=far+side+helf)に倣って、Helpページの名前付きルートを`helf`に変更してみてください ([リスト 5.29](https://railstutorial.jp/chapters/filling_in_the_layout?version=5.1#code-helf))。

```diff:config/routes.rb
  Rails.application.routes.draw do
    root 'static_pages#home'
-   get '/help', to: 'static_pages#help'
+   get '/help', to: 'static_pages#help', as: 'helf'
    get '/about', to: 'static_pages#about'
    get '/contact', to: 'static_pages#contact'
  end
```

## 2. 先ほどの変更により、テストが`red`になっていることを確認してください。[リスト 5.28](https://railstutorial.jp/chapters/filling_in_the_layout?version=5.1#code-static_page_routes_test)を参考にルーティングを更新して、テストを`green`にして見てください。

1.が終了した時点で、一旦テストを実行してみます。

```
# rails test
...略

ERROR["test_should_get_help", StaticPagesControllerTest, 1.884794099983992]
 test_should_get_help#StaticPagesControllerTest (1.89s)
NameError:         NameError: undefined local variable or method `help_path' for ...略

  5/5: [=============================================================================================================================================================] 100% Time: 00:00:02, Time: 00:00:02

Finished in 2.07678s
5 tests, 7 assertions, 0 failures, 1 errors, 0 skips
```

確かに`test_should_get_help`のところでテストが失敗していますね。

`rails console`で、`app.help_path`メソッドと`app.helf_path`メソッドの存在を確かめてみましょう。

```
>> app.help_path
NoMethodError (undefined method `help_path' for #<ActionDispatch::Integration::Session:0x000055f201d2df40>)\

>> app.helf_path
=> "/help"
```

`app.help_path`メソッドが存在しない一方、`app.helf_path`メソッドが存在します。

この場合、`test_should_get_help`のテストを通すためには、`test/controllers/static_pages_controller_test.rb`に以下の変更を行う必要があります。

```diff:test/controllers/static_pages_controller_test.rb（抜粋）
    test "should get help" do
-     get help_path
+     get helf_path
      assert_response :success
      assert_select "title", "Help | #{@base_title}"
    end
```

以上の変更を保存した上で改めて`rails test`を実行します。

```
# rails test
...略

  5/5: [=============================================================================================================================================================] 100% Time: 00:00:02, Time: 00:00:02

Finished in 2.15824s
5 tests, 9 assertions, 0 failures, 0 errors, 0 skips
```

今度はテストが通りました。

## 3. エディタのUndo機能を使って、今回の演習で行った変更を元に戻して見てください。

全体としては、以下2つの内容の変更となります。

```diff:config/routes.rb
  Rails.application.routes.draw do
    root 'static_pages#home'
-   get '/help', to: 'static_pages#help', as: 'helf'
+   get '/help', to: 'static_pages#help'
    get '/about', to: 'static_pages#about'
    get '/contact', to: 'static_pages#contact'
  end
```

```diff:test/controllers/static_pages_controller_test.rb（抜粋）
    test "should get help" do
-     get helf_path
+     get help_path
      assert_response :success
      assert_select "title", "Help | #{@base_title}"
    end
```

以上の変更を保存した上で改めて`rails test`を実行します。

```
# rails test
...略

  5/5: [=============================================================================================================================================================] 100% Time: 00:00:01, Time: 00:00:01

Finished in 1.86960s
5 tests, 9 assertions, 0 failures, 0 errors, 0 skips
```

無事テストが通りました。これで心置きなく次の学習にかかれます。

## 余談

```ruby:
get '/help', to: 'static_pages#help', as: 'helf'
```

以上のように書くべきところを、誤って以下のように書いてしまいました。

```ruby:
get '/help', to: 'static_pages#help', as: helf
```

これでどうなったかといいますと…

```
# rails test
/var/www/sample_app/config/routes.rb:3:in `block in <top (required)>': undefined local variable or method `helf' for #<ActionDispatch::Routing::Mapper:0x000055bb8e302880> (NameError)
...略

# rails console
/var/www/sample_app/config/routes.rb:3:in `block in <top (required)>': undefined local variable or method `helf' for #<ActionDispatch::Routing::Mapper:0x0000563606493238> (NameError)
...略
```

`rails test`も`rails console`もできなくなってしまいました。「未定義の変数名を使ってしまった」というエラーですね。

# 名前付きルート

名前付きルートを定義したことにより、レイアウト中で名前付きルートを使えるようになりました。具体的には、「`link_to`メソッドの第2引数に名前付きルートを使えるようになった」というのが大きな変化です。早速headerパーシャルとfooterパーシャルにある`link_to`メソッドの記述を変更していきましょう。

なお、headerパーシャルでは、Web共通の慣習に従って、ロゴにもHomeページへのリンクを追加しています。

```diff:app/views/layouts/_header.html.erb
  <header class="navbar navbar-fixed-top navbar-inverse">
    <div class="container">
-     <%= link_to "sample app", '#', id: "logo" %>
+     <%= link_to "sample app",  root_path, id: "logo" %>
      <nav>
        <ul class="nav navbar-nav navbar-right">
-         <li><%= link_to "Home",   '#' %></li>
-         <li><%= link_to "Help",   '#' %></li>
+         <li><%= link_to "Home",    root_path %></li>
+         <li><%= link_to "Help",    help_path %></li>
          <li><%= link_to "Log in", '#' %></li>
        </ul>
      </nav>
    </div>
  </header>
```

```diff:app/views/layouts/_footer.html.erb
  <footer class="footer">
    <small>
      The <a href="https://railstutorial.jp/">Ruby on Rails Tutorial</a>
      by <a href="http://www.michaelhartl.com/">Michael Hartl</a>
    </small>
    <nav>
      <ul>
-       <li><%= link_to "About",   '#' %></li>
-       <li><%= link_to "Contact", '#' %></li>
+       <li><%= link_to "About",    about_path %></li>
+       <li><%= link_to "Contact",  contact_path %></li>
        <li><a href="http://news.railstutorial.org/">News</a></li>
      </ul>
    </nav>
  </footer>
```

例えば、`/about`ではAboutページが表示されます。

<img width="1164" alt="スクリーンショット 2019-09-26 20.38.07.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/323778/e8228c99-096d-2413-0968-4f6fedb04787.png">

このときのHTTPリクエストとそれに対する`rails server`の反応は以下のとおりです。

```
Started GET "/about" for 172.17.0.1 at 2019-09-26 11:37:03 +0000
Cannot render console from 172.17.0.1! Allowed networks: 127.0.0.1, ::1, 127.0.0.0/127.255.255.255
Processing by StaticPagesController#about as HTML
  Rendering static_pages/about.html.erb within layouts/application
  Rendered static_pages/about.html.erb within layouts/application (0.8ms)
  Rendered layouts/_rails_default.erb (140.5ms)
  Rendered layouts/_shim.html.erb (0.3ms)
  Rendered layouts/_header.html.erb (0.7ms)
  Rendered layouts/_footer.html.erb (0.5ms)
Completed 200 OK in 349ms (Views: 307.2ms)
```

# 演習 - 名前付きルート

## 1. [リスト 5.29](https://railstutorial.jp/chapters/filling_in_the_layout?version=5.1#code-helf)のように`helf`ルーティングを作成し、レイアウトのリンクを更新してみてください。

```diff:config/routes.rb
  Rails.application.routes.draw do
    root 'static_pages#home'
-   get '/help', to: 'static_pages#help'
+   get '/help', to: 'static_pages#help', as: 'helf'
    get '/about', to: 'static_pages#about'
    get '/contact', to: 'static_pages#contact'
  end
```

```diff:app/views/layouts/_header.html.erb
  <header class="navbar navbar-fixed-top navbar-inverse">
    <div class="container">
      <%= link_to "sample app",  root_path, id: "logo" %>
      <nav>
        <ul class="nav navbar-nav navbar-right">
          <li><%= link_to "Home",    root_path %></li>
-         <li><%= link_to "Help",    help_path %></li>
+         <li><%= link_to "Help",    helf_path %></li>
          <li><%= link_to "Log in", '#' %></li>
        </ul>
      </nav>
    </div>
  </header>
```

この変更を加えた後、`rails console`における`app.help_path`メソッドと`app.helf_path`メソッドの存在確認の結果は以下の通りになります。

```
>> app.help_path
NoMethodError (undefined method `help_path' for #<ActionDispatch::Integration::Session:0x0000561721e38dc8>)
>> app.helf_path
=> "/help"
```

一方、`rails server`の結果は以下の通りになります。

```
Started GET "/help" for 172.17.0.1 at 2019-09-26 11:44:11 +0000
Cannot render console from 172.17.0.1! Allowed networks: 127.0.0.1, ::1, 127.0.0.0/127.255.255.255
Processing by StaticPagesController#help as HTML
  Rendering static_pages/help.html.erb within layouts/application
  Rendered static_pages/help.html.erb within layouts/application (0.5ms)
  Rendered layouts/_rails_default.erb (194.1ms)
  Rendered layouts/_shim.html.erb (0.4ms)
  Rendered layouts/_header.html.erb (0.6ms)
  Rendered layouts/_footer.html.erb (1.0ms)
Completed 200 OK in 376ms (Views: 342.8ms)
```

名前付きルートの名前を変えても、エンドポイントが`/help`のまま変わっていないことは重要です。`config/routes.rb`において、`get`ルールの第1引数を変えなければ、エンドポイントは変わらないのです。

## 2. 前回の演習と同様に、エディタのUndo機能を使ってこの演習で行った変更を元に戻してみてください。

```diff:config/routes.rb
  Rails.application.routes.draw do
    root 'static_pages#home'
-   get '/help', to: 'static_pages#help', as: 'helf'
+   get '/help', to: 'static_pages#help'
    get '/about', to: 'static_pages#about'
    get '/contact', to: 'static_pages#contact'
  end
```

```diff:app/views/layouts/_header.html.erb
  <header class="navbar navbar-fixed-top navbar-inverse">
    <div class="container">
      <%= link_to "sample app",  root_path, id: "logo" %>
      <nav>
        <ul class="nav navbar-nav navbar-right">
          <li><%= link_to "Home",    root_path %></li>
-         <li><%= link_to "Help",    helf_path %></li>
+         <li><%= link_to "Help",    help_path %></li>
          <li><%= link_to "Log in", '#' %></li>
        </ul>
      </nav>
    </div>
  </header>
```

# リンクのテスト

初めての結合テストです。ここでは、「アプリケーションのHTML構造を調べて、レイアウトの各リンクが正しく動くかどうかをチェックする」というテストを書く方法を学習していきます。

まず、`site_layout`というテストのテンプレートを作成します。

```
# rails generate integration_test site_layout
Running via Spring preloader in process 1434
      invoke  test_unit
      create    test/integration/site_layout_test.rb
```

Railsが渡されたファイル名の末尾に`_test`という文字列を追加しているのがポイントなのだそうです。

## リンクのテストの全体像

今回のテストの全体像は以下のとおりです。

1. ルートURL（Homeページ）にGETリクエストを送る。
2. 正しいページテンプレートが描画されているか確かめる。
3. Home、Help、About、Contactの各ページへのリンクが正しく動作するか確かめる。

`test/integration/site_layout_test.rb`の全体像は以下のとおりです。

```ruby:test/integration/site_layout_test.rb
require 'test_helper'

class SiteLayoutTest < ActionDispatch::IntegrationTest

  test "layout links" do
    get root_path
    assert_template 'static_pages/home'
    assert_select "a[href=?]", root_path, count: 2
    assert_select "a[href=?]", help_path
    assert_select "a[href=?]", about_path
    assert_select "a[href=?]", contact_path
  end
end
```

## リンクのテストは何を確認するか

上記のコードでは、以下の確認が行われます。

* `root_path`へのGETリクエストの送出
* `root_path`へGETリクエストを送出して返ってきたリソースに対する以下の確認
    * `static_pages/home`というテンプレートが描画されているか
    * `root_path`が示すリソースをリンク先とする`a`要素が2つ存在するか
    * `help_path`が示すリソースをリンク先とする`a`要素が1つ存在するか
    * `about_path`が示すリソースをリンク先とする`a`要素が1つ存在するか
    * `contact_path`が示すリソースをリンク先とする`a`要素が1つ存在するか

## 実際のコードの解説

例えば、以下のコードを取り上げてみます。

```
assert_select "a[href=?]", about_path
```

当該テストコードでは、Railsは`?`を自動的に`about_path`に置換します[^assert_selectの?における特殊記号の扱い]。現時点で、`about_path`に対応するエンドポイントは`/about`なので、これにより、以下のようなHTMLコードがあるかをチェックすることになります。

[^assert_selectの?における特殊記号の扱い]: このとき、`about_path`内に特殊記号があればエスケープ処理されます。

```
<a href="/about">...</a>
```

現時点で、`static_pages/home`テンプレートが描画されたときのルートURLへのリンクは2つ存在します[^ルートURLの所在]。ルートURLが2つあるかどうかをチェックする場合は、以下のテストコードを用います。オプションハッシュで`:count`キーに対する値が`2`と定義されているのがポイントです。

```
assert_select "a[href=?]", root_path, count: 2
```

[^ルートURLの所在]: 1つはロゴに、もう1つはナビゲーションバー内にあります。

この他にも、`assert_select`には様々な機能があります。興味がありましたら、[Railsチュートリアル 表5.2](https://railstutorial.jp/chapters/filling_in_the_layout?version=5.1#table-assert_select)を参照してみてください。

## テストを実行してみる

統合テストのみを実施する場合は、Railsの開発環境で以下のコマンドを実行します。

```
# rails test :integration
```

`rails test`の部分は`rails t`でもOKですね。

```
# rails t :integration
...略

  6/6: [=============================================================================================================================================================] 100% Time: 00:00:02, Time: 00:00:02

Finished in 2.20712s
6 tests, 14 assertions, 0 failures, 0 errors, 0 skips
```

無事にテストが通りました。全体のテストはどうでしょうか。

```
# rails test
...略

  6/6: [=============================================================================================================================================================] 100% Time: 00:00:01, Time: 00:00:01

Finished in 1.81602s
6 tests, 14 assertions, 0 failures, 0 errors, 0 skips
```

全体のテストも無事通りました。

「リンクに間違った変更が加えられたら、テストですぐに気づくことができる」という仕組みが無事整備されましたね。

# 演習 - リンクのテスト

## 1. footerパーシャルの`about_path`を`contact_path`に変更してみて、テストが正しくエラーを捕まえてくれるかどうか確認してみてください。

```diff:app/views/layouts/_footer.html.erb
  <footer class="footer">
    <small>
      The <a href="https://railstutorial.jp/">Ruby on Rails Tutorial</a>
      by <a href="http://www.michaelhartl.com/">Michael Hartl</a>
    </small>
    <nav>
      <ul>
-       <li><%= link_to "About",    about_path %></li>
+       <li><%= link_to "About",    contact_path %></li>
        <li><%= link_to "Contact",  contact_path %></li>
        <li><a href="http://news.railstutorial.org/">News</a></li>
      </ul>
    </nav>
  </footer>
```

上記変更をした場合、テストの結果はどうなるでしょうか…という話ですね。テストは通らないはずです。

```
# rails t :integration
...略

 FAIL["test_layout_links", SiteLayoutTest, 1.887058500025887]
 test_layout_links#SiteLayoutTest (1.89s)
        Expected at least 1 element matching "a[href="/about"]", found 0..
        Expected 0 to be >= 1.
        test/integration/site_layout_test.rb:10:in `block in <class:SiteLayoutTest>'

  6/6: [=============================================================================================================================================================] 100% Time: 00:00:01, Time: 00:00:01

Finished in 1.89008s
6 tests, 13 assertions, 1 failures, 0 errors, 0 skips
```

めでたく（？）テストは通りませんでした。「`a[href="/about"]`にマッチする要素が（HTMLコード中に）見つからない」という不適合を報告してきています。

…この状態で先には進めないので、`app/views/layouts/_footer.html.erb`に対する先ほどの変更はもとに戻しておきましょう。

## 2.1. [リスト 5.35](https://railstutorial.jp/chapters/filling_in_the_layout?version=5.1#code-test_helper_application_helper)で示すように、Applicationヘルパーで使っている`full_title`ヘルパーを、test環境でも使えるようにすると便利です。こうしておくと、[リスト 5.36](https://railstutorial.jp/chapters/filling_in_the_layout?version=5.1#code-test_helper_application_helper)のようなコードを使って、正しいタイトルをテストすることができます。

```diff:test/test_helper.rb
  ENV['RAILS_ENV'] ||= 'test'
  ...略

  class ActiveSupport::TestCase
    # ...略
    fixtures :all
+   include ApplicationHelper
    # ...略
  end
```

```diff:test/integration/site_layout_test.rb
  require 'test_helper'

  class SiteLayoutTest < ActionDispatch::IntegrationTest

    test "layout links" do
      get root_path
      assert_template 'static_pages/home'
      assert_select "a[href=?]", root_path, count: 2
      assert_select "a[href=?]", help_path
      assert_select "a[href=?]", about_path
      assert_select "a[href=?]", contact_path
+     get contact_path
+     assert_select "title", full_title("Contact")
    end
  end
```
現時点で、テストは問題なく通ります。

```
# rails test
...略

  6/6: [=============================================================================================================================================================] 100% Time: 00:00:01, Time: 00:00:01

Finished in 1.68342s
6 tests, 15 assertions, 0 failures, 0 errors, 0 skips
```

## 2.2. ただし、これは完璧なテストではありません。例えばベースタイトルに「Ruby on Rails Tutoial」といった誤字があったとしても、このテストでは発見することができないでしょう。

```diff:app/helpers/application_helper.rb
  module ApplicationHelper

    # ページごとの完全なタイトルを返します。
    def full_title(page_title = '')
-     base_title = "Ruby on Rails Tutorial Sample App"
+     base_title = "Ruby on Rails Tutoial Sample App"
      if page_title.empty?
        base_title
      else
        page_title + " | " + base_title
      end
    end
  end
```

以下のように、`site_layout_test`は通ってしまいます。

```
# rails t test/integration/site_layout_test.rb
...略

  1/1: [=============================================================================================================================================================] 100% Time: 00:00:01, Time: 00:00:01

Finished in 1.88365s
1 tests, 6 assertions, 0 failures, 0 errors, 0 skips
```

## 2.3. この問題を解決するためには、`full_title`ヘルパーに対するテストを書く必要があります。そこで、Applicationヘルパーをテストするファイルを作成し、[リスト 5.37](https://railstutorial.jp/chapters/filling_in_the_layout?version=5.1#code-test_helper_application_helper)の`FILL_IN`の部分を適切なコードに置き換えてみてください。

```ruby:test/helpers/application_helper_test.rb
require 'test_helper'

class ApplicationHelperTest < ActionView::TestCase
  test "full title helper" do
    assert_equal full_title,         "Ruby on Rails Tutorial Sample App"
    assert_equal full_title("Help"), "Help | Ruby on Rails Tutorial Sample App"
  end
end
```

早速`application_helper_test.rb`に対して`rails test`を実行してみます。

```
# rails test test/helpers/application_helper_test.rb
...略

 FAIL["test_full_title_helper", ApplicationHelperTest, 0.04009939997922629]
 test_full_title_helper#ApplicationHelperTest (0.04s)
        --- expected
        +++ actual
        @@ -1 +1 @@
        -"Ruby on Rails Tutoial Sample App"
        +"Ruby on Rails Tutorial Sample App"
        test/helpers/application_helper_test.rb:5:in `block in <class:ApplicationHelperTest>'

  1/1: [=============================================================================================================================================================] 100% Time: 00:00:00, Time: 00:00:00

Finished in 0.04308s
1 tests, 1 assertions, 1 failures, 0 errors, 0 skips
```

見事（？）テストで不適合が出ました。

## 2.余談. `base_title`を正しく直したときに、テストが通るかを確認してみます。

`base_title`の中身を"Ruby on Rails Tutorial Sample App"に直してみます。

```diff:app/helpers/application_helper.rb
  module ApplicationHelper

    # ページごとの完全なタイトルを返します。
    def full_title(page_title = '')
-     base_title = "Ruby on Rails Tutoial Sample App"
+     base_title = "Ruby on Rails Tutorial Sample App"
      if page_title.empty?
        base_title
      else
        page_title + " | " + base_title
      end
    end
  end
```

再び`application_helper_test.rb`に対して`rails test`を実行してみます。

```
# rails test test/helpers/application_helper_test.rb
...略

  1/1: [=============================================================================================================================================================] 100% Time: 00:00:00, Time: 00:00:00

Finished in 0.02249s
1 tests, 2 assertions, 0 failures, 0 errors, 0 skips
```

今度こそテストが通りました。