Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationEventAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
14
Help us understand the problem. What are the problem?

More than 1 year has passed since last update.

@jnchito

【2019年7月版・動画付き】Cloud9上でEveryday Railsの`js: true`付きのフィーチャスペックを実行する手順

注:2020年8月版の手順を最後に追記しています。

はじめに

先ほど、こちらの記事を拝見しました。

【Everyday Rails 6章 JavaScriptテスト】AWS Cloud9でChromeエラーが出たときの対処法 - Qiita

詳しくは上記の記事を読んでいただきたいのですが、簡単にまとめると、

  • Everyday Rails - RSpecによるRailsテスト入門」(僕が翻訳した電子書籍。以下Everyday Rails)の第6章に書いてあるjs: true付きのテストコードをCloud9で動かそうとしたらエラーが起きた
  • 参考記事を読んで対応しようとしたが、それでもダメだった
  • Chromeを使うのはあきらめてPhantomjs + poltergeistを使うようにしたらテストが動いた

というものです。

たしかに、本の中では第2の選択肢としてPhantomjs + poltergeistを紹介しています。
ですが、こちらはすでに開発が止まっているため、できることならChromeを使って実行したいところです。

そこで、この記事ではCloud9上でサンプルコードを動かしながらEveryday Railsを勉強しようとしている読者さんのために、Cloud9上でjs: true付きのフィーチャスペックを実行する手順(Phantomjs + poltergeistではなく、Chromeを使う手順)を紹介します。

実行環境

この記事は以下の環境で動作確認しています。

また、サンプルコードを動かすために参照しているEveryday Railsの版は、最新の変更履歴が2019/04/08の版(chromedriver-helperではなく、webdriversを使っている版)です。

手順

1. tasks_spec.rb を準備する

今回はspec/features/tasks_spec.rbをCloud9上で動かせるようにしていきます。
第6章にある以下の説明文まで、本書の説明通りにサンプルコードを準備してください。

さあ、これで準備が整いました。実際にやってみましょう。新しく作ったスペックを実行してみてください。

$ bin/rspec spec/features/tasks_spec.rb

Cloud9上でこのコマンドを実行すると以下のようなエラーが発生するはずです。

 Failures:

  1) Tasks user toggles a task
     Failure/Error: visit root_path

     Webdrivers::VersionError:
       Failed to find Chrome binary or its version.
     # /home/ec2-user/.rvm/gems/ruby-2.6.3/gems/webdrivers-4.0.1/lib/webdrivers/chrome_finder.rb:10:in `version'
     # 以下省略...

もしくは次のようなエラーになっているかもしれません。
(webdrivers 4.1.0でのみ発生? - 参考

Failures:

  1) Tasks user toggles a task
     Failure/Error: visit root_path

     ArgumentError:
       wrong first argument
     # /home/ec2-user/.rvm/gems/ruby-2.6.3/gems/webdrivers-4.1.0/lib/webdrivers/system.rb:150:in `popen'
     # 以下省略...

2. Chromeブラウザをインストールする

js: true付きのフィーチャスペックを実行するにはChromeブラウザが必要ですが、初期状態のAmazon LinuxにはChromeがインストールされていません。
そこで、ターミナルから以下のコマンドを実行し、Chromeをインストールしてください。

$ curl https://intoli.com/install-google-chrome.sh | bash

この記事の執筆時点ではChrome 75がインストールされました。

Successfully installed google-chrome-stable, Google Chrome 75.0.3770.100 .

3. ヘッドレスモードでChromeを起動できるようにする

Cloud9上ではGUIモードのChromeを起動することはできません。
ですので、代わりにヘッドレスモード(GUIを起動しないモード)でテストを実行するようにします。

spec/support/capybara.rbにあるselenium_chromeselenium_chrome_headlessに変更してください。

spec/support/capybara.rb
-Capybara.javascript_driver = :selenium_chrome
+Capybara.javascript_driver = :selenium_chrome_headless

4. selenium-webdriverとcapybaraを最新版にする

最新のChromeを正常に操作できるよう、selenium-webdriverとcapybaraを最新版にします。

まず、Gemfileを編集してcapybaraのバージョン制限を外します。

Gemfile
 group :test do 
-  gem 'capybara', '~> 2.15.2'
+  gem 'capybara'
   gem 'webdrivers'
 end

続いて以下のコマンドを実行し、selenium-webdriverとcapybaraをアップデートします。

$ bundle update selenium-webdriver capybara

この記事の執筆時点では以下のバージョンにアップデートされました。

$ bundle list | grep 'selenium\|capybara'
  * capybara (3.25.0)
  * selenium-webdriver (3.142.3)

