背景
時(shí)間回到2022年绸栅,我參與了一個(gè)使用了Flutter技術(shù)構(gòu)建的Web前端項(xiàng)目螺男。在這個(gè)項(xiàng)目上,我們小組的目標(biāo)是實(shí)施Flutter前端自動(dòng)化測(cè)試粘秆。
彼時(shí)如迟,F(xiàn)lutter 2.x剛在Web端發(fā)力不久,F(xiàn)lutter Web上的應(yīng)用和生態(tài)才剛剛開始攻走,而在這一切激進(jìn)的技術(shù)棧上構(gòu)建一套自動(dòng)化方案的需求又迫在眉睫殷勘。
在技術(shù)選型上,我們使用了類Cucumber測(cè)試的方案昔搂,使用Gherkin語言構(gòu)建一套自動(dòng)化語言步驟庫(kù)玲销。Gherkin語言有時(shí)候又被稱為小黃瓜語言,它是第一種有著類似自然語言可讀性的業(yè)務(wù)語言摘符,用來描述業(yè)務(wù)行為贤斜,而不必關(guān)心具體的實(shí)現(xiàn)細(xì)節(jié)。它也是一種領(lǐng)域特定的語言逛裤,用來定義Cucumber格式的測(cè)試瘩绒。
通過不斷地改進(jìn),我們使得這些步驟既具有自然語言通俗易懂的可讀的特性带族,又具有自動(dòng)化步驟的可執(zhí)行性锁荔,用這套步驟,我們最終用它統(tǒng)一了手工測(cè)試用例和自動(dòng)化測(cè)試用例的書寫蝙砌,執(zhí)行阳堕,管理。
文檔式Gherkin和動(dòng)作式Gherkin的區(qū)別
Gherkin語言其實(shí)可以使用不同國(guó)家語言的單詞和語法書寫择克,但和其他編程語言一樣恬总,我們這里還是使用英文單詞和文法。
當(dāng)定義步驟庫(kù)的時(shí)候肚邢,使用Gherkin語言去描述業(yè)務(wù)或者用例可以有不同的風(fēng)格壹堰,典型的有“文檔式Gherkin”和“動(dòng)作式Gherkin”這兩大類。
文檔式Gherkin往往用來描述“應(yīng)該做些什么”道偷。所以經(jīng)常用來描述軟件需求缀旁,產(chǎn)品期望行為。
比如一個(gè)步驟是:“當(dāng)創(chuàng)建了一個(gè)新用戶的時(shí)候勺鸦,那么他會(huì)出現(xiàn)在新用戶列表中”并巍。這種風(fēng)格的好處就是可以快速書寫出一個(gè)結(jié)構(gòu)合適,方便理解的軟件文檔换途。當(dāng)這種文檔式Gherkin語言寫的測(cè)試執(zhí)行失敗的時(shí)候懊渡,往往代表了產(chǎn)品的實(shí)際行為和文檔上的期望行為發(fā)生了背離刽射。當(dāng)然文檔式Gherkin語句也有其缺點(diǎn),比如自動(dòng)化實(shí)現(xiàn)起來剃执,某些語句需要驗(yàn)證的范圍會(huì)非常大誓禁,執(zhí)行復(fù)雜,且隨著測(cè)試的增加肾档,步驟庫(kù)里的步驟數(shù)量也會(huì)快速地增長(zhǎng)摹恰。
相比文檔式Gherkin,動(dòng)作式Gherkin描述的是“如何做些什么”怒见,由于動(dòng)作式Gherkin關(guān)注的是每一步具體做什么俗慈,所以常用作寫測(cè)試用例。如一個(gè)步驟是“當(dāng)點(diǎn)擊含有Submit文字的按鈕遣耍,那么Successfully文字應(yīng)該可見”闺阱。
動(dòng)作式Gherkin語句的好處就是目的單一,每一步需要驗(yàn)證的點(diǎn)很小舵变,當(dāng)然與之而來的缺點(diǎn)就是要完成一個(gè)用例的書寫需要很多步驟組成酣溃,用例里的步驟會(huì)很多,用例變得很長(zhǎng)纪隙。且每一個(gè)動(dòng)作對(duì)測(cè)試場(chǎng)景的覆蓋率都不高赊豌,需要完成測(cè)試覆蓋率要很多步驟一同拼湊起來。
文檔式Gherkin風(fēng)格詳解
由于我們需要大量自動(dòng)化測(cè)試用例瘫拣,所以我們更傾向于使用動(dòng)作式Gherkin亿絮,雖然最終我們使用了動(dòng)作式的Gherkin語言定義了自動(dòng)化步驟庫(kù)告喊,但我們還是先了解一下文檔式Gherkin的風(fēng)格麸拄。
文檔式Gherkin使用描述性的措辭,聚合了具體的動(dòng)作黔姜。這使讀者能夠快速理解一個(gè)場(chǎng)景拢切,并掌握文檔中描述的軟件功能。使用文檔式Gherkin語言寫的軟件需求或者測(cè)試秆吵,并由自動(dòng)化實(shí)現(xiàn)執(zhí)行后淮椰,這個(gè)文檔基本上不會(huì)過時(shí)。因?yàn)橐坏┸浖?shí)際行為和需求文檔的描述發(fā)生了背離纳寂,那么自動(dòng)化執(zhí)行需求文檔上的Gherkin語句的時(shí)候主穗,測(cè)試就會(huì)失敗。而這些測(cè)試往往都是以天為粒度去執(zhí)行的毙芜,如果今晚你提交了代碼改變軟件行為而沒有更新需求文檔忽媒,當(dāng)晚的自動(dòng)化測(cè)試流水線就會(huì)失敗紅掉。如果你的項(xiàng)目有流水線”紅不過夜”(導(dǎo)致流水線失敗變紅的問題不留到第二天而是當(dāng)天內(nèi)解決)的規(guī)定腋粥,那么恭喜晦雨,今晚就必須把文檔上由Gherkin語言書寫的測(cè)試修正架曹。
使用場(chǎng)景:書寫可測(cè)試的軟件需求說明書
例子:
When the admin creates a new user
Then the user list should contain the newly created user
規(guī)則1:使用不大于5個(gè)步驟的Scenario場(chǎng)景
Scenario是Gherkin語言中的關(guān)鍵字,通常代表一個(gè)場(chǎng)景闹瞧。作為一個(gè)經(jīng)驗(yàn)法則绑雄,一個(gè)文檔式Gherkin寫的場(chǎng)景通常由3-5個(gè)步驟組成。有時(shí)候奥邮,就連包含Given的步驟也不需要万牺,那么便只需要2個(gè)左右步驟了。當(dāng)然洽腺,長(zhǎng)的場(chǎng)景可能包含了多于5個(gè)Gherkin步驟杏愤,此時(shí)便可能說明了這個(gè)場(chǎng)景需要拆分了,讓更多更小的場(chǎng)景去覆蓋每一個(gè)需要關(guān)注的點(diǎn)已脓。
同時(shí)珊楼,前置條件也是可以隱式說明的。比如度液,在描述產(chǎn)品行為的時(shí)候厕宗,對(duì)于每個(gè)與登錄頁(yè)面本身無關(guān)的場(chǎng)景,可以預(yù)期用戶已經(jīng)登錄了堕担。每一個(gè)場(chǎng)景一般只應(yīng)該包含一個(gè)“Then”已慢。
如果有多個(gè)包含Then的步驟,那么就說明這個(gè)場(chǎng)景有多個(gè)AC(Acceptance Criteria)霹购。如果Then語句執(zhí)行失敗佑惠,那么此AC便校驗(yàn)失敗了,測(cè)試便會(huì)停止齐疙,那么后面的AC步驟也不會(huì)去執(zhí)行驗(yàn)證膜楷,于是在失敗的路徑下多個(gè)AC便失去了意義。當(dāng)然這個(gè)規(guī)則也不是個(gè)教條贞奋,比如當(dāng)兩個(gè)AC相互依賴赌厅,他們最好同時(shí)驗(yàn)證。比如分開驗(yàn)證兩個(gè)AC都時(shí)候時(shí)間成本轿塔,外部資源成本非常昂貴特愿,那么也是可以放在一起寫多個(gè)Then語句的。
規(guī)則2:使用主動(dòng)語態(tài)
當(dāng)描述一些行為的時(shí)候勾缭,應(yīng)當(dāng)使用主動(dòng)的語態(tài)揍障,比如 "the user does X" 而不是 "X is done by the user"這種被動(dòng)的語態(tài)。
規(guī)則3:使用不同時(shí)態(tài)
在Gherkin中定義包含Given語句的時(shí)候俩由,要使用過去時(shí)時(shí)態(tài)毒嫡,因?yàn)檫@表示測(cè)試之前發(fā)生的一個(gè)前置條件。如:“Given the user was logged-in” 采驻。
在Gherkin中定義包含When語句的時(shí)候审胚,要使用現(xiàn)在時(shí)時(shí)態(tài)匈勋,這代表測(cè)試執(zhí)行的時(shí)候發(fā)生的,如:“When the user cancels the form”
在Gherkin中定義包含Then語句的時(shí)候膳叨,用情態(tài)動(dòng)詞寫成期望例如:Then the form should be closed洽洁。這強(qiáng)調(diào)了我們不是預(yù)測(cè)SUT將如何表現(xiàn),而是描述我們對(duì)它的期望菲嘴。
規(guī)則4:使用角色名稱
使用這些角色名稱:如 “Users”饿自、“Admin”、“Guest”龄坪,而不是 "I"昭雌。這可以增加一個(gè)場(chǎng)景的重點(diǎn),讓它專注于某一個(gè)角色健田,以便更容易閱讀理解烛卧。在后續(xù)步驟中,要么重復(fù)角色名稱妓局,要么使用代詞They來代表這類角色总放。
例如:
When the Admin starts the creation of a user
Then the Admin should be asked to confirm the creation
又如:
When the Admin starts the creation of a user
Then they should be asked to confirm the creation
規(guī)則5:使用大寫的否定詞
否定詞會(huì)大大改變句子的意思,但很容易被忽視好爬。把否定詞寫成大寫字母局雄,便可以強(qiáng)調(diào)它們。
例如:
“The the text “Welcome” should NOT be visible” 或 “The user should NOT exists”
符合受眾需求的產(chǎn)出物
作為技術(shù)人員存炮,往往具有很強(qiáng)的工程師思維慣性炬搭,產(chǎn)出物也是有鮮明的技術(shù)標(biāo)簽。所以從業(yè)務(wù)的視角來看穆桂,并不是那么對(duì)用戶友好宫盔。我們定義的第一版步驟庫(kù)便是如此。比如Flutter項(xiàng)目中所有的對(duì)象都可以加上類似于id的key屬性充尉,用來查找這個(gè)唯一的對(duì)象元素飘言,如果在步驟中要用這個(gè)屬性來尋找對(duì)象,那么步驟變成了類似:
When the element with key “userNameTextField” is filled with text “john@gmail.com”
這么定義出來的步驟可能有如下問題:
- 具有很強(qiáng)的編碼能力的Dev/QA可能更傾向于直接使用程序語言來書寫測(cè)試加快執(zhí)行驼侠,那么這套Ghkerin庫(kù)會(huì)被棄置。
- 沒有代碼倉(cāng)庫(kù)訪問權(quán)限的QA或者BA無法通過訪問代碼查看具體某個(gè)對(duì)象的Key是多少谆吴,那么這套Gherkin庫(kù)他/她無法使用倒源。
作為業(yè)務(wù)人員,更希望在步驟中隱藏所有技術(shù)細(xì)節(jié)句狼,方便使用笋熬。所以我們做了如下改進(jìn):
- 隱藏所有的Key細(xì)節(jié),盡可能使用元素可見的屬性腻菇,或者目標(biāo)元素和一個(gè)可見元素的相對(duì)關(guān)系來定位元素胳螟,如按鈕的文字昔馋,下拉選項(xiàng)上面的Label文字,文字輸入框的ToolTip糖耸,表格的標(biāo)題等等秘遏。
- 如果一個(gè)對(duì)象沒有可見的屬性必須使用Key定位的話,我們將駝峰式變量名的Key映射到友好的自然語言功能名稱上嘉竟,同時(shí)維護(hù)一個(gè)Wiki文檔邦危,這樣業(yè)務(wù)使用人員可以方便地查找和使用這個(gè)步驟。
于是舍扰,上面的步驟就變成了:
When the text field “user name” is filled with “john@gmail.com”
動(dòng)作式Gherkin風(fēng)格詳解
我們使用動(dòng)作式Gherkin定義了用例倦蚪,通過總結(jié),有如下經(jīng)驗(yàn)边苹。動(dòng)作式Gherkin語句用每一個(gè)參數(shù)化的步驟描述一個(gè)行為陵且,這種風(fēng)格使得步驟庫(kù)的體積不必非常大。因此也減少了自動(dòng)化框架步驟的開發(fā)和維護(hù)工作量个束,每一個(gè)步驟盡量和公共組件進(jìn)行互動(dòng)滩报,也保證了每個(gè)步驟的重用性非常之高,所以播急,一旦需要新測(cè)試脓钾,用現(xiàn)有的動(dòng)作式步驟庫(kù)書寫后這個(gè)case就可以立即運(yùn)行了,也不需要實(shí)現(xiàn)一個(gè)新的步驟桩警。
使用場(chǎng)景:寫測(cè)試用例
例子:
When the button 'Create User' is clicked
And the text field 'Last name' is filled with 'Jim'
And the text field 'First name' is filled with 'Green'
And the button 'Save' is clicked
Then the 'user list' should contain the text 'Jim, Green'
規(guī)則1:使用單一測(cè)試點(diǎn)的Scenario場(chǎng)景
由于動(dòng)作式Gherkin不可避免要使用更多的步驟可训,所以動(dòng)作式Gherkin的測(cè)試長(zhǎng)度一般都會(huì)更長(zhǎng)一些,但是這并不代表一個(gè)測(cè)試可以寫很長(zhǎng)很大捶枢。同樣地握截,一個(gè)測(cè)試還是需要遵循單一原則,最好覆蓋一個(gè)測(cè)試點(diǎn)烂叔,在覆蓋這個(gè)測(cè)試點(diǎn)的過程中谨胞,盡可能減少測(cè)試步驟讓這個(gè)測(cè)試簡(jiǎn)短精悍,方便維護(hù)蒜鸡。
規(guī)則2:使用被動(dòng)語態(tài)
由于動(dòng)作式Gherkin是對(duì)UI對(duì)象的操作胯努,為了方便閱讀,加強(qiáng)對(duì)互動(dòng)的UI元素的關(guān)注所以一般是 "X is clicked"這種被動(dòng)的語態(tài)逢防。
例子:
When the text field 'Last name' is filled with 'CAO'
反例:
When fill 'CAO' into the text field 'Last name'
規(guī)則3:使用不同時(shí)態(tài)
和文檔式Gherkin一樣叶沛,使用不同的時(shí)態(tài)來區(qū)分先決條件、行為忘朝、期望灰署。
Given步驟用過去時(shí)時(shí)態(tài),例如:Given user was logged-in.
When步驟用現(xiàn)在時(shí)來描述動(dòng)作, 例如:When button 'Login' is clicked.
Then步驟用情態(tài)動(dòng)詞描述期望,Then the text 'Welcome' should be visible.
規(guī)則4:專注于UI元素
動(dòng)作式Gherkin步驟專注于和UI界面互動(dòng)溉箕,所以盡可能隱藏用戶角色信息晦墙,一般來說,在Given步驟中給定了一個(gè)用戶角色即可肴茄,而之后晌畅,便不在語句中強(qiáng)調(diào)用戶角色,把重點(diǎn)放在用戶界面元素上独郎,這樣可以縮短自然語句中的措辭踩麦,突出用戶界面,這是動(dòng)作式Gherkin語句最關(guān)注的部分氓癌。
比如:
例子:
Given the 'Admin' was logged-in
When the button 'Delete user' is clicked
反例:
Given the 'Admin' was logged-in
When the 'Admin' clicks the 'Delete user' button
規(guī)則5:使用可見的UI屬性
UI元素有不同的屬性谓谦,一些屬性是可見的,這樣方便用戶區(qū)別他們贪婉,比如一個(gè)按鈕可以text反粥,class,id來查找到疲迂,為了讓對(duì)象快速被人識(shí)別才顿,那么便應(yīng)該使用人類可見的屬性來識(shí)別這些自動(dòng)化UI對(duì)象,那么對(duì)于這個(gè)按鈕就應(yīng)該用按鈕的文本來識(shí)別尤蒿,這樣便建立了測(cè)試語句和軟件UI對(duì)象視覺上的強(qiáng)有力的聯(lián)系郑气。
例子:
When the button '<button text>' is clicked
反例:
When the button with id '<id>' is clicked
有時(shí)候,一些對(duì)象沒有可視的屬性腰池,有時(shí)候一些對(duì)象是其他對(duì)象的分組尾组,或者其他對(duì)象的描述,比如一個(gè)區(qū)域示弓,一個(gè)層讳侨,這時(shí)候,便可以使用id奏属。此時(shí)跨跨,便需要開發(fā)團(tuán)隊(duì)給特定的元素添加id來支持自動(dòng)化測(cè)試。
例子:
Then the widget with the id 'header' should contain text ' today’s announcement'
但是要注意的是囱皿,這套步驟庫(kù)的受眾是誰勇婴,如果是非技術(shù)性用戶,那么盡可能隱藏掉id這種技術(shù)細(xì)節(jié)铆帽。
例子:
Then the element 'homepage header' should contain text ' today’s announcement'
規(guī)則6:前置條件中隱式假設(shè)的使用
例子1:
Given 'admin' was logged-in
And the dashboard page is visible
例子2:
Given the dashboard page is visible
我們可以假設(shè)咆耿,當(dāng)dashboard可見的時(shí)候,管理員必須要登錄爹橱,那么文檔式Gherkin使用例2便可以聚焦到dashboard相關(guān)的信息了。然而,在使用代碼實(shí)現(xiàn)步驟的時(shí)候愧驱,將多個(gè)動(dòng)作聚集到一個(gè)步驟的定義中慰技,會(huì)大大降低一個(gè)步驟的可重用性,一個(gè)復(fù)雜的動(dòng)作不能像原子動(dòng)作那樣與其他步驟結(jié)合组砚。一旦這些步驟鏈中任何一個(gè)地方改變吻商,那么整個(gè)步驟就要修改維護(hù)。
但另一方面糟红,如果一個(gè)場(chǎng)景可以將一些步驟聚合在一起艾帐,那么便可以大大提高這個(gè)場(chǎng)景的可讀性,忽略無關(guān)信息盆偿,如:Given owner exists. 這步其實(shí)聚合一系列創(chuàng)建用戶的動(dòng)作柒爸,一句話就表達(dá)了整個(gè)意思。所以編寫方案時(shí)事扭,需要在這兩種需求之間找到一個(gè)平衡捎稚。
統(tǒng)一手工測(cè)試和自動(dòng)化測(cè)試
文檔式Gherkin和動(dòng)作式Gherkin都有它們的適用之處,在寫軟件需求或者測(cè)試時(shí)候選擇最合適的即可求橄。遵守以上法則今野,會(huì)讓定義出來的Gherkin語言符合語言習(xí)俗,讓英語測(cè)試工程師更快速地使用這套步驟快速建立文檔和用例罐农,也讓自動(dòng)化框架開發(fā)工程師更方便地維護(hù)和對(duì)接步驟庫(kù)的使用者条霜。
在提供了基于動(dòng)作式Gherkin的步驟庫(kù)后,通過不斷地反饋和優(yōu)化涵亏,我們隱藏了對(duì)象的ID細(xì)節(jié)宰睡,提供了友好的元素定位方式,以及方便記憶的對(duì)象命名庫(kù)溯乒,客戶的QA終于可以方便地使用我們的步驟庫(kù)來書寫測(cè)試用例了夹厌。由于Gherkin步驟本身就是以英語自然語言來書寫的,所以它也就自然而然可以用來書寫手工測(cè)試用例了裆悄。一套用例矛纹,測(cè)試工程師可以看著通俗易懂的Gherkin語言來手動(dòng)執(zhí)行用例,F(xiàn)lutter上的類Cucumber自動(dòng)化框架也可以用自動(dòng)化執(zhí)行用例出具報(bào)告光稼。這樣一來或南,傳統(tǒng)的“手動(dòng)測(cè)試維護(hù)一套手工用例,自動(dòng)化測(cè)試再維護(hù)一套從手工測(cè)試轉(zhuǎn)化成的自動(dòng)化用例”的工作流不再存在艾君。終于可以大大減少用例的維護(hù)和執(zhí)行開銷了采够。
文/Thoughtworks 曹植野
原文鏈接:如何定義高質(zhì)量的Gherkin自然語言步驟庫(kù)-Thoughtworks洞見