目錄
回顧
在上一節中,我大致的介紹了一下cucumber的特點,以及基於ruby和JavaScript下關於cucumber環境的配置,如果你還沒有進行相關的了解或者環境的配置,你可以點擊這里來進行了解一下
在本節中,我將借用一個場景來對cucumber的一些特點來進行描述
HelloWorld
1.cucumber的目錄結構
cucumber的執行需要特定的目錄結構的。我們首先需要先創建這樣的一個目錄結構:
mkdir HelloWorld cd HelloWorld mkdir features cd features touch hello_cucumber.feature mkdir step_definitions cd step_definitions touch hello_cucumber.rb通過上面的命令創建好如下圖的目錄層級結構:
在圖中,HelloWorld這個目錄下面包含了一個名為features目錄,在features目錄下面有一個名為hello_cucumber.feature的文件以及一個名為step_definitions的目錄,在step_definitions這個目錄下面有一個名為hello_cucumber.rb的文件。下面解釋下各個目錄以及文件的作用:
HelloWorld
這個根目錄可以理解為工程所在的目錄,存放了所有需要用到的文件和資源
features
這個目錄下面包含了所有的場景文件和實現場景文件中描述的步驟文件
hello_cucumber.feature
這個文件包含了場景的描述,也就是對測試用例的描述,里面一般交代了測試的前提和測試需要的條件並且當發生某一事件的時候能夠得到一個什么樣的結果,這些描述一般使用很易懂的自然語言來進行描述它,所以技術或者非技術人員都能看懂
在features目錄下可以包含一個或者多個feature文件,一般情況下,對於具有相同性質的測試場景會放到同一個feature文件中,以便於維護
step_definitions
這個目錄包含了實現測試場景描述的步驟文件
hello_cucumber.rb
這個文件包含對應的測試場景的實現代碼,這個步驟文件取決於你使用的什么語言,我這里是使用的ruby
2.代碼
代碼主要是包含在hello_cucumber.feature和hello_cucumber.rb文件中
hello_cucumber.feature
這里我們主要描述這樣一個場景,以平常一個登陸系統來做為例子吧。在測試中的話,首先會有對這個登陸系統的描述和一些基本的需求。主要是作為一個登陸系統的使用者,希望登陸系統的運作正常。正常的使用中,一個登陸場景如下:
前置條件:進入到登陸頁面
事件: 在用戶名輸入框輸入正確的用戶名,在密碼框輸入正確的密碼,點擊確定
預期結果:成功登陸
這是一個比較簡單的測試用例,看看在cucumber中是如何實現它的。
首先我們先要將這個用例轉換成cucumber所知道的描述語言,這部分描述是在feature文件中來進行實現的。代碼如下:
Feature: Login Login system should work fine Scenario: Login with right username and right password Given I open the login page When I set username with a right username And I set password with a right password And I click the login button Then I see login success代碼中的Feature,Scenario,Given,And,When,Then都是cucumber中的關鍵字,Feature說明了這個測試場景的大體情況和一些基本的描述,一般由需求人員和測試人員去完成,Scenario指明了具體場景的標題,以及這個場景是用來干什么的。Given給出了具體的測試場景的條件,When給出了事件,And表示一個連接,Then是預期的結果。在一個feature文件中可以包含多個Scenario。
hello_cucumber.rb
這個文件主要包含了feature文件中描述的場景的實現,代碼如下
Given /^I open the login page$/ do puts "open login page" end When /^I set username with a right username$/ do puts "set a right username" end When /^I set password with a right password$/ do puts "set a right password" end When /^I click the login button$/ do puts "click login button" end Then /^I see login success$/ do puts "login success" end在feature文件中的每一個步驟都需要一個相應的ruby代碼來與之對應,如果沒有對應的實現步驟,則在執行用例的時候會出現找不到步驟的異常。在feature尋找步驟的時候,是通過正則表達式來進行匹配的,step文件中的Given /^...$/會匹配feature文件中符合這個正則的步驟。這個匹配是會忽略Given When之類的關鍵字的。如果在匹配的時候feature中的步驟沒有找到step中對應的實現,則才執行的時候會報出忽略這一個步驟的異常而導致用戶不會通過的。
3.運行用例
在命令行下進入到HelloWorld這個文件夾,然后輸入命令 cucumber features/hello_cucumber.feature,結果如下:
從結果中看出,我們的用例全部的通過了。而且,我們在ruby文件(step文件)中的日志也都被打印出來了(天藍色字)。
關於cucumber的命令,我會在后面仔細的來進行介紹的。
擴展
通過上面的例子,我們已經可以使用cucumber的基本功能去實現一些用例了。當然前提還需要你去了解一些自己熟悉的語言的一些測試框架,不然單純的cucumber並不能起到太大的作用。
現在我們來進行擴展一下上面的需求。依舊是登錄的例子。測試用例如下:
前置條件:進入到登陸頁面
事件: 在用戶名輸入框輸入正確的用戶名,在密碼框輸入錯誤的密碼,點擊確定
預期結果:成功失敗
根據剛剛所說的,寫下的如下的feature:
Feature: Login Login system should work fine Scenario: Login with right username and error password Given I open the login page When I set username with a right username And I set password with a error password And I click the login button Then I see login fail對應的step如下:
Given /^I open the login page$/ do puts "open login page" end When /^I set username with a right username$/ do puts "set a right username" end When /^I set password with a error password$/ do puts "set a error password" end When /^I click the login button$/ do puts "click login button" end Then /^I see login success$/ do puts "login fail" end代碼寫到這里就完成了,但是軟件工程中一個重要的思想是復用,相同的東西是否能進行提取呢?在上面的2個例子中,在設置密碼這個地方,步驟基本是相同的,只是輸入的值不一樣,我們是否可以將這2個步驟合成一個呢?答案是可以的。修改設置密碼的step:
When /^I set password with a (.*) password$/ do |password| puts "set a #{password} password" end經過這樣的修改后發現feature中密碼中輸入步驟也能匹配到step對應的實現,而且能將right或者是error提取成一個參數傳入到實現中。
feature中的參數化使得我們很少做很多的重復工作。
聰明的你又想起了另外的一個需求,比如我們的登錄的例子需要在chrome和firefox上面去執行。也許你會想,我們直接把上面的第一步(打開瀏覽器進入login頁)修改成匹配chrome和firefox的通用步驟,然后其他的copy一遍就ok。這樣做是ok的,然而cucumber提供了一種更為聰明的方法來進行這個操作。
feature如下:
Feature: Login Login system should work fine Scenario Outline: Login with right username and right password Given I use <browser> open the login page When I set username with a right username And I set password with a right password And I click the login button Then I see login success Examples: | browser | | chrome | | firefox |step如下:
Given /^I use (.*) open the login page$/ do |browser| puts "use #{browser} open login page" end When /^I set username with a right username$/ do puts "set a right username" end When /^I set password with a (.*) password$/ do |password| puts "set a #{password} password" end When /^I click the login button$/ do puts "click login button" end Then /^I see login success$/ do puts "login success" end在feature中,將前面Scenario改為了Scenario Outline,表示會有表格參數,參數使用<>來進行標注,在用例結束后Examples關鍵字中寫入參數的具體值。這樣后,在執行用例的時候,這個用例會被執行2次,每次執行會依次的采用Examples中的參數來進行執行,我們使用命令來執行看看結果:
從結果中可以看出我們執行了2個Scenario,打出的日志在Examples下面,第一個使用了chrome,第二個使用了firefox,和我們的預期是一樣的。使用Examples能大幅的減輕我們的工作量。
在cucumber中還存在着另外一個table參數。我們看看他的使用場景。依舊是登錄頁,但是現在登錄頁和之前的不太一樣,我們的系統是非常注重安全的,所以每一個用戶登錄的時候需要使用2個密碼來進行登錄,如果密碼全部都正確才能登錄成功。測試用例如下:
前置條件:進入到登陸頁面
事件: 在用戶名輸入框輸入正確的用戶名,在第一個密碼框輸入正確的密碼,在第二個密碼框輸入正確的密碼,點擊確定
預期結果:成功登錄
先看看feature:
Feature: Login Login system should work fine Scenario: Login with right username and right password Given I open the login page When I set username with a right username And I set password | id | value | | password1 | value1 | | password2 | value2 | And I click the login button Then I see login success在看看step:
Given /^I open the login page$/ do puts "open login page" end When /^I set username with a right username$/ do puts "set a right username" end When /^I set password/ do |table| table.hashes.each do |item| puts "set #{item["id"]} to #{item["value"]}" end end When /^I click the login button$/ do puts "click login button" end Then /^I see login success$/ do puts "login success" end在feature中,我們也使用了一個表格的形式,在step中可以通過一個參數直接獲取到這個表格中的所有的參數,並且將他們存入到了hash中,而我們可以對這個hash進行操作,然后獲取我們想要的值。
執行用例后如下:
可以看到結果和我們想要的是一樣的。
在cucumber中有時候還會使用到步驟的組合。依舊采用登錄這個例子。他里面所有的feature和使用的第一個例子一樣。我們仔細想想里面的步驟中的第一步(打開登錄頁面),它實際是由打開瀏覽器和跳轉到登錄頁面這2個步驟實現的,現在我們不改變feature,看看step中如何把這一步分解成為2步:
Given /^I open the login page$/ do steps %{ Given I launch the browser And I go to login page } end When /^I set username with a right username$/ do puts "set a right username" end When /^I set password with a right password/ do puts "set a right password" end When /^I click the login button$/ do puts "click login button" end Then /^I see login success$/ do puts "login success" end Given /^I launch the browser$/ do puts "launch browser" end Given /^I go to login page$/ do puts "go to login page" end在上面的step中,我們將之前的一步分解成了2步,這2步又被另外的一個step所調用。你也可以用下面的方式來實現它:
Given /^I open the login page$/ do step "I launch the browser" step "I go to login page" end看看執行的結果:
結果如我們所預期的一樣。
關於cucumber的基本語法就講到這里了,如果感覺我有漏掉的希望大家可以提出。