blog

これから始める Ruby on Rails シリーズRuby on Rails:RSpecとCapybaraで初めてのインテグレーションテスト

    • Ryuichi Nonaka
    この記事は書かれてから1年以上経過しており、内容が古い場合があります。

    はじめに

    前回の記事では簡単な静的ページを作りました。今回はその静的ページに対して、RSpecを使った簡単なテストを実装してみます。この記事の内容はRuby on Rails チュートリアル第3章の2項 最初のテストを参考にしています。Ruby on Railsおよびrspecを最新版で行っているため、チュートリアルとは異なる部分があります。

    RSpecとは

    テストについてほとんど知識がないので、RSpecを使ったテストコードを読もう (2/4)を引用してきました。

    RSpecとは、Rubyで書かれたプログラムの動作を確認するための、テストコードを記述・実行するためのフレームワークのことです。 実際に動くプログラムの動作のことを振る舞い(ビヘイビア)と呼ぶことから、それまでのテスト駆動開発のやり方をビヘイビア駆動開発(BDD)と呼ぶようになっています。

    テスト駆動開発(TDD)はよく耳にしますが、ビヘイビア駆動開発というのは初耳ですね。自分のようにRuby on Railsの勉強と合わせてテストも勉強してみようという方にはこのサイト「Everyday Rails - RSpecによるRailsテスト入門」(電子書籍版あり)もとても役立つ気がしています。この書籍はRSpecに特化した書籍なので、Ruby on Rails チュートリアルで全体像を理解しつつ、必要に応じて読むようにしています。

    RSpecと合わせて使うCapybara

    Capybaraとはユーザーの操作をエミュレーション(たとえば、ページ遷移)しながらそこにエラーがないかをテストできます。この指定をRSpecを通して自動化できます。

    RSpecをインストールする

    前回の環境をコピーするかブランチを作りrspecを試す環境を作ります。Gemfileを開き、rspec-railscapybaraを追加します。

    group :development, :test do
      gem 'rspec-rails'
      gem 'capybara'
    end
    

    Gemfileへの追記が終わったらbundle installでインストールします。 Yosemiteにバージョンアップしていて、エラーが出た場合はこの記事の下部を参考にしてください。

    インストールされるバージョン

    上記Gemfileの指定でインストールされたバージョンは以下の通りです。

    capybara (2.4.4)
          mime-types (>= 1.16)
          nokogiri (>= 1.3.3)
          rack (>= 1.0.0)
          rack-test (>= 0.5.4)
          xpath (~> 2.0)
    rspec-rails (3.1.0)
          actionpack (>= 3.0)
          activesupport (>= 3.0)
          railties (>= 3.0)
          rspec-core (~> 3.1.0)
          rspec-expectations (~> 3.1.0)
          rspec-mocks (~> 3.1.0)
          rspec-support (~> 3.1.0)
    

    RSpecを使う準備

    インストールが完了したら、RSpecの設定ファイルを作り設定を追記します。$ rails generate rspec:installというコマンドでspec_helper.rbrails_helper.rbが作られます。

    $ rails generate rspec:install
          create  .rspec
          force  spec/spec_helper.rb
          create  spec/rails_helper.rb
    

    spec_helper.rbはRSpecに関する設定、rails_helper.rbにはRailsに関する設定を記述します。今回はspec_helper.rbだけ手を入れます。

    spec_helper.rbに設定を追記

    実はそのままでは動かすことができません。そのままではuninitialized constant Capybara (NameError)というエラーが出てしまったため、こちらrspec の実行で “uninitialized constant Capybara (NameError)”を参考に設定を書き加えました。RSpec.configure do |config|の中に3行追記します。

    
    RSpec.configure do |config|
      ENV["RAILS_ENV"] ||= 'test'
      require File.expand_path("../../config/environment", __FILE__)
      require 'rspec/rails'
    
    

    加えて、最後のendの前にCapybaraに関する指定を1行追記します。

    
      config.include Capybara::DSL
    end
    

    インテグレーションテスト(総合テスト)を作る

    静的ページstatic_pagesに対して、インテグレーションテストを作ります。

    $ rails generate integration_test static_pages
          invoke  rspec
          create    spec/requests/static_pages_spec.rb
    

    生成されたspec/requestsディレクトリのstatic_pages_spec.rbを開きます。 先頭のrequire 'rails_helper'require 'spec_helper'に書き換えます。

    英語で記述するとこんな感じ。

    require 'spec_helper'
    
    RSpec.describe "StaticPages" do
      describe "Home page" do
        it "should have the content 'Sample App'" do
          visit '/static_pages/home'
          expect(page).to have_content('Sample App')
        end
      end
    end
    

    日本語で表してみるとこうなります。

    require 'spec_helper'
    
    RSpec.describe "StaticPages コントローラの" do
      describe "Home ページに" do
        it "文字列'Sample App'が含まれているか" do
          visit '/static_pages/home'
          expect(page).to have_content('Sample App')
        end
      end
    end
    

    テスト対象となるViewのhome(app/views/static_pages/home.html.erb)はそのままにしておきます。

    <h1>StaticPages#home</h1>
    <p>Find me in app/views/static_pages/home.html.erb</p>
    

    テストを実行する

    対象のViewには手を加えず、意図的にテストを失敗させます。 $ rspec spec/requests/static_pages_spec.rbで実際にテストを実行してみます。

    $ rspec spec/requests/static_pages_spec.rb
    F
    
    Failures:
    
      1) StaticPages コントローラの Home ページに 文字列'Sample App'が含まれているか
         Failure/Error: expect(page).to have_content('Sample App!')
           expected #has_content?("Sample App") to return true, got false
         # ./spec/requests/static_pages_spec.rb:7:in `block (3 levels) in <top (required)>'
    
    Finished in 0.07151 seconds (files took 2.19 seconds to load)
    1 example, 1 failure
    
    Failed examples:
    
    rspec ./spec/requests/static_pages_spec.rb:5 # StaticPages コントローラの Home ページに 文字列'Sample App'が含まれているか
    

    失敗したテストが表示されていますね。

    テストを成功させる

    次にHTML(app/views/static_pages/home.html.erb)にSample Appを加えて、テストを成功させます。

    <h1>Sample App</h1>
    <p>Find me in app/views/static_pages/home.html.erb</p>
    

    保存したら、もう一度$ rspec spec/requests/static_pages_spec.rbを実行します。

    $ rspec spec/requests/static_pages_spec.rb
    .
    
    Finished in 0.05663 seconds (files took 1.83 seconds to load)
    1 example, 0 failures
    

    無事成功しました。これで、テストが動くことを確認できました。
    初めてのテストはここまで。Ruby on Railsを読んで続きができたら次回を書きたいと思います。

    途中でエラーが出た方は以下を参考にしてみてください。

    エラーについて

    bundle installで起こるエラー

    bundle install時に下記のようなエラーが出たらXcodeのコマンドラインツールが古いかもしれません。$ xcode-select --installを試してみてください。

    Gem::Ext::BuildError: ERROR: Failed to build gem native extension.
    
        /Users/ryuichi/.rbenv/versions/2.1.0/bin/ruby extconf.rb
    Building nokogiri using packaged libraries.
    -----
    libiconv is missing.  please visit http://nokogiri.org/tutorials/installing_nokogiri.html for help with installing dependencies.
    -----
    *** 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
    source 'https://rubygems.org'
        --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/ryuichi/.rbenv/versions/2.1.0/bin/ruby
        --help
        --clean
        --use-system-libraries
        --enable-static
        --disable-static
        --with-zlib-dir
        --without-zlib-dir
        --with-zlib-include
        --without-zlib-include=${zlib-dir}/include
        --with-zlib-lib
        --without-zlib-lib=${zlib-dir}/lib
        --enable-cross-build
        --disable-cross-build
    
    extconf failed, exit code 1
    
    Gem files will remain installed in /Users/ryuichi/Projects/Labs/step4.rspec.rails/vendor/bundle/ruby/2.1.0/gems/nokogiri-1.6.3.1 for inspection.
    Results logged to /Users/ryuichi/Projects/Labs/step4.rspec.rails/vendor/bundle/ruby/2.1.0/extensions/x86_64-darwin-13/2.1.0-static/nokogiri-1.6.3.1/gem_make.out
    An error occurred while installing nokogiri (1.6.3.1), and Bundler cannot continue.
    Make sure that `gem install nokogiri -v '1.6.3.1'` succeeds before bundling.
    

    bundle install時にNokogiriに関するエラー

    このエラーが出たときはエラー内に解決方法が書かれています。$ bundle config build.nokogiri --use-system-librariesを実行してから$ bundle installしましょう。

    IMPORTANT!  Nokogiri builds and uses a packaged version of libxml2.
    
    If this is a concern for you and you want to use the system library
    instead, abort this installation process and reinstall nokogiri as
    follows:
    
        gem install nokogiri -- --use-system-libraries
    
    If you are using Bundler, tell it to use the option:
    
        bundle config build.nokogiri --use-system-libraries
        bundle install
    
    However, note that nokogiri does not necessarily support all versions
    of libxml2.
    
    For example, libxml2-2.9.0 and higher are currently known to be broken
    and thus unsupported by nokogiri, due to compatibility problems and
    XPath optimization bugs.
    ************************************************************************
    Building libxslt-1.1.28 for nokogiri with the following patches applied:
        - 0001-Adding-doc-update-related-to-1.1.28.patch
        - 0002-Fix-a-couple-of-places-where-f-printf-parameters-wer.patch
        - 0003-Initialize-pseudo-random-number-generator-with-curre.patch
        - 0004-EXSLT-function-str-replace-is-broken-as-is.patch
        - 0006-Fix-str-padding-to-work-with-UTF-8-strings.patch
        - 0007-Separate-function-for-predicate-matching-in-patterns.patch
        - 0008-Fix-direct-pattern-matching.patch
        - 0009-Fix-certain-patterns-with-predicates.patch
        - 0010-Fix-handling-of-UTF-8-strings-in-EXSLT-crypto-module.patch
        - 0013-Memory-leak-in-xsltCompileIdKeyPattern-error-path.patch
        - 0014-Fix-for-bug-436589.patch
        - 0015-Fix-mkdir-for-mingw.patch
    ************************************************************************
    IMPORTANT!  Nokogiri builds and uses a packaged version of libxslt.
    
    If this is a concern for you and you want to use the system library
    instead, abort this installation process and reinstall nokogiri as
    follows:
    
        gem install nokogiri -- --use-system-libraries
    
    If you are using Bundler, tell it to use the option:
    
        bundle config build.nokogiri --use-system-libraries
        bundle install
    ************************************************************************
    

    以上、はじめてのテストでした。

    シリーズ

    1. Ruby on Railsの最初の一歩
    2. Ruby on RailsアプリをHerokuにデプロイしてみる
    3. $ bundle exec を省略する
    4. Ruby on Railsで静的ページを作る
    5. Ruby on Rails:RSpecとCapybaraで初めてのインテグレーションテスト
    6. Ruby on Rails:埋め込みRubyを使った簡単な動的ページを作る
    7. Ruby on Rails:Guardを使ったテストの自動化

    コメント・フィードバック