読者です 読者をやめる 読者になる 読者になる

ぞえの技術めも

Ruby on Rails勉強中

【89日目】【1日20分のRailsチュートリアル】【第8章】2つの目立たないバグに対するテストを作成する

Ruby on Railsチュートリアル(第3版)

今日は「8.4.4 2つの目立たないバグ」のテストを書くところから。

8.4.4 2つの目立たないバグ

テスト駆動開発は、この種の地味なバグ修正にはうってつけです。そこで、2つのエラーをキャッチするテストを書くことにします。

こんなややしこしそうなバグもテスト書けるのか。。。

ログイン→ログアウトのテストに下記コードを追加。

test/integration/users_login_test.rb

    # 2番目のウィンドウでログアウトをクリックするユーザーをシミュレートする
    delete logout_path

ログアウトした後に再度ログアウトしようとするコード、ってことかな…?

$ bundle exec rake test
24 tests, 58 assertions, 0 failures, 1 errors, 0 skips

テストはもちろんNGです。

リスト8.42のアプリケーションコードでは、logged_in?がtrueの場合に限ってlog_outを呼び出すように変更しました。

destroyアクションを下記のように変更。

app/controllers/sessions_controller.rb

  def destroy
    log_out if logged_in?
    redirect_to root_url
  end
$ bundle exec rake test
24 tests, 61 assertions, 0 failures, 0 errors, 0 skips

テスト成功しました。

2番目の問題についてですが、統合テストで2種類のブラウザをシミュレートするのは正直かなり困難です。その代わり、同じ問題をUserモデルで直接テストするだけなら簡単に行えます。

ほぅほぅ。

Userモデルのテストとして下記を追加。

test/models/user_test.rb

  test "authenticated? should return false for a user with nil digest" do
    assert_not @user.authenticated?('')
  end

テストはNGになります。

$ bundle exec rake test
ERROR["test_authenticated?_should_return_false_for_a_user_with_nil_digest", UserTest, 2016-11-22 15:03:43 +0000]
 test_authenticated?_should_return_false_for_a_user_with_nil_digest#UserTest (1479827023.00s)
BCrypt::Errors::InvalidHash:         BCrypt::Errors::InvalidHash: invalid hash
25 tests, 61 assertions, 0 failures, 1 errors, 0 skips

エラーを修正してテストがGREENになるようにするには、記憶ダイジェストがnilの場合にfalseを返すようにすればよいのです (リスト8.45)。

authenticated?メソッドに記憶トークンがnilの場合はreturnするコードを追加。

app/models/user.rb

  # 渡されたトークンがダイジェストと一致したらtrueを返す
  def authenticated?(remember_token)
    return false if remember_digest.nil?
    BCrypt::Password.new(remember_digest).is_password?(remember_token)
  end

これでテストが通るようになり、2つの目立たないバグも解消されました。

$ bundle exec rake test
25 tests, 62 assertions, 0 failures, 0 errors, 0 skips

テストにも色んなアプローチがあるんだな。。。

今日の作業時間は【22分】

次は「8.4.5 “Remember me” チェックボックス」から。