天天看點

使用RSpec編寫具有可讀性的功能測試

  測試是建立與維護一個大型平台不可或缺的一部分。每當我們為futurelearn這個平台增添新功能時,我們都會編寫自動化的功能測試來記錄這些新功能是如何運作的,并確定他們不運轉時我們也能知曉。

  令人愛恨交加的cucumber

  cucumber是一款用來編寫功能測試的常用工具,每當我們開啟項目時它都是我們的不二選擇。它可以讓我們以使用者的視角編寫出高層級的行為驅動測試。

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 features

  那麼,我麼該如何在不失測試可讀性的前提下停用cucumber呢?

  我們已經開始使用rspec features來替代cucumber,它們通常看起來會是這樣:

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

  它們總是趨于變得很長,使得難以辨明其究竟在測試些什麼。而且難以區分諸如arrange, act, assert(在cucumber裡又被稱為’given’、’when’和’then’)這些部分。我們試過在代碼中這些步驟裡添加注釋,但它們就和通常那些程式代碼裡的注釋一樣不盡如人意:一段時間之後這些注釋就變得與實際代碼不同步了。

  一般來說,如果是在程式裡别的地方寫出這麼長的方法,我們就會有所警覺,并且通常會采用提取方法的辦法進行重構。何不也這麼做呢?讓我們依據cucumber步驟的風格,把這些代碼也提取成一個個方法吧。

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

def given_there_is_a_course

@course = factorygirl.create(:course)

def and_i_am_logged_in_as_a_learner

@learner = factorygirl.create(:learner)

login_as @learner

def when_i_enrol_on_a_course

visit course_path(@course)

def then_the_course_should_appear_in_my_courses

expect(page).to have_content(@course.full_title)

  我們有何發現

  我們移除了全部的cucumber功能測試,并把它們中大部分用新式的rspec features加以重寫。這樣一來即可保證擁有cucumber所提供的優秀的可讀性,又使得測試變得更加便于編寫和維護。

  我們做了一個慎重的決定,不把各個features檔案裡提取的方法進行複用,因為擔心這麼做會使得測試難于了解。我們發現在編寫一個feature下的多條scenario時,會不自覺的就想要進行代碼複用。

最新内容請見作者的github頁:http://qaseven.github.io/

繼續閱讀