読みやすい(?)RSpecのfeature test、この発想はなかったわ・・・

Ruby Weekly経由で知ったのですが、読みやすいRSpecのfeature testを書く方法、この発想はなかったわ・・・って感じです。

Cucumberぽく読めるように書く

元ネタはこの記事、How we write readable feature tests with RSpec

Cucumberではこんな感じのコードでfeature testを表現できてリーダブルだけど、

Feature: Enrolment
  Scenario: Enrolling in a course
    Given there is a course
    And I am logged in as a learner
    When I enrol on a course
    Then the course should appear in 'my courses'

RSpecでのfeature testはこんな感じのコードになっちゃって、リーダブルとは言いづらいよね、という話。

feature 'Enrolment' do
  scenario 'Enrolling in a course' do
    course = FactoryGirl.create(:course)
 
    learner = FactoryGirl.create(:learner)
    login_as learner
 
    visit course_path(course)
    find('.join').click
    expect(page).to have_content('Thanks for joining!')
 
    visit '/'
    expect(page).to have_main_header('My Courses')
    expect(page).to have_content(course.full_title)
  end
end

だからCucumberぽく読めるようにこう書くよ!

feature 'Enrolment' do
  scenario 'Enrolling in a course' do
    given_there_is_a_course
    and_i_am_logged_in_as_a_learner
    when_i_enrol_on_a_course
    then_the_course_should_appear_in_my_courses
  end
 
  def given_there_is_a_course
    @course = FactoryGirl.create(:course)
  end
 
  def and_i_am_logged_in_as_a_learner
    @learner = FactoryGirl.create(:learner)
    login_as @learner
  end
 
  def when_i_enrol_on_a_course
    visit course_path(@course)
    find('.join').click
    expect(page).to have_content('Thanks for joining!')
  end
 
  def then_the_course_should_appear_in_my_courses
    visit '/'
    expect(page).to have_main_header('My Courses')
    expect(page).to have_content(@course.full_title)
  end
end

うーん、気持ちは分からなくもないけど、Cucumberでのパターンマッチがなくなった分、退化しているような感じが・・・。

更にRubyでは日本語のメソッドも定義できるので、こんな風に書けたりもするかも。

feature '登録' do
  scenario 'コース登録' do
    前提:対象のコースがあること
    かつ:学習者としてログインしていること
    もし:対象のコースに登録するとき
    ならば:自分のコースに対象のコースが表示されること
  end
end

しかしコードレビューのときにこんなfeature testがいきなり出てきたら、かなり物議を醸しそうだ。