中年エンジニアの開発と生活の日々

中年エンジニアがソフトウェア開発や日々の生活で得た知見の備忘録

Turnip の RSpec で関数を定義して呼び出すには

現在、Turnip と RSpec を組み合わせて Ruby でテストスクリプトを作成しているのですが、共通な処理を関数にまとめる方法についてまとめてみました。

Turnip については以下のサイトが詳しいです

Rubyist Magazine - エンドツーエンドテストの自動化は Cucumber から Turnip へ

Turnipでは Feature ファイルと Stepファイルに分かれていて、Step ファイルは RSpec でテストスクリプトを記述していきます。

RSpecについては以下のサイトが詳しいです relishapp.com

テストスクリプトを書いていると実感するのですが、同じ処理をパラメータを変えて繰り返すことが多いです。そのため、同じ処理を関数として定義して呼び出さないと見通しが悪いですし、メンテナンスも大変です。ところが、通常の Ruby のやり方ではうまくいきません。

たとえば、Stepファイルに以下のようにして関数を定義して、Step の中で呼びだしてみます。

  def putsHogehoge
    puts "hogehoge"
  end

step "Step1" do
  putsHogehoge
end

通常の Ruby でしたら、"Step1" の中で putsHogehoge がコールされてコンソールに “hogehgoe” と表示されますが、Turnip で Feature ファイルからこのStep1を呼び出すと以下のようなエラーメッセージが表示されます。

Failures:

  1) Test Sample Given GetParam
     Failure/Error: putHogehoge

     NameError:
       undefined local variable or method `putsHogehoge' for #<RSpec::ExampleGroups::Test::Sample:0x007fb676a58ac8>
     # spec/steps/sample_steps.rb:13:in `block in <top (required)>'
     # ./vendor/bundle/ruby/2.3.0/gems/turnip-2.1.1/lib/turnip/execute.rb:25:in `step'
     # ./spec/features/login.feature:5:in `run_step'
     # ./vendor/bundle/ruby/2.3.0/gems/turnip-2.1.1/lib/turnip/rspec.rb:44:in `instance_eval'
     # ./vendor/bundle/ruby/2.3.0/gems/turnip-2.1.1/lib/turnip/rspec.rb:44:in `run_step'
     # ./spec/features/sample.feature:6:in `block (4 levels) in run_feature'
     # ./spec/features/sample.feature:5:in `each'
     # ./spec/features/sample.feature:5:in `block (3 levels) in run_feature'
     # ./spec/features/sample.feature:5:in `Step1'

Step1 は Turnip のフレームワークから呼び出されているようで、すぐ上に定義されている putsHogehoge という関数が見えないようです。

解決策

以下のサイトを参考に Turnip で拡張されている箇所のつじつまを合わせたら、Helper Method を呼び出すことができました。 relishapp.com

  • Spec フォルダに helpers.rb を作成します。別に stepsディレクトリに作成してもよい気もしますが、Step ではなく、Helper なので一つ上のディレクトリに格納しています。
  • helpers.rb に Helpers Module を定義して、その中に関数を定義します
# coding: utf-8

module Helpers
  def putsHogehoge
    puts "hogehgoe"
  end
end
  • spec_helper.rb に require ‘./spec/helpers’ を追加します。
require 'rubygems'
require 'selenium-webdriver'
require 'appium_lib'
require 'bundler/setup'
require './spec/helpers'  # <- 追加
  • spec_helper.rb の RSpec configure に c.include Helpers を追加。これにより、Helpers Module が各 Step でロードされます。
RSpec.configure do |c|
  c.include Helpers # <- 追加

  c.before(:each) {
    @driver = Appium::Driver.new(desired_caps).start_driver
    @driver.manage.timeouts.implicit_wait = 5
    Appium.promote_appium_methods Object
  }
  c.after(:each) {
    @driver.quit
  }
end

こうすることによって、Turnip の Step ファイルから自分で定義した関数を呼び出せるようになりました。