Docker環境でRspecをインストールする

Windowsで Docker を用いて Rails 6.0 + MySQL の環境構築の続きです。

Windowsで Docker を用いて Rails 6.0 + MySQL の環境構築
https://codelabo.com/posts/20201010192152

前回はテストを入れずにRails環境を構築したので、今回はテストフレームワークとしてRspecを入れます。

Bundler::GemNotFoundエラーの対処方法も書いてます。

基本的に公式リポジトリ https://github.com/rspec/rspec-rails に書かれてる通りに進めればできると思います。

Gemfileに以下を追加

group :development, :test do
  gem 'rspec-rails', '~> 4.0.1'
end

bundle install します。

docker-compose run app bundle install

設定ファイルを生成します。

 docker-compose run app rails generate rspec:install

エラーがでました。

Traceback (most recent call last):
        25: from /usr/local/bundle/gems/spring-2.1.1/bin/spring:49:in `<main>'
        24: from /usr/local/bundle/gems/spring-2.1.1/lib/spring/client.rb:30:in `run'
        23: from /usr/local/bundle/gems/spring-2.1.1/lib/spring/client/command.rb:7:in `call'
        22: from /usr/local/bundle/gems/spring-2.1.1/lib/spring/client/server.rb:9:in `call'
        21: from /usr/local/lib/ruby/2.7.0/rubygems/core_ext/kernel_require.rb:72:in `require'
        20: from /usr/local/lib/ruby/2.7.0/rubygems/core_ext/kernel_require.rb:72:in `require'
        19: from /usr/local/bundle/gems/spring-2.1.1/lib/spring/server.rb:9:in `<top (required)>'
        18: from /usr/local/lib/ruby/2.7.0/rubygems/core_ext/kernel_require.rb:72:in `require'
        17: from /usr/local/lib/ruby/2.7.0/rubygems/core_ext/kernel_require.rb:72:in `require'
        16: from /usr/local/bundle/gems/spring-2.1.1/lib/spring/commands.rb:4:in `<top (required)>'
        15: from /usr/local/bundle/gems/spring-2.1.1/lib/spring/commands.rb:33:in `<module:Spring>'
        14: from /usr/local/lib/ruby/2.7.0/rubygems/core_ext/kernel_require.rb:92:in `require'
        13: from /usr/local/lib/ruby/2.7.0/rubygems/core_ext/kernel_require.rb:92:in `require'
        12: from /usr/local/lib/ruby/2.7.0/bundler/setup.rb:20:in `<top (required)>'
        11: from /usr/local/lib/ruby/2.7.0/bundler/ui/shell.rb:88:in `silence'
        10: from /usr/local/lib/ruby/2.7.0/bundler/ui/shell.rb:136:in `with_level'
         9: from /usr/local/lib/ruby/2.7.0/bundler/setup.rb:20:in `block in <top (required)>'
         8: from /usr/local/lib/ruby/2.7.0/bundler.rb:149:in `setup'
         7: from /usr/local/lib/ruby/2.7.0/bundler/runtime.rb:20:in `setup'
         6: from /usr/local/lib/ruby/2.7.0/bundler/runtime.rb:101:in `block in definition_method'
         5: from /usr/local/lib/ruby/2.7.0/bundler/definition.rb:226:in `requested_specs'
         4: from /usr/local/lib/ruby/2.7.0/bundler/definition.rb:237:in `specs_for'
         3: from /usr/local/lib/ruby/2.7.0/bundler/definition.rb:170:in `specs'
         2: from /usr/local/lib/ruby/2.7.0/bundler/spec_set.rb:80:in `materialize'
         1: from /usr/local/lib/ruby/2.7.0/bundler/spec_set.rb:80:in `map!'
/usr/local/lib/ruby/2.7.0/bundler/spec_set.rb:86:in `block in materialize': Could not find diff-lcs-1.4.4 in any of the sources (Bundler::GemNotFound)

Bundler::GemNotFound

何を言ってるかわかりませんが、docker-compose build してみます。

Docker関連でエラーが出ると心が折れそうになるので、やめてほしいですね。

docker-compose build

もう一度Rails generate します。

docker-compose run app rails generate rspec:install

以下のログが出てうまくいきました。

Starting vdoll-rails_db_1 ... done                                                                                      Running via Spring preloader in process 66
      create  .rspec
      create  spec
      create  spec/spec_helper.rb
      create  spec/rails_helper.rb

テスト実行

以下のコマンドでテストを実行できます。

docker-compose run app rspec
# もしくは
docker-compose run app bundle exec rspec

他のターミナルなどで docker-compose up してるならrunではなくexecを使う方が高速です。

docker-compose exec app rspec
# もしくは
docker-compose exec app bundle exec rspec

上のコマンドだとすべてのテストが実行されるので、テストの数が多くなればかなり時間がかかるようになってしまいます。

なので、以下の様にファイル単位で実行することが多いかと思います。

docker-compose run app bundle exec rspec spec/*/*_spec.rb

余計なファイルが生成されないようにする

docker-compose exec app rails g controller Pages index show

みたいなコマンドで以下の様に必要ないテストファイルが生成されたりします。

それを生成されないようにするためには、\config\application.rb

module App
  class Application < Rails::Application
    # Rspec
    config.generators.test_framework :rspec,
      view_specs: false, 
      helper_specs: false, 
      controller_specs: false, 
      routing_specs: false
    end
  end

の様に追記します。

個人的にViewのテストを書かないのはFeatureSpecやSystemSpecのような統合テストが代わりになるから、コントローラーのテストを書かないのはRequestSpecや統合テストでカバーできるからなのかなと思いました。

RSpecのFeature Specを設定

rspec-railsに加えて、capybaraとselenium-webdriverをGemfileに追加。

Gemfile

group :development, :test do
  gem 'rspec-rails', '~> 4.0.1'
end

group :test do
  gem 'capybara' # 追加
end

bundle install

$ docker-compose run app bundle install

\spec\spec_helper.rb に

require 'capybara/rspec'

factory_botでテストデータを使いまわす

factory_botを使うことで user = create(:user) みたいにテストデータを使いまわせて便利です。

インストール

Gemfileにfactorybot, databasecleanerを追加。

database_cleanerはSystemSpecを利用する場合は不要です。

Gemfile

group :test do
  gem 'factory_bot_rails'
  gem 'database_cleaner'
end

DatabaseCleanerの設定

spec/rails_helper.rb

RSpec.configure do |config|
  # FactoryBotの利用をON
  config.include FactoryBot::Syntax::Methods

  # DatabaseCleanerの設定
  config.before(:suite) do
    DatabaseCleaner.strategy = :truncation
  end

  config.before(:each) do
    DatabaseCleaner.start
  end

  config.after(:each) do
    DatabaseCleaner.clean
  end

  config.before(:all) do
    DatabaseCleaner.start
  end

  config.after(:all) do
    DatabaseCleaner.clean
  end
end

テストデータの作成

これで問題なくテストデータを作れます。

spec/factories/users.rbファイルを作成して以下の様に書きます。

spec/factories/users.rb

FactoryBot.define do
  factory :ilya, class: User do
    name { 'Illyasviel von Einzbern' }
    email { 'iliya@fate.pi' }
    password { 'password' }
    password_confirmation { 'password' }
  end

  factory :miyu, class: User do
    name { '美遊・エーデルフェルト' }
    email { 'miyu@fate.pi' }
    password { 'password' }
    password_confirmation { 'password' }
  end
end

specファイルで以下の様に使います。

@user = create(:ilya)