#author("2018-07-03T15:44:47+09:00","default:wikiwriter","wikiwriter")
#author("2018-07-04T15:39:08+09:00","default:wikiwriter","wikiwriter")
&tag(Railsテスティングガイド);
*目次 [#b63ae818]
#contents
*関連ページ [#l728a547]
-[[Rails テスティングガイド | Rails ガイド:https://railsguides.jp/testing.html]]…日本語版サイト
-[[Testing Rails Applications — Ruby on Rails Guides:http://guides.rubyonrails.org/testing.html]]…公式サイト。日本語版は情報が古いのでこちらを参考にすること。

*参考情報 [#z8d31c99]


* 1 Railsアプリケーションでテストを作成しなければならない理由 [#m7e16995]

* 2 テストを導入する [#xe4e9d82]

** 2.1 Rails Sets up for Testing from the Word Go [#j52f7a32]
-Railsプロジェクトを作成すると以下のようなフォルダが作成される
#pre{{
$ ls -F test
controllers/           helpers/               mailers/               system/                test_helper.rb
fixtures/              integration/           models/                application_system_test_case.rb
}}


** 2.2 The Test Environment [#v67cb360]
-testはtest環境で実施される。
-config/database.ymlでテスト用のデータベースが設定できる。


** 2.3 Rails meets Minitest [#ye73ffcd]
-モデルを生成するとテストが自動的に作成される。
#pre{{

$ bin/rails generate model article title:string body:text
...
create  app/models/article.rb
create  test/models/article_test.rb
create  test/fixtures/articles.yml
...
}}

-test/models/article_test.rbは以下のような内容となる。
#pre{{

require 'test_helper'
 
class ArticleTest < ActiveSupport::TestCase
  # test "the truth" do
  #   assert true
  # end
end
}}
-テストメソッド名は以下のどちらでもよい。
#pre{{

test "the truth" do
  assert true
end


def test_the_truth
  assert true
end
}}
-失敗テスト。articleのtitleが設定されていないので以下のテストは失敗する。
#pre{{
test "should not save article without title" do
  article = Article.new
  assert_not article.save
end
}}
-実行。本来失敗してほしいのだが成功してしまう。
#pre{{
$ bin/rails test test/models/article_test.rb
}}
-articleに検証メソッドを追加すると成功する。
#pre{{
class Article < ApplicationRecord
  validates :title, presence: true
end
}}

** 2.4 Available Assertions [#fbdc2b74]

**2.5 Rails Specific Assertions [#se6208f2]

**2.6 A Brief Note About Test Cases [#ib167b69]


**2.7 The Rails Test Runner [#seb79b61]
-bin/rails testコマンドで全てのテストを実行できる。
-特定のテストやメソッドを実行する場合。
#pre{{
$ bin/rails test test/models/article_test.rb
$ bin/rails test test/models/article_test.rb -n test_the_truth
$ bin/rails test test/models/article_test.rb:6 #行番号の指定
$ bin/rails test test/controllers #ディレクトリ
}}

*3 The Test Database [#a221eb97]
-テスト用のデータベースが使われる。
-config/database.ymlで定義。

**3.1 Maintaining the test database schema [#cbfed533]
-テストを実行するためには現在のデータがデータベースに反映されていることが必要。
-テストヘルパーは保留中のmigrationsが存在しないあかどうかをチェックする。

**3.2 The Low-Down on Fixtures [#q1f10dde]
-Railsではフィクスチャと呼ばれる仕組みを利用してテストデータを準備っする。
-test/fixturesディレクトリ以下に存在しYAMLで定義。
#pre{{
# lo & behold! I am a YAML comment!
david:
  name: David Heinemeier Hansson
  birthday: 1979-10-15
  profession: Systems development
 
steve:
  name: Steve Ross Kellock
  birthday: 1974-09-27
  profession: guy with keyboard
}}
-関連の定義。
#pre{{

# In fixtures/categories.yml
about:
  name: About
 
# In fixtures/articles.yml
first:
  title: Welcome to Rails!
  body: Hello world!
  category: about
}}
-fixturesのYAMLではERBを使用することもできる。
-テストの中で以下のように使用可能。
#pre{{

# this will return the User object for the fixture named david
users(:david)
 
# this will return the property for david called id
users(:david).id
 
# one can also access methods available on the User class
david = users(:david)
david.call(david.partner)
}}

* 4 Model Testing [#u1bb93a0]
-モデルテストはモデルのテストを実行するもの。
-test/modelsディレクトリに作成する。
#pre{{
$ bin/rails generate test_unit:model article title:string body:text
create  test/models/article_test.rb
create  test/fixtures/articles.yml
}}


* 5 System Testing [#ubac64da]
-システムテストは、アプリケーションとシステムの相互作用をテストする。
-リアルorヘッドレスブラウザを使用してテスト実行。
-Capybaraを利用する。
-railsではtest/systemディレクトリ以下に作成する。
#pre{{
$ bin/rails generate system_test users
}}
-以下の内容
#pre{{

