DEV Community

kaede
kaede

Posted on • Updated on

Rails 基礎 Part 04 -- index の単体テストを RSpec と FactoryBot で作る

why

コーチングを受けて、テストピラミッドを学んだ。
これにより、単体テストを絶対に書くべきだと考えた。

単体テストを全て書くためには、スピードを上げる必要があると考えた。
テストを作るスピードが遅ければ、テストだけどんどん別チケットになってたまってしまうからだ。

テストを作るスピードを上げるために、プライベートで一から作ってみることにした。


テストピラミッドについて

テストピラミッドは、下記の図のようになっている。

               /\
              /  \
             / UI \
            / テスト \
           /---------\
          / 統合テスト  \
         /-------------\
        / ユニットテスト   \
       /------------------\

Enter fullscreen mode Exit fullscreen mode

参考は下記 URL

https://thinkit.co.jp/article/13346


今回の作業に必要なもの

  1. Controller の実装本体。index メソッド。前回の記事で作成ずみ
  2. Rspec ライブラリ。Rails にビルドインされている。
  3. FactoryBot のライブラリ。
  4. FactoryBot でのテストデータ生成用のファクトリー定義ファイル
  5. RSpec と ファクトリー定義ファイル を使った単体テストのファイル

ファクトリーとは?

データを生成する場所のこと。

現実世界の具体例で考えてみよう。

僕らはコンビニで食べ物を買う。
しかしコンビニでは基本的に物を製造しない。
製品は別の場所、工場でで作られる。
それからコンビニに運ばれて売られる。

これをデータに置き換えよう。
データを生成する「工場」がまさに「ファクトリー」。
そして今回、このファクトリーを単体テストフレームワークである RSpec で使用する。



前回作った API の GET から UT を作っていく


Gemfile でライブラリのインストール

単体テスト専用のデータを作るため、FactoryBot というライブラリをインストールする。

Gemfile
Enter fullscreen mode Exit fullscreen mode
group :development, :test do
  # See https://guides.rubyonrails.org/debugging_rails_applications.html#debugging-with-the-debug-gem
  gem "debug", platforms: %i[ mri mingw x64_mingw ]
  gem 'rspec-rails', '~> 6.0.0'
  gem 'factory_bot_rails'

end
Enter fullscreen mode Exit fullscreen mode

これで development or test でのみ動く

FactoryBot の README は下記。

https://github.com/thoughtbot/factory_bot/blob/master/GETTING_STARTED.md#update-your-gemfile

bundle install でプロジェクトに入る


データ挿入の factries

spec/factories/bank_tranksactions.rb
Enter fullscreen mode Exit fullscreen mode

これを作成

FactoryBot.define do
  factory :bank_transaction do
    account_number { '1234567' }
    amount  { 250_000 }
    description  { "おちんぎん" }
#     sequence(:username) { |n| "user#{n}" }
  end
end
Enter fullscreen mode Exit fullscreen mode

呼ばれるとデータが入る factories を作る


Controller のテスト本体

spec/controllers/bank_transactions_controller_spec.rb
Enter fullscreen mode Exit fullscreen mode
describe BankTransactionsController do
  context 'when logged in' do
      before do
        FactoryBot.create(:bank_transaction)
      end
      it 'get all bank transactions' do
        # FactoryBot.build(:bank_transaction)
        # FactoryBot.create(:bank_transaction)
        get :index

        # pp response.body
        amount = JSON.parse(response.body).first['amount'].to_i
        expect(amount).to eq 250000
      end

      after do
        BankTransaction.destroy_all
      end
  end
end
Enter fullscreen mode Exit fullscreen mode
  1. describe ControllerName でコントローラー指定
  2. before FactoryBot.create でテスト実行前にデータを作成して DB に入れる。
    • build では DB には入らない。
  3. get :methodName でメソッドを指定
  4. json が返ってくるのでパースしてキーを指定
  5. expect(key).to eq value で比較
  6. after でデータを破棄

このサイクル。


実際の実行

Terminal
Enter fullscreen mode Exit fullscreen mode

エラーがある場合

rspec spec/controllers/bank_transactions_controller_spec.rb
F

Failures:

  1) BankTransactionsController when logged in get all bank transactions
     Failure/Error: json = JSON.parse(response.body).first.to_i

     NoMethodError:
       undefined method `to_i' for {"id"=>1, "account_number"=>"1234567", "amount"=>"250000.0", "description"=>"おちんぎん", "created_at"=>"2023-05-21T05:23:39.241Z", "updated_at"=>"2023-05-21T05:23:39.241Z"}:Hash
     # ./spec/controllers/bank_transactions_controller_spec.rb:12:in `block (3 levels) in <main>'
Enter fullscreen mode Exit fullscreen mode

ない場合

kaede0902@V bank_transactions_api % rspec spec/controllers/bank_transactions_controller_spec.rb
.

Finished in 0.08155 seconds (files took 1.77 seconds to load)
1 example, 0 failure
Enter fullscreen mode Exit fullscreen mode

Top comments (0)