5. テストが正常に実行できることを確認する

これで準備完了です。
うまくいけば次のようにtasks_spec.rbが正常に実行できるはずです。

$ bin/rspec spec/features/tasks_spec.rb 
Running via Spring preloader in process 18989

Tasks
Capybara starting Puma...
* Version 3.8.2 , codename: Sassy Salamander
* Min threads: 0, max threads: 4
* Listening on tcp://127.0.0.1:35495
  user toggles a task

Finished in 2.13 seconds (files took 0.28209 seconds to load)
1 example, 0 failures

ちなみに、上の実行例では.rspecファイルから--warningsを外して、不要な警告が表示されないようにしています。

.rspec
--require spec_helper
--format documentation

動画を使った、より詳しい説明

この記事の内容をもっと詳しく説明した動画をYouTubeにアップしています。
こちらもぜひご覧ください。

https://www.youtube.com/watch?v=wIKW3mIPrdcimage

参考文献

追記:2020年8月版の手順

下記の質問に答える形で、2020年8月版の手順も動画にまとめました。

具体的には本記事の手順4と手順5の間に以下の手順が追加で必要になります。

webdrivers gemを使う

selenium-webdriver gemはサポートが止まっています。代わりにwebdrivers gemを使います。

Gemfile
 group :test do
   gem 'capybara'
   gem 'selenium-webdriver'
-  gem 'chromedriver-helper'
+  gem 'webdrivers'
$ bundle install

spec/support/vcr.rb に設定を追加

webdrivers gemをインストールした関係で、vcrの設定を追加する必要があります。

spec/support/vcr.rb
 VCR.configure do |config|
   config.cassette_library_dir = "#{::Rails.root}/spec/cassettes"
   config.hook_into :webmock
   config.ignore_localhost = true
+  config.ignore_hosts 'chromedriver.storage.googleapis.com'
   config.configure_rspec_metadata!
 end

詳しくは上記の動画を参考にしてください。

追記2:さらにRuby 2.6系で実行する場合

上の「2020年8月版の手順」ではRuby 2.4系で動かしたのですが、Ruby 2.6系で動かすと以下のようなエラーが出る場合があります。(masterブランチのテストコードをそのまま実行しようとすると発生します)