require "application_system_test_case"
 
class UsersTest < ApplicationSystemTestCase
  # test "visiting the index" do
  #   visit users_url
  #
  #   assert_selector "h1", text: "Users"
  # end
end
}}
-デフォルトでシステムテストはSeleniumドライバで実行される。

** 5.1 Changing the default settings [#e0f1f73e]
-railsのシステムテストの設定は簡単に変更できる。
-例えばSeleniumからPoltergeistに変更したい場合Gemfileにpoltergeistを追加したあとで、テストファイルを以下のように変更する。
#pre{{

require "test_helper"
require "capybara/poltergeist"
 
class ApplicationSystemTestCase < ActionDispatch::SystemTestCase
  driven_by :poltergeist
end

class ApplicationSystemTestCase < ActionDispatch::SystemTestCase
  driven_by :selenium, using: :firefox
end

class ApplicationSystemTestCase < ActionDispatch::SystemTestCase
  driven_by :selenium, using: :headless_chrome
end
}}

**5.2 Screenshot Helper [#x1e3cf99]
-ScreenshotHelperはスクリーンショットヘルパーを取得するのを助ける。
-take_screenshotとtake_failed_screenshotが存在。

**5.3 Implementing a system test [#u21cd85c]
-システムテストのスケルトンを生成する。
 $ bin/rails generate system_test articles
-テストファイルの中身。
#pre{{

require "application_system_test_case"
 
class ArticlesTest < ApplicationSystemTestCase
  test "viewing the index" do
    visit articles_path
    assert_selector "h1", text: "Articles"
  end
end
}}
-テストの実行。デフォルトでrails testではシステムテストを実行しないのに注意。
 bin/rails test:system

★chromedriverが存在しないと実行できない。macOSの場合「brew cask install chromedriver」でインストール可能。

-新しい記事を作成するテスト。
#pre{{

test "creating an article" do
  visit articles_path
 
  click_on "New Article"
 
  fill_in "Title", with: "Creating an Article"
  fill_in "Body", with: "Created this article successfully!"
 
  click_on "Create Article"
 
  assert_text "Creating an Article"
end
}}
-最初にarticles_pathに移動して、"New Article"ボタンをクリック。そしてタイトルとボディを埋めて保存する。
-システムテストはユーザーが利用しているソフトをシステムをテストする実情に最も近いテストとなる。


* 6 Integration Testing [#kb7fa84e]

-統合テストはアプリケーションのさまざまな箇所が相互作用するさまをテストする。
-アプケーション内の重要なワークフローをテストする。
-railsでは統合テストはtest/integrationディレクトリに作成される。
-以下のように作成できる。
#pre{{
$ bin/rails generate integration_test user_flows
}}
-その中身。
#pre{{

require 'test_helper'
 
class UserFlowsTest < ActionDispatch::IntegrationTest
  # test "the truth" do
  #   assert true
  # end
end
}}
-テストはActionDispatch::IntegrationTestを警鐘する。

** 6.1 Helpers Available for Integration Tests [#r6b1a798]
-ActionDispatch::IntegrationTestでは標準のテストに加え追加のヘルパーが使用できる。
--ActionDispatch::Integration::Runner
--ActionDispatch::Integration::RequestHelpers
--ActionDispatch::Integration::Session

**6.2 Implementing an integration test [#a5bd52de]
-ブログシステムに統合テストを追加する。
 $ bin/rails generate integration_test blog_flow
-
-BlogFlowTestを実装する。"/"を取得しh1タグの中身が"Welcome#index"であることを確認。なおこのテストを実行するにはwelcome_controllerを先に作っておかないと行けない(後述)。
#pre{{

require 'test_helper'
 
class BlogFlowTest < ActionDispatch::IntegrationTest
  test "can see the welcome page" do
    get "/"
    assert_select "h1", "Welcome#index"
  end
end
}}
-welcome_controllerの作成。
 bundle exec rails generate controller Welcome index
-routes.rbの設定。
#pre{{
Rails.application.routes.draw do
  get 'welcome/index'
  root 'welcome#index'
  resources :articles
end
}}
-記事作成のテスト。
#pre{{
  test "can create an article" do
    get "/articles/new"
    assert_response :success

    post "/articles",
         params: { article: { title: "can create", body: "article successfully." } }
    assert_response :redirect
    follow_redirect!
    assert_response :success
    assert_select "p", "Title:\n  can create"

#    assert_select "p" do |element|
#      # 該当するNokogiri::XML::NodeSetがかえってくる(この場合3つの"p"要素のNokogiri::XML::Elementを含む)
#      # textでタグを除いた状態のテキストが取得できる。これとの比較になる。
#      p element.text
#    end
  end
}}

