rails5 テストコードどのファイルに書けば良いか問題


夏季休業に入り、いよいよコーディングだけの生活に入りました。railsのテスト駆動開発ができるよう
になりたいと思ってまして、いざ書こうと思ったときにどのファイルにどれを書けば良いんだっけ。。
となりました。(テスト明け故にだいぶ抜けてる..orz)
特にintegrationファイル(統合テスト)では、何を書いたら良いのかと、思いまして書かせて頂きました。

参照は→https://railstutorial.jp/chapters/basic_login?version=5.1#cha-basic_login

ちなみにテストコードを書くメリットについては下記の記事がわかりやすいので、ご参照ください。
→https://qiita.com/inabe49/items/72250d9e8d5b869a91a0
#viewに関するテストコード

/test/controller/static_pages_controller_test.rb

```
class StaticPagesControllerTest < ActionDispatch::IntegrationTest

test "should get home" do
 get root_path
 assert_responce :success
end

test "should get help" do
 get help_path
 assert_responce :success
end

test "should get about" do
 get about_path
 assert_responce :success
end

test "should get contact" do
 get contact_path
 assert_resoponce :success do
end

end

```
上記のテストコードは、viewのStaticPagesディレクトリにある、htmlファイル(erb)へのgetリクエスト
に対して、テンプレートのレスポンスが正しく返って来ているかどうかについて、テストしています。
このテストに対してエラーが出た場合は、大体の場合、routingが通ってない問題を疑うと良いと思います。
（routes.rbで設定した、URLに対してgetリクエストしているから。)
このようなroutingとviewが正しく動作するかどうかのテストは、test/controller/~でテストコードを
書くと良いのではないでしょうか。

#パラメーターの送受信に関するテストコード

このようなパラメーターの送受信する際に必要なテストコードは、integraionディレクトリを生成して、テストします。今回は、ログイン機能で必要なパラメーターの送受信に関するテストコードです。

/test/integration/user_login_test.rb

```
require 'test_helper'
class UserLoginTest < ActionDispatch::IntegrationTest
 def setup
 @user=users(:michael) #test用のフェイクユーザー(fixturesのファイル名users.ymlのusers)
 end

test "test with invalid information" do
 get login_path
 assert_template "session/new"
 post login_path, params: {session:{email:"",password:""}}
 assert_template "session/new"
 get root_path
 assert flash.empty?
end
 
test "login with valid information" do
 get login_path
 assert_template "session/new"
 post login_path, params: {session:{email:@user.email,password:"password"}}
 redirected_to @user
 follow_redirect!
 assert_template "users/show"
 assert_select "a[href=?]" ,login_path,count:0"
 assert_select "a[href=?]" ,logout_path 
 assert_select "a[href=?]" ,user_path(@user)
end

test "login with valid information followed by logout" do
 get login_path
 post login_path, params:{session:{email:@user.email,password:"password"}}
 assert is_login_in?
 assert_redirected_to @user
 follow_redirected!
 assert_template "users/show"
 assert_select "a[href=?]" ,login_path,count:0
 assert_select "a[href=?]" ,logout_path
 assert_select "a[href=?]" ,user_path(@user)
 delete logout_path
 assert_not is_logged_in?
 assert_redirected_to root_path
 follow_redirect!
 assert_select "a[href=?]" ,login_path
 assert_select "a[href=?]" ,logout_path,count:0
 assert_select "a[href=?]" ,user_path(@user),count:0
 end
end
```

最初のコメントが"login with invalid information"のテストコード
では、コメント通り、非有効なパラメーターを受け取った時の挙動をテストコードで書いてます。
次の"login with valid information"のテストコードでは、有効なパラメーターを受け取った時の挙動をテストコードで書いてます。
最後の"login with valid information followed by logout"のテストコードでは、ログインからログアウトまでの挙動をテストコードで書いています。

assert_selectはその後のセレクタである、a[href=?]つまり、aタグのhref属性が存在するかどうかについて、また、オプションがcount:0というのは、href属性が0であるかどうかについて検証しています。

assert_templateはどのテンプレートに画面遷移するかについて検証しています。

integration(統合テスト)はどのような時に行うかについて調べてみたり、railstutorialを読んだが、やはりパラメーターの送受信や、その時のテンプレートの挙動をテストする時に、integrationを使うよう。。
何かintegrationファイルでの統合テストについてどういう使い方をすれば良いのかtwitterなどで教えて頂けると幸いです。

#modelに関するテストコード

/models/user.rb

```
class User < ApplicationRecord
	attr_accessor :remember_token
	before_save {self.email = email.downcase}
  validates :name, presence: true,length:{maximum: 50}

  VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i
  validates :email,presence: true,length:{maximum:255},
  format:{with:VALID_EMAIL_REGEX},uniqueness:{case_sensitive: false}
  has_secure_password
  validates :password,presence:true,length:{minimum: 6}

	def User.digest(string)
	 cost = ActiveModel::SecurePassword.min_cost ? BCrypt::Engine::MIN_COST :
																								 BCrypt::Engine.cost
	 BCrypt::Password.create(string, cost: cost)
  end

	def User.new_token
		SecureRandom.urlsafe_base64
	end
	#ここでtokenを発行する事でuserモデルと紐づけることができる.

	def remember
		self.remember_token=User.new_token
		update_attribute(:remember_digest,User.digest(remember_token))
	end

	def authenticated?(remember_token)
		BCrypt::Password.new(:remember_digest).is_password?(:remember_token)
	end
 end

```

このモデルに対するテストコードは、


/test/model/user_test.rb

```
require "test_helper"

class UserTest < ActiveSupport::TestCase
 
def setup
 @user=User.new(name:"Exampleuser",email:user@example.com,password:"foobar",password_confi rmaiton:"foobar")
end
 
 test "should be valid" do
  assert @user.valid?
 end
 
 test "name should be present" do
  @user.name=""
  assert_not @user.valid?
  end
 
 test "email should be present" do
  @user.email=""
  assert_not @user.valid?
 end
 
 test "name should not be too long"
  @user.name="a"*51
  assert_not @user.valid?
 end
 
 test "email should not be too long" do
  @user.name="a"*244+"@example.com"
  assert_not @user.valid?
 end

 test "email validation should accept valid valid address" do
  invalid_address=%w[user@example,com user_at_foo.org user.name@example. foo@bar_baz.com foo@bar+baz.com]
  invalid_address.each do |valid_address|
    @user.email = valid_address
    assert_not @user.valid,"#{valid_address.inspect} should be valid"
  end
end

  test "email address should be unique" do
   duplicate_user=@user.dup
   duplicate_user.email=@user.email.upcase
   @user.save
   assert_not duplicate.valid?
  end
  
   test "password should be present (nonblank)" do
    @user.password=@user.password_confirmation="a"*6
    assert_not @user.valid?
   end
  
  test "password should have a minimum length" do
    @user.password=@user.password_confirmation="a"*5
    assert_not @user.valid?
  end
 end
```

modelのデータ検証のテストコードは、当たり前ですが、/test/model/~に書きます。
モデルデータの検証(validatesメソッドでDBに格納する際にその格納するデータが正常なデータか検証する)に対するテストコードです。
models/user.rbと見比べてみると、何のテストコードを書いているのかわかると思うので暇な方は是非。

個人的にintegraitonはどのような時に使うか知りたかったために書かせて頂きました。

書く量多すぎな。。Rspecはどうなんだろう。。

ということで、次は、Rspecについて書いていこうと思います。(もしかしたら別のことになるかもしれない。。)

twitter→https://twitter.com/FujisawaRyohei