Failures:

  1) Tasks user toggles a task
     Got 0 failures and 2 other errors:

     1.1) Failure/Error: visit root_path

          ArgumentError:
            unknown keyword: write_timeout



          # /home/ec2-user/.rvm/gems/ruby-2.6.3/gems/webmock-3.0.1/lib/webmock/http_lib_adapters/net_http.rb:259:in `initialize'
          # /home/ec2-user/.rvm/gems/ruby-2.6.3/gems/webmock-3.0.1/lib/webmock/http_lib_adapters/net_http.rb:136:in `start_with_connect_without_finish'
          # /home/ec2-user/.rvm/gems/ruby-2.6.3/gems/webmock-3.0.1/lib/webmock/http_lib_adapters/net_http.rb:104:in `request'
          # /home/ec2-user/.rvm/gems/ruby-2.6.3/gems/capybara-3.32.2/lib/capybara/server.rb:56:in `block in responsive?'
          # /home/ec2-user/.rvm/gems/ruby-2.6.3/gems/webmock-3.0.1/lib/webmock/http_lib_adapters/net_http.rb:123:in `start_without_connect'
          # /home/ec2-user/.rvm/gems/ruby-2.6.3/gems/webmock-3.0.1/lib/webmock/http_lib_adapters/net_http.rb:150:in `start'
          # /home/ec2-user/.rvm/gems/ruby-2.6.3/gems/capybara-3.32.2/lib/capybara/server/checker.rb:36:in `make_request'
          # /home/ec2-user/.rvm/gems/ruby-2.6.3/gems/capybara-3.32.2/lib/capybara/server/checker.rb:28:in `http_request'
          # /home/ec2-user/.rvm/gems/ruby-2.6.3/gems/capybara-3.32.2/lib/capybara/server/checker.rb:14:in `request'
          # /home/ec2-user/.rvm/gems/ruby-2.6.3/gems/capybara-3.32.2/lib/capybara/server.rb:56:in `responsive?'
          # /home/ec2-user/.rvm/gems/ruby-2.6.3/gems/capybara-3.32.2/lib/capybara/server.rb:81:in `boot'
          # /home/ec2-user/.rvm/gems/ruby-2.6.3/gems/capybara-3.32.2/lib/capybara/session.rb:93:in `initialize'
          # /home/ec2-user/.rvm/gems/ruby-2.6.3/gems/capybara-3.32.2/lib/capybara.rb:415:in `new'
          # /home/ec2-user/.rvm/gems/ruby-2.6.3/gems/capybara-3.32.2/lib/capybara.rb:415:in `block in session_pool'
          # /home/ec2-user/.rvm/gems/ruby-2.6.3/gems/capybara-3.32.2/lib/capybara.rb:312:in `current_session'
          # /home/ec2-user/.rvm/gems/ruby-2.6.3/gems/capybara-3.32.2/lib/capybara/dsl.rb:46:in `page'
          # /home/ec2-user/.rvm/gems/ruby-2.6.3/gems/capybara-3.32.2/lib/capybara/dsl.rb:58:in `block (2 levels) in <module:DSL>'
          # ./spec/system/tasks_spec.rb:24:in `go_to_project'
          # ./spec/system/tasks_spec.rb:14:in `block (2 levels) in <top (required)>'
          # /home/ec2-user/.rvm/gems/ruby-2.6.3/gems/spring-commands-rspec-1.0.4/lib/spring/commands/rspec.rb:18:in `call'
          # -e:1:in `<main>'

     1.2) Failure/Error:
                def initialize(io, read_timeout: 60, continue_timeout: nil, debug_output: nil)
                  @read_timeout = read_timeout
                  @rbuf = ''
                  @debug_output = debug_output

                  @io = case io
                  when Socket, OpenSSL::SSL::SSLSocket, IO
                    io
                  when StringIO
                    PatchedStringIO.new(io.string)

          ArgumentError:
            unknown keyword: write_timeout



          # /home/ec2-user/.rvm/gems/ruby-2.6.3/gems/webmock-3.0.1/lib/webmock/http_lib_adapters/net_http.rb:259:in `initialize'
          # /home/ec2-user/.rvm/gems/ruby-2.6.3/gems/webmock-3.0.1/lib/webmock/http_lib_adapters/net_http.rb:136:in `start_with_connect_without_finish'
          # /home/ec2-user/.rvm/gems/ruby-2.6.3/gems/webmock-3.0.1/lib/webmock/http_lib_adapters/net_http.rb:104:in `request'
          # /home/ec2-user/.rvm/gems/ruby-2.6.3/gems/capybara-3.32.2/lib/capybara/server.rb:56:in `block in responsive?'
          # /home/ec2-user/.rvm/gems/ruby-2.6.3/gems/webmock-3.0.1/lib/webmock/http_lib_adapters/net_http.rb:123:in `start_without_connect'
          # /home/ec2-user/.rvm/gems/ruby-2.6.3/gems/webmock-3.0.1/lib/webmock/http_lib_adapters/net_http.rb:150:in `start'
          # /home/ec2-user/.rvm/gems/ruby-2.6.3/gems/capybara-3.32.2/lib/capybara/server/checker.rb:36:in `make_request'
          # /home/ec2-user/.rvm/gems/ruby-2.6.3/gems/capybara-3.32.2/lib/capybara/server/checker.rb:28:in `http_request'
          # /home/ec2-user/.rvm/gems/ruby-2.6.3/gems/capybara-3.32.2/lib/capybara/server/checker.rb:14:in `request'
          # /home/ec2-user/.rvm/gems/ruby-2.6.3/gems/capybara-3.32.2/lib/capybara/server.rb:56:in `responsive?'
          # /home/ec2-user/.rvm/gems/ruby-2.6.3/gems/capybara-3.32.2/lib/capybara/server.rb:73:in `boot'
          # /home/ec2-user/.rvm/gems/ruby-2.6.3/gems/capybara-3.32.2/lib/capybara/session.rb:93:in `initialize'
          # /home/ec2-user/.rvm/gems/ruby-2.6.3/gems/capybara-3.32.2/lib/capybara.rb:415:in `new'
          # /home/ec2-user/.rvm/gems/ruby-2.6.3/gems/capybara-3.32.2/lib/capybara.rb:415:in `block in session_pool'
          # /home/ec2-user/.rvm/gems/ruby-2.6.3/gems/capybara-3.32.2/lib/capybara.rb:312:in `current_session'
          # /home/ec2-user/.rvm/gems/ruby-2.6.3/gems/capybara-3.32.2/lib/capybara/dsl.rb:46:in `page'
          # /home/ec2-user/.rvm/gems/ruby-2.6.3/gems/spring-commands-rspec-1.0.4/lib/spring/commands/rspec.rb:18:in `call'
          # -e:1:in `<main>'

このエラーが出た場合はwebmockのバージョンを最新にすると解消します。(参考

$ bundle update webmock
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
14
Help us understand the problem. What are the problem?