* 7 Functional Tests for Your Controllers [#fa363cc5]
-Railsではコントローラーの個別の(?)メソッドをテストするにはfunctional test(機能テスト)を使用する。

**7.1  What to include in your Functional Tests [#sb6d18bf]
-以下の内容を機能テストに記述する
--リクエストが成功したか
--リダイレクトが正しいか。
--ユーザー認証が成功したか。
--正しいオブジェクトがtemplateに埋め込まれたか。
--適切なメッセージがビューに表示されたか。
-機能テストを作成するにはscaffoldを使用するのが簡単。test/controllers/articles_controller_test.rbがそれ。
 $ bin/rails generate scaffold_controller article title:string 
-すでにコントローラーを作成済みで、7つのデフォルトアクションに対するテストを作成したい場合以下のように実行する。
 $ bin/rails generate test_unit:scaffold article
-テストの一つ。
#pre{{
# articles_controller_test.rb
class ArticlesControllerTest < ActionDispatch::IntegrationTest
  test "should get index" do
    get articles_url
    assert_response :success
  end
end
}}
-getメソッドwebリクエストを送信し、@responseで結果を受ける。以下のパラメータを受け取る。
--URI(例えばarticles_url)。
--params
--headers
--env
--xhr
--as
-showアクションでリファラを設定する場合。
#pre{{
get article_url, params: { id: 12 }, headers: { "HTTP_REFERER" => "http://example.com/home" }
}}
-updateアクションをAjaxリクエストする場合。
#pre{{
patch article_url, params: { id: 12 }, xhr: true
}}
-記事作成メソッドのテスト(この前にテストを実行すると、新たに追加したvalidationにより失敗するとあるがデフォルト状態でも作成できそうだが…)。
#pre{{
test "should create article" do
  assert_difference('Article.count') do
    post articles_url, params: { article: { body: 'Rails is awesome!', title: 'Hello Rails' } }
  end
 
  assert_redirected_to article_path(Article.last)
end
}}



**2.2 Railsを即座にテスト用に設定する [#qb174f1a]
-プロジェクトを作成すると、以下のフォルダが自動的に作成される。
#pre{{

$ ls -F test
controllers/    helpers/        mailers/        test_helper.rb
fixtures/       integration/    models/
}}

**2.3 フィクスチャのしくみ [#e38e1008]
-フィクスチャ=サンプルデータ。
-YAMLで記述。test/fixtures以下。
#pre{{
david:
  name: David Heinemeier Hansson
  birthday: 1979-10-15
  profession: Systems development
 
steve:
  name: Steve Ross Kellock
  birthday: 1974-09-27
  profession: guy with keyboard
}}

-YAMLはERBで処理される。
-フィクスチャはActive Recordオブジェクト。
#pre{{
# davidという名前のフィクスチャに対応するUserオブジェクトを返す
users(:david)
 
# idで呼び出されたdavidのプロパティを返す
users(:david).id
 
# Userクラスで利用可能なメソッドにアクセスすることもできる
email(david.girlfriend.email, david.location_tonight)

}}

-フィクスチャとして容易したymlファイルはテストの実行前にテストDBにロードされる。
*3 モデルに対する単体テスト [#c65fc1b9]
-articleモデルを生成。
#pre{{
$ bin/rails generate scaffold article title:string body:text
}}
-以下のようなテストクラスが生成される。
#pre{{

require 'test_helper'
 
class ArticleTest < ActiveSupport::TestCase
  # test "the truth" do
  #   assert true
  # end
end
}}

**3.1 テストデータベースのスキーマを管理する [#re44c079]


**3.2 テストを実行する。 [#pfc34540]
-以下のように実行できる。
#pre{{
 bin/rails test test/models/article_test.rb
}}
-特定のメソッドdけをテスト。
#pre{{
 bin/rails test test/models/article_test.rb test_the_truth
}}
-失敗のテスト。article.rbを変更。
#pre{{
class Article < ActiveRecord::Base
  validates :title, presence: true
end
}}
-テスト追加。
#pre{{
class ArticleTest < ActiveSupport::TestCase
  test "the truth" do
    assert true
  end

  test "should not save article without title" do
    article = Article.new
    assert_not article.save, "Saved the article without a title"
  end
end

}}

**3.3 単体テストに含めるべき項目 [#j3ce5ae7]

**3.4 利用可能なアサーション [#g83e6cdb]

**3.5 Rails固有のアサーション [#y9342428]


*4 コントローラの機能テスト [#t3c058fd]
-1つのコントローラーに含まれる複数のアクションをテスト。
-機能テスト=functional test。


**4.1 機能テストに含める項目 [#y660cd93]
-以下の項目を含める
--Webリクエストが成功したか
--正しいページにリダイレクトされたか
--ユーザー認証が成功したか
--レスポンスのテンプレートに正しいオブジェクトが保存されたか
--ビューに表示されたメッセージは適切か
-test/controllers/articles_controller_test.rb
#pre{{
  test "should get new" do
    get new_article_url
    assert_response :success
  end
}}
-showアクションに対するテストの場合。
#pre{{
  test "should show article" do
    get article_url(@article)
    assert_response :success
  end
}}



トップ   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS