楊曄
(浙江警官職業(yè)學(xué)院信息技術(shù)與管理系,浙江 杭州 310018)
基于BDD的自動化測試框架研究
楊曄
(浙江警官職業(yè)學(xué)院信息技術(shù)與管理系,浙江杭州310018)
敏捷開發(fā)模式的盛行掀起了自動化測試的一輪熱潮,測試和開發(fā)合作越來越密切。本文研究的自動化測試框架,將BDD的敏捷開發(fā)理念與軟件測試相融合,通過統(tǒng)一的Gherkin語言定義驗(yàn)收測試標(biāo)準(zhǔn),幫助業(yè)務(wù)人員、測試人員和開發(fā)人員形成對需求明確統(tǒng)一的認(rèn)識,然后通過web driver測試代碼實(shí)現(xiàn)可執(zhí)行的驗(yàn)收測試,以TDD的方式實(shí)現(xiàn)產(chǎn)品代碼。該框架使用Specflow、Selenium和MsTest等測試工具,真正實(shí)現(xiàn)了自動化測試,大大減少了手工測試的壓力,促進(jìn)開發(fā)測試過程中軟件開發(fā)涉眾之間的溝通,及時得到用戶反饋,滿足快速發(fā)布產(chǎn)品的需求,提升產(chǎn)品質(zhì)量。
自動化測試;BDD;Specflow;Selenium;Scenario
隨著信息化步伐不斷加快,軟件作為處理業(yè)務(wù)和提供服務(wù)的重要保障,其開發(fā)任務(wù)日趨繁重,各類管理軟件也變得越來越龐大和復(fù)雜,這就對軟件測試提出了更高的要求。為了節(jié)省大量的時間和開支,必須使用自動化測試技術(shù)代替效率低下的手工測試,節(jié)省軟件測試成本,縮短產(chǎn)品發(fā)布周期。
雖然現(xiàn)在有很多錄制/回放的測試工具可用于自動化測試,但是由于捕捉方式產(chǎn)生腳本的數(shù)據(jù)硬編碼問題,測試人員需要不斷地修改腳本以適應(yīng)應(yīng)用程序的變化,導(dǎo)致測試效率并沒有得到有效提高。因此本文結(jié)合敏捷測試流程和自動化實(shí)施方法,給出基于BDD的自動化測試框架設(shè)計和應(yīng)用分析。
軟件開發(fā)過程中最常見的兩個問題是需求和開發(fā)脫節(jié)、開發(fā)和測試脫節(jié)。用戶想要的功能沒有開發(fā),開發(fā)的功能并非用戶想要,用戶和開發(fā)人員所說語言不同。開發(fā)和測試被認(rèn)為是割裂的,從開發(fā)到測試周期過程,測試自動化程度低。使用BDD(Behavior Driven Development,行為驅(qū)動開發(fā))技術(shù)可以解決需求和開發(fā)脫節(jié)的問題,從用戶的需求出發(fā),保證程序?qū)崿F(xiàn)效果與用戶需求一致。BDD的出現(xiàn)解決了測試驅(qū)動開發(fā)中常遇到的問題,比如從哪里開始測試,應(yīng)該測試什么,不應(yīng)該測試什么等。
BDD在繼承TDD(Test Driven Development,測試驅(qū)動開發(fā))的基礎(chǔ)上,通過為驗(yàn)收測試創(chuàng)建測試,實(shí)現(xiàn)關(guān)注點(diǎn)分離,優(yōu)化過程管理。BDD開發(fā)關(guān)注用戶情景以及圍繞這些情景建立邏輯和測試,通過領(lǐng)域特定語言(Domain Specific Language,DSL)來描述系統(tǒng)行為,再以這些行為為驅(qū)動,編寫產(chǎn)品代碼來實(shí)現(xiàn)這些行為。通過Domain的表達(dá)方式,來描述系統(tǒng)的Feature與用戶的Scenario,并依據(jù)這些Scenario來產(chǎn)生對應(yīng)的code flow template,接著可結(jié)合單元測試的3A原則,即Arrange-Act-Assert,來驗(yàn)證系統(tǒng)功能是否有滿足這些Scenario。
自動化測試框架融合框架開發(fā)思想,結(jié)合測試流程和工具,能夠?qū)崿F(xiàn)自動化測試的規(guī)?;岣邷y試效率,保證測試質(zhì)量。自動化測試框架的好壞直接影響到自動化測試的成功與否。一個完整的自動化框架能夠?yàn)闇y試人員提供測試用例的設(shè)計、開發(fā)、執(zhí)行、結(jié)果分析的界面,為測試過程提供數(shù)據(jù)保存的場所,為測試執(zhí)行提供驅(qū)動。在此基礎(chǔ)上,才能為測試實(shí)現(xiàn)自動化提供技術(shù)可能,加上團(tuán)隊、流程、管理的配合,最終形成一個完整的軟件測試自動化解決方案。本文提出的基于BDD的自動化測試框架圖如圖1所示。
圖1 基于BDD的自動化測試框架圖
該框架融合BDD的開發(fā)流程和分層測試的理念,能夠適應(yīng)敏捷開發(fā)的測試流程,將測試活動前置,實(shí)現(xiàn)了需求的實(shí)例化和可執(zhí)行,真正實(shí)現(xiàn)了自動化驗(yàn)收測試帶來的收益,從而讓團(tuán)隊真正享受到自動化測試帶來的收益。同時該框架使及時全面的回歸測試、穩(wěn)定性測試、兼容性測試成為可能,為持續(xù)集成提供基礎(chǔ),便于重現(xiàn)或校驗(yàn)偶發(fā)性缺陷。
在框架中,首先獲取客戶的商業(yè)目標(biāo),找到特征功能,編寫用戶故事,定義與管理用戶需求。然后編寫驗(yàn)收測試用例,定義用戶故事的完成事項(xiàng),使用BDD規(guī)范的Feature和Scenario,描述驗(yàn)收測試用例所對應(yīng)的系統(tǒng)行為,這樣在驗(yàn)證軟件的同時,自動升級了技術(shù)和功能文檔,更容易開發(fā)出高質(zhì)量的代碼,易于使用、維護(hù)和測試。使用UI測試和Service測試技術(shù)編寫相應(yīng)的Step Template,生成自動化的驗(yàn)收測試用例,這樣就形成了可執(zhí)行的需求規(guī)范。然后進(jìn)入TDD的循環(huán)過程,以測試驅(qū)動完成生產(chǎn)代碼的編寫,同時完成Unit測試。
進(jìn)行BDD實(shí)踐首先要解決兩個問題,一是如何實(shí)現(xiàn)一個能夠描述系統(tǒng)行為(業(yè)務(wù)價值)、非技術(shù)人員可讀的測試,二是如何讓這個測試變得可執(zhí)行。目前有很多工具可在開發(fā)過程中實(shí)現(xiàn)BDD,包括Jbehave、Cucumber、Lettuce、Rspec和SpecFlow等。這些BDD框架各自提供了一套DSL,開發(fā)人員可以使用DSL描述業(yè)務(wù)需求。同時,這些框架都依賴于Web Driver,BDD框架通過Web Driver調(diào)用瀏覽器的接口,模擬用戶輸入,讀取瀏覽器頁面上顯示的內(nèi)容用于驗(yàn)證。
在本文中的BDD工具,我們將采用ASP.NET MVC框架進(jìn)行開發(fā),IDE使用Microsoft Visual Studio。在測試框架中,我們將采用SpecFlow和WebDriver工具Selenium實(shí)現(xiàn)自動化驗(yàn)收測試,Service測試和Unit測試將采用MSTest。
已知某單位的設(shè)備管理系統(tǒng),可以實(shí)現(xiàn)對設(shè)備的信息管理、報修處理等功能?,F(xiàn)將使用基于BDD的自動化測試框架,實(shí)現(xiàn)并測試登錄模塊。
(1)用SpecFlow描述業(yè)務(wù)價值
在自動化驗(yàn)收測試層,我們首先安裝配置好BDD測試框架工具SpecFlow,然后根據(jù)用戶需求故事和驗(yàn)收條件,編寫Features和Scenarioes腳本。當(dāng)前登錄功能可以劃分為以下幾個場景:
1)用戶名密碼匹配,登錄成功;
2)用戶名或密碼不匹配,登錄失敗,并給出相應(yīng)提示。
BDD使用Gherkin語言來定義系統(tǒng)行為。Gherkin是一種領(lǐng)域特定語言,它允許我們在不解釋具體執(zhí)行細(xì)節(jié)的情況下,詳細(xì)描述應(yīng)用應(yīng)該如何執(zhí)行。需求的大部分內(nèi)容是由自由文字組成,只有幾個特定的Gherkin關(guān)鍵字:Feature、Scenario、Given、When、And和Then,其他的都是自由文字,并且主要記錄了功能特性是如何被使用的。Gherkin是一種基于行的編程語言,場景中的每一行(Line)就是一個步驟(Step)。
以用SpecFlow的DSL描述登錄成功任務(wù)作說明,其他情況相同,得到測試場景代碼如下:
Feature:User Login
In order to access my account As a user of the website
I want to log into the website
Background:There is a user with the following login detail:
|LoginName|Password|
|my@example.com|test|
Scenario:Login succeed
Given the user is at the login page
When the user fill in the account information:
|LoginName|Password|
|my@example.com|test|
And the user click the login button
Then the user should be at the
|http://localhost:57499/Consumer/Index|
And the page should display the
|pageContent|
|我的設(shè)備管理系統(tǒng)|
這些代碼計劃就是遵循了一定格式的英語,即使看不懂代碼的產(chǎn)品經(jīng)理、業(yè)務(wù)分析師也能夠通過此文檔和開發(fā)人員順暢地交流。用Specflow把一個需求的不同場景描述出來,也是從不同角度闡述了這個需求的業(yè)務(wù)價值。Specflow的目標(biāo)就是書寫可執(zhí)行的,能夠表述業(yè)務(wù)價值的文檔。
(2)Web Driver與頁面交互
接下來需要讓文檔執(zhí)行起來,Specflow提供了把業(yè)務(wù)邏輯轉(zhuǎn)換為可執(zhí)行代碼的機(jī)制Step Definition。然后我們使用Web Driver,像真實(shí)用戶那樣打開瀏覽器,輸入用戶名密碼,點(diǎn)擊提交按鈕,驗(yàn)證登錄是否成功。這里我們選用了比較流行的Web Driver框架Selenium 2,具體Step Definition實(shí)現(xiàn)代碼如下:
[Binding]
public class UserLoginSteps
{
private IWebDriver driver;
[Given(@"the user is at the login page")]
public void GivenTheUserIsAtTheLoginPage()
{
driver=new FirefoxDriver();
driver.Navigate().GoToUrl("http://localhost:57499/Account/Login");
}
[When(@"the user fill in the account information:")]
public void WhenTheUserFillInTheAccountInformation (Table table)
{
driver.FindElement(By.Id("LoginName")).SendKeys(table.Rows[0][0]);
driver.FindElement(By.Id("Password")).SendKeys(table. Rows[0][1]);
}
[When(@"the user click the login button")]
public void WhenTheUserClickTheLoginButton()
{
driver.FindElement(By.Id("loginSubmit")).Click();
}
[Then(@"the user should be at the(.*)page:")]
public void ThenTheUserShouldBeAtThePage(string p0, Table table)
{
var expectedURL=table.Rows[0][0];
var actualURL=driver.Url;
Assert.AreEqual(expectedURL,actualURL,"沒有跳轉(zhuǎn)到{0}的頁面。",p0);
} [Then(@"the page should display the(.*)information:")] publicvoid ThenThePageShouldBeDisplayedCorrectly (string p0,Table table)
{
string expectedWords=table.Rows[0][0];
string actualWords=driver.FindElement(By.XPath("html/body/div[1]/div/h1")).Text;
bool isContained=actualWords.Contains(expected-Words);
Assert.IsTrue(isContained,"頁面中沒有找到要檢查的詞語{0}",p0);
driver.Close();
driver.Quit();
driver=null;
}
這段代碼將打開瀏覽器,訪問地址 http://localhost: 51426/Account/Login/,在郵件輸入框輸入“my@example. com”,在密碼輸入框輸入“test”,點(diǎn)擊“登錄”按鈕,驗(yàn)證測試結(jié)果是否正確跳轉(zhuǎn)到“http://localhost:51426/Consumer/Index”,并且打開的頁面包含登錄成功后的“學(xué)生后臺管理首頁”字樣,如果成功,則測試通過,否則失敗。
Web Driver通過調(diào)用瀏覽器的支持自動化的API,模擬真實(shí)用戶在瀏覽器上的操作。把這段代碼放在上面的Step Definition中,當(dāng)Specflow測試運(yùn)行的時候,這段代碼就會運(yùn)行,完成登錄操作。
(3)運(yùn)行自動化驗(yàn)收測試
通過Specflow對需求進(jìn)行編碼,并使用Selenium將其轉(zhuǎn)換成驗(yàn)收測試,這樣真正實(shí)現(xiàn)了和代碼相關(guān)的驗(yàn)收測試,并且可以不依賴具體實(shí)現(xiàn),而是從UI層上進(jìn)行確認(rèn)。運(yùn)行驗(yàn)收測試的方法可以使用Visual Studio的測試資源管理器,同時使用MSTest。此處以MSTest為例,結(jié)果如下:
*****KnowledgeDot.Test.Specs.Features.LoginFeature.Login-SucceedAsStudent_Given I am at the login page
->done:LoginSteps.GivenIAmAtTheLoginPage()(8.3s)
When I fill in the account information:
---table step argument---
|UserName|Password|Role|
|stu|stu|學(xué)生|
->done:LoginSteps.WhenIFillInTheFollowingForm(