# Rails の feature スペックを書く

featureスペック をまだ書いていないプロジェクトで書こうとしたときのメモです。

他のプロジェクトで、featureスペック を書いたことはありましたが、設定ははじめてでした。

まだ、設定途中です。

# feature スペック

# spec/features/xxxx/create_spec.rb

# frozen_string_literal: true

require 'rails_helper'

RSpec.describe 'ユーザー追加', type: :feature, js: true do
  def input_aaa
    fill_in 'aaa_name', with: '名前'
    choose 'aaa_gender_男性'
  end

  def input_bbb
    check 'bbb_salary', with: '5,000兆円以上'
    select 'エンジニア', from: 'bbb_profession'
  end

  shared_examples_for :finish_xxxx do
    scenario '完了ページへ遷移' do
      expect { click_button '追加する' } .to change { User.all.size } .by(1)
      expect(page).to have_content '名前を入力してください'
      expect(page).to have_current_path xxx_path
    end
  end

  shared_examples_for :render_new do
    scenario '追加ページがrenderされる' do
      fill_in 'aaa_name', with: ''
      click_button '追加する'
      expect(page).to have_content '名前を入力してください'
      expect(page).to have_current_path xxx_path
    end
  end

  feature 'ユーザーを追加する' do
    background do
      visit new_xxxx_path
      input_aaa
      input_bbb
    end

    context 'valid' do
      include_context :finish_xxxx
    end

    context 'invalid' do
      include_context :render_new
    end
  end
end

# 実行

$ bundle exec rspec ./spec/features/xxxx/create_spec.rb

Randomized with seed 28106

ユーザー追加
  ユーザーを追加する
    example at ./spec/features/xxxx/create_spec.rb:78 (FAILED - 1)

Failures:

  1) ユーザー追加 ユーザーを追加する
     Failure/Error: visit new_shop_yyyyy_path(shop)

     Selenium::WebDriver::Error::WebDriverError:
       unable to connect to chromedriver 127.0.0.1:9515
     # ./spec/features/yyyyy/create_spec.rb:69:in `block (3 levels) in <top (required)>'

Top 1 slowest examples (20.73 seconds, 79.1% of total time):
  ユーザー追加 ユーザーを追加する
    20.73 seconds ./spec/features/yyyyy/create_spec.rb:78

Finished in 26.22 seconds (files took 4.47 seconds to load)
1 example, 1 failure

Failed examples:

rspec ./spec/features/xxxx/create_spec.rb:78 # ユーザー追加 ユーザーを追加する

Randomized with seed 28106

落ちる。

# feature スペック が途中で落ちないように修正

これらを参考に進めた。

# 必要な gem をインストール

すでにインストールされていた。

# Gemfile

group :development, :test do
  gem 'capybara', '~> 2.13'
  gem 'rspec-rails'
  gem 'selenium-webdriver'
end

# chromedriver

chromedriver をインストール

$ brew install chromedriver

Updating Homebrew...
==> Auto-updated Homebrew!
Updated 2 taps (homebrew/core and homebrew/cask).
==> New Formulae
bumpversion                                     git-absorb                                      jp
==> Updated Formulae
clutter-gst             cocoapods               ffmpeg                  kube-aws                mpv                     timidity

Error: No available formula with the name "chromedriver"
It was migrated from homebrew/core to homebrew/cask.
You can access it again by running:
  brew tap homebrew/cask
And then you can install it by running:
  brew cask install chromedriver

brew cask install chromedriver しろと言われたので、実行。

$ brew cask install chromedriver
Warning: Cask 'chromedriver' is already installed.

To re-install chromedriver, run:
  brew cask reinstall chromedriver

すでに、インストールされていたので、featureスペック を実行。


上手くいかなかったので、

下と同じエラーだった気がする。

Selenium::WebDriver::Error::WebDriverError:
  unable to connect to chromedriver 127.0.0.1:9515

Error: unable to connect to chromedriver http://127.0.0.1:9515 (Selenium::WebDriver::Error::WebDriverError) · Issue #44 · flavorjones/chromedriver-helper · GitHub を参考に対応した。

$ which chromedriver
/Users/xxxxx/.rbenv/shims/chromedriver

