Sochi419のブログ

プログラミング初学者です。Ruby, JavaScriptを学習中です。猫が好きです。フィヨルドブートキャンプというスクールの受講生です。

testの書き方

プログラミング初学者の私なりに、railsのtestの書き方をまとめてみました。

各テストファイルの役割

├── test・・・Rails標準の各種テスト用のコードファイルやフィクスチャ(テストデータ)などを管理する
│   ├── application_system_test_case.rb
│   ├── channels
│   │   └── application_cable
│   │       └── connection_test.rb
│   ├── controllers・・・コントローラーテスト(機能テスト)のコードファイルを保存する
│   ├── fixtures・・・テスト実行時に最初にロードされるテスト用のデータファイル(YAML形式)を保存する
│   │   ├── books.yml
│   │   ├── comments.yml
│   │   ├── files・・・画像ファイルなどのファイルデータを配置する
│   │   ├── relationships.yml
│   │   ├── reports.yml
│   │   └── users.yml
│   ├── helpers
│   ├── integration
│   ├── mailers
│   ├── models・・・モデル単体のテストのコードファイルを保存する
│   │   ├── book_test.rb
│   │   ├── comment_test.rb
│   │   ├── relationship_test.rb
│   │   ├── report_test.rb
│   │   └── user_test.rb
│   ├── system・・・UIの操作を活用したシステムテストのコードを保存する。Capybaraを使用
│   │   └── books_test.rb
│   └── test_helper.rb・・・全テストファイルにrequireすることで、共通のテスト条件として組み込まれる

基本いじるのは、下記の3つの印象。

  1. fixtures→テスト時に使用するデータファイルがある。
  2. models→モデルテスト
  3. system→システムテスト

fixturesファイルについて

  • 初期状態

scaffoldで用意された初期状態は以下のような感じ。

one:
  title: MyString
  memo: MyText

もし、テスト時に使用しないのであれば、全てコメントアウトする。 使う場合は以下のような感じにする。

  • 例 test/fixtures/users.yml
Alice:
  name: Alice
  email: alice@example.com
  encrypted_password: <%= Devise::Encryptor.digest(User, 'password') %>

上記のように定義しておけば、テストメソッドで、hoge = users(:Alice)のようにすれば呼び出せる。 ちなみに、fixturesで定義しなくても、各メソッドで定義しても使える。

hoge = User.new(email: 'foo@example.com', name: '')

メソッドが何個もあるなら、いちいち定義するのが冗長なので、fixtureにデータを書いておくのが吉。

modelテストについて

modelテストには、modelで定義したメソッドを定義する。

例えばuserモデルに以下のメソッド定義がある場合、

  • app/models/user.rb
  def name_or_email
    name.presence || email
  end

対応するuserモデルテストは以下のように書く。

  • test/models/user_test.rb
  test '#name_or_email' do
    user = User.new(email: 'foo@example.com', name: '')

    assert_equal 'foo@example.com', user.name_or_email
  end

assertを使って、期待される結果が返ってくるかをテストする。

assert_equal '期待される返り値', 実際の返り値
  • よく使いそうなassertメソッド
メソッド 役割
assert_empty 指定された項目が空であるかを確認する
assert_equal 相互に指定された内容が一致するかを確認する
assert_difference ブロックの評価結果の差分を確認する

他にもassertメソッドは何個かあるみたい。 https://railsguides.jp/testing.html#%E5%88%A9%E7%94%A8%E5%8F%AF%E8%83%BD%E3%81%AA%E3%82%A2%E3%82%B5%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3

systemテストについて

systemテストではrailsCRUD機能をテストする。 scaffoldした時点で、CRUDテストの雛形は作成されている。 rails test:systemをして、エラーを解消しながら、テストを書く流れとなる。

下記に、自作したテストファイルを記載する。今後テストするときは、下記のお手本を参考にテストを書くといいかもしれない。

booksのCRUDをテストする場合

require 'application_system_test_case'

class BooksTest < ApplicationSystemTestCase
  setup do
    visit root_url
    fill_in 'Eメール', with: 'alice@example.com'
    fill_in 'パスワード', with: 'password'
    click_button 'ログイン'
  end

  test 'visiting the index' do
    visit books_url
    assert_selector 'h1', text: '本'
  end

  test 'creating a Book' do
    visit books_url
    click_on '新規作成'

    fill_in 'タイトル', with: 'Ruby超入門'
    fill_in 'メモ', with: 'すごくわかりやすい!!'
    fill_in '著者', with: 'igaiga'
    click_on '登録する'

    assert_text '本が作成されました。'
    assert_text 'Ruby超入門'
    assert_text 'すごくわかりやすい!!'
    assert_text 'igaiga'
  end

  test 'updating a Book' do
    visit books_url
    click_on '編集'

    fill_in 'タイトル', with: '独習RubyonRails'
    fill_in 'メモ', with: 'わかりやすい!!'
    fill_in '著者', with: '小餅良介'
    click_on '更新'

    assert_text '本が更新されました。'
    assert_text '独習RubyonRails'
    assert_text 'わかりやすい!!'
    assert_text '小餅良介'
  end

  test 'destroying a Book' do
    visit books_url
    page.accept_confirm do
      click_on '削除'
    end

    assert_text '本が削除されました。'
  end
end