$ ls ~/.rbenv/versions/*/bin/* | grep chromedriver
/Users/xxxxx/.rbenv/versions/2.4.1/bin/chromedriver
/Users/xxxxx/.rbenv/versions/2.4.1/bin/chromedriver-helper
/Users/xxxxx/.rbenv/versions/2.4.1/bin/chromedriver-update
/Users/xxxxx/.rbenv/versions/2.5.1/bin/chromedriver
/Users/xxxxx/.rbenv/versions/2.5.1/bin/chromedriver-update

$ rm ~/.rbenv/versions/2.4.1/bin/chromedriver

$ rm ~/.rbenv/versions/2.4.1/bin/chromedriver-update

$ ls ~/.rbenv/versions/*/bin/* | grep chromedriver
/Users/xxxxx/.rbenv/versions/2.4.1/bin/chromedriver-helper
/Users/xxxxx/.rbenv/versions/2.5.1/bin/chromedriver
/Users/xxxxx/.rbenv/versions/2.5.1/bin/chromedriver-update

$ rm ~/.rbenv/versions/2.5.1/bin/chromedriver-update

$ rm ~/.rbenv/versions/2.5.1/bin/chromedriver

$ rbenv rehash

$ which chromedriver
/usr/local/bin/chromedriver

# Capybara の設定

# spec/support/capybara.rb

require 'capybara/rspec'
require 'selenium-webdriver'

Capybara.register_driver :chrome do |app|
  Capybara::Selenium::Driver.new(app, browser: :chrome)
end

Capybara.register_driver :headless_chrome do |app|
  capabilities = Selenium::WebDriver::Remote::Capabilities.chrome(
    chromeOptions: { args: %w[headless disable-gpu] }
  )

  Capybara::Selenium::Driver.new(
    app,
    browser: :chrome,
    desired_capabilities: capabilities
  )
end

Capybara.javascript_driver = :headless_chrome
Capybara.default_max_wait_time = 5

Capybara.default_max_wait_time = 5 みたいな感じで、 要素を見つけるまでの時間を設定できる。

参考:Capybara のウェイト時間で足りない場合、さらに待たせる。 - ンンンパ

# スクリーンショットを全画面で撮れるように

すべてのフォームに値が入力されているかわからなかったので、 スクリーンショットを撮るようにしたが、

`open #{save_screenshot("a.png", full: true)}`

だと、一部分しか撮れていなかった。


全画面を撮りたかったので、 Capybara+headless-chrome でフルサイズのスクリーンショットを撮る - Qiita を読んで、同じ様に書いた。

# spec/rails_halper.rb

...
require 'rspec/rails'
require 'support/capybara'
...

# スクリーンショットを全画面で撮る
def take_full_page_screenshot(path)
  width  = Capybara.page.execute_script("return Math.max(document.body.scrollWidth, document.body.offsetWidth, document.documentElement.clientWidth, document.documentElement.scrollWidth, document.documentElement.offsetWidth);")
  height = Capybara.page.execute_script("return Math.max(document.body.scrollHeight, document.body.offsetHeight, document.documentElement.clientHeight, document.documentElement.scrollHeight, document.documentElement.offsetHeight);")

  window = Capybara.current_session.driver.browser.manage.window
  window.resize_to(width+100, height+100)

  page.save_screenshot path
end

binding.pry を使って、テストを止めて take_full_page_screenshot で、 全画面のスクリーンショットを見れる。

[1] pry(#<RSpec::ExampleGroups::Nested::Nested::Valid>)> `open #{take_full_page_screenshot("a.png")}`

# 上手くいかなかったところ

# choose がだめだった
choose 'aaa_gender_男性'

# これだと動いた
page.execute_script("document.getElementById('aaa_gender_男性').checked = true")
# check もだめ
check 'bbb_salary', with: '5,000兆円以上'

# これで動く
page.execute_script("document.getElementById('5,000兆円以上').checked = true")
# fill_in と select は問題なく動いた
fill_in 'aaa_name', with: '名前'
select 'エンジニア', from: 'bbb_profession'

参考:forms - Capybara choose method Unable to find radio button - Stack Overflow

# Obsolete #<Capybara::Node::Element>

binding.pry で止めて、click_on, click_button などすると、こうなった。

[4] pry(#<RSpec::ExampleGroups::Nested::Nested::Valid>)> click_on '追加する'
=> Obsolete #<Capybara::Node::Element>

次の画面に遷移してほしいのに、クリックしても遷移しない。 クリックしてバリデーションに引っかかったときは、エラーメッセージは出る(謎)。

# CircleCI

CircleCI で、落ちていたので修正する。

Docker の設定とかしてないから?

Failures:

  1) ユーザー追加 ユーザーを追加する invalid 追加ページがrenderされる
     Failure/Error: visit new_shop_yyyyy_path(shop)

     Selenium::WebDriver::Error::WebDriverError:
        Unable to find chromedriver. Please download the server from http://chromedriver.storage.googleapis.com/index.html and place it somewhere on your PATH. More info at https://github.com/SeleniumHQ/selenium/wiki/ChromeDriver.
     Shared Example Group: :render_new called from ./spec/features/yyyyy/create_spec.rb:98
     # ./spec/features/yyyyy/create_spec.rb:85:in `block (3 levels) in <top (required)>'

# いろいろ試したやつ

最初いろいろ設定しようとしたけど、上手くできなかったのでやめた。

# capybara-webkit

# Gemfile

group :development, :test do
  gem 'capybara-webkit'
end
$ bundle install

...

Gem::Ext::BuildError: ERROR: Failed to build gem native extension.

    current directory: /Users/xxxxx/.rbenv/versions/2.5.0/lib/ruby/gems/2.5.0/gems/capybara-webkit-1.15.1
/Users/xxxxx/.rbenv/versions/2.5.0/bin/ruby -r ./siteconf20190206-95678-6swsbl.rb extconf.rb
*** extconf.rb failed ***
Could not create Makefile due to some reason, probably lack of necessary
libraries and/or headers.  Check the mkmf.log file for more details.  You may
need configuration options.

Provided configuration options:
	--with-opt-dir
	--without-opt-dir
	--with-opt-include
	--without-opt-include=${opt-dir}/include
	--with-opt-lib
	--without-opt-lib=${opt-dir}/lib
	--with-make-prog
	--without-make-prog
	--srcdir=.
	--curdir
	--ruby=/Users/xxxxx/.rbenv/versions/2.5.0/bin/$(RUBY_BASE_NAME)
	--with-gl-dir
	--without-gl-dir
	--with-gl-include
	--without-gl-include=${gl-dir}/include
	--with-gl-lib
	--without-gl-lib=${gl-dir}/lib
	--with-zlib-dir
	--without-zlib-dir
	--with-zlib-include
	--without-zlib-include=${zlib-dir}/include
	--with-zlib-lib
	--without-zlib-lib=${zlib-dir}/lib
Command 'qmake ' not available

extconf failed, exit code 1

Gem files will remain installed in /Users/xxxxx/.rbenv/versions/2.5.0/lib/ruby/gems/2.5.0/gems/capybara-webkit-1.15.1 for inspection.
Results logged to
/Users/xxxxx/.rbenv/versions/2.5.0/lib/ruby/gems/2.5.0/extensions/x86_64-darwin-17/2.5.0-static/capybara-webkit-1.15.1/gem_make.out

An error occurred while installing capybara-webkit (1.15.1), and Bundler cannot continue.
Make sure that `gem install capybara-webkit -v '1.15.1' --source 'https://rubygems.org/'` succeeds before bundling.

In Gemfile:
  capybara-webkit

qmake がないと言われたので、qt を入れようとした。

# qt

$ brew install qt

Updating Homebrew...
==> Auto-updated Homebrew!
Updated 3 taps (homebrew/core, homebrew/cask and px4/px4).
==> New Formulae
ahoy                                gerbil-scheme                       lsd                                 px4/px4/gcc-arm-none-eabi-80
anyenv                              grpcurl                             man-db                              rakudo
aws-iam-authenticator               hexyl                               moarvm                              s3ql

...

                      zorba
devd                         i2pd                         mysql@5.7                    sbcl
devtodo                      iamy                         nativefier                   scalapack
==> Deleted Formulae
apache-arrow            cctools                 cputhrottle             ld64                    percona-server@5.6      ruby@1.8
apache-arrow-glib       cctools-headers         hyper                   liblastfm               php@5.6

==> Downloading https://homebrew.bintray.com/bottles/qt-5.12.0.high_sierra.bottle.tar.gz
######################################################################## 100.0%
==> Pouring qt-5.12.0.high_sierra.bottle.tar.gz
==> Caveats
We agreed to the Qt open source license for you.
If this is unacceptable you should uninstall.

qt is keg-only, which means it was not symlinked into /usr/local,
because Qt 5 has CMake issues when linked.

If you need to have qt first in your PATH run:
  echo 'export PATH="/usr/local/opt/qt/bin:$PATH"' >> ~/.zshrc

For compilers to find qt you may need to set:
  export LDFLAGS="-L/usr/local/opt/qt/lib"
  export CPPFLAGS="-I/usr/local/opt/qt/include"

For pkg-config to find qt you may need to set:
  export PKG_CONFIG_PATH="/usr/local/opt/qt/lib/pkgconfig"

==> Summary
🍺  /usr/local/Cellar/qt/5.12.0: 9,689 files, 318.9MB
==> `brew cleanup` has not been run in 30 days, running now...
Removing: /Users/xxxxx/Library/Caches/Homebrew/awscli--1.16.60.high_sierra.bottle.tar.gz... (8MB)
Removing: /Users/xxxxx/Library/Caches/Homebrew/bash--4.4.23.high_sierra.bottle.tar.gz... (2.7MB)
Removing: /Users/xxxxx/Library/Caches/Homebrew/bash-completion@2--2.8.high_sierra.bottle.tar.gz... (222.3KB)
...
Removing: /Users/xxxxx/Library/Logs/Homebrew/git... (64B)
Removing: /Users/xxxxx/Library/Logs/Homebrew/libmpc... (64B)

ここからは、何もしてない。 買い替えた mac(High Sierra)で capybara-webkit のインストールで躓いたときに行ったこと - Qiita が参考になるかも。

# 参考