您好,登錄后才能下訂單哦!
主要結(jié)論
1.測試自動化是一種妥善記錄并具備清晰定義的方法,借此可以反復(fù)運行同一套測試腳本。然而與此同時,這種測試自動化腳本還可進一步實現(xiàn)其他更有創(chuàng)意的應(yīng)用。
2.雖然自動化的分析思維很難實現(xiàn),但我們的腳本中無疑可以具備一定的隨機性。
3.測試中“隨機性”的具體程度各異:從隨機輸入和參數(shù),再到全面的隨機測試用例,情況不一而足。
4.很難將隨機步驟與相應(yīng)的驗證措施匹配起來,但我們可以使用不同的驗證策略確保應(yīng)用程序能夠按照預(yù)期工作。
5.隨機測試無法取代主觀或傳統(tǒng)測試技術(shù),但可在回歸測試過程中讓我們對應(yīng)用程序質(zhì)量更為自信。
正如Cem Kaner在他的一片教程中所說,探索式測試是一種強調(diào)個人自由度和個體測試人員責(zé)任的軟件測試方式,可通過將與測試有關(guān)的學(xué)習(xí)、測試設(shè)計、測試執(zhí)行,以及測試結(jié)果的理解視作一系列彼此提攜,在項目完整過程中并行執(zhí)行的活動,借此對測試工作的成果進行持續(xù)不斷的優(yōu)化。
簡而言之,按照他的定義,眾所周知的“軟件質(zhì)量和消費者(Software Quality and Consumer)”主張為測試人員提供了在項目中按照自己認為合適的方式進行測試的自由和責(zé)任。循序漸進地記錄所有規(guī)范,這種做法已經(jīng)不再是必須,原因也很簡單,創(chuàng)意過程基本式無法記錄的,對吧!在他在TestBash 3大會上有關(guān)測試中決策工作的演講中,Mark Tomlinson對系統(tǒng)的主觀理解這一想法表示支持。如果將其作為探索式的,基于風(fēng)險和基于會話的測試技術(shù)(可將其稱之為主觀技術(shù))的核心,測試者將能主觀地確定應(yīng)用程序中可能導(dǎo)致失敗的重要環(huán)節(jié)。
可以參看這張旋轉(zhuǎn)舞者的動力學(xué)錯覺示意圖:不同時刻內(nèi),我們的大腦或判斷舞者以一個特定的順序旋轉(zhuǎn):向左或向右。測試工作也會面臨類似情況:我們可能考慮使用不同流程實現(xiàn)相同結(jié)果,或相同流程導(dǎo)致雖不同但符合預(yù)期的結(jié)果,或者,嗯……任何其他結(jié)果。
整個測試執(zhí)行過程所用的主觀技術(shù)可以通過各種成熟的分析思維和“隨機性”的優(yōu)勢加以引導(dǎo)。其中后者是一個更重要的要素,本文,將揭露自動化測試中“隨機化”的神秘面紗。
如果你感覺到學(xué)編程有些吃力,但是又對IT行業(yè)非常喜愛的話,可以加測試交流群:1017539290,進群免費領(lǐng)取測試學(xué)習(xí)資料!
明確起見,測試自動化并不是一種創(chuàng)作活動,而是一種妥善記錄且清晰定義的方法,借此可以讓同一套測試腳本反復(fù)運行使用。問題在于,我們該如何使用這些測試自動化腳本,同時更更具創(chuàng)意?
產(chǎn)品質(zhì)量隨時間而變
產(chǎn)品質(zhì)量模型和所記錄的測試場景可通過特定的狀態(tài)機以及外部特性加以概括。這一點正是測試自動化所熱愛的。測試自動化所關(guān)注的正是根據(jù)一些非常具體的測試需求集編寫測試腳本。
這種做法很適合功能性回歸測試:清理、打磨、全新發(fā)布,隨后由開發(fā)大師創(chuàng)建。姑且將其稱之為Shiny吧。
但經(jīng)過一段冗長、精疲力竭的開發(fā)時間線后(伴隨著多次發(fā)布,長達數(shù)年的支持,數(shù)百個Bug的修復(fù)和功能請求等),系統(tǒng)會變成什么樣?
確實,從用戶接口的角度來看,可能非常類似于那種雖然老舊但依然工作良好的系統(tǒng),但表面之下,這種情況通常被稱之為“大泥球”。
對于這樣的系統(tǒng),算使用自動化腳本,具體功能的哪些部分依然能獲得和初生產(chǎn)發(fā)布時同等程度的測試?也許只有30%-80%的部分可以吧。那么其他功能呢?不知道。
當然,此時簡單的辦法可能是審查所有現(xiàn)有的質(zhì)量文檔,改良原有的場景,(即時)引入新的場景等。但考慮到業(yè)內(nèi)的經(jīng)驗,隨著遺留系統(tǒng)的規(guī)則測試文檔逐漸過時,雖然更新工作依然重要,但這種做法并非總是可行。
為測試自動化解決方案打造妥善定義的架構(gòu)
下圖是一個精簡的測試自動化解決方案的范例圖,其中包含三層(類似于基于UI、業(yè)務(wù)邏輯和數(shù)據(jù)庫實現(xiàn)業(yè)務(wù)應(yīng)用程序的方法):UI/API映射、業(yè)務(wù)裸機,以及測試腳本。
1.UI/API映射代表該解決方案的技術(shù)端:UI自動化工具程度與自動化系統(tǒng)的UI高度綁定,這一層所用的方法可能類似于focus()、type_text()、click_button()。
2.業(yè)務(wù)邏輯是一種由來自業(yè)務(wù)操作的關(guān)鍵字組成的庫。業(yè)務(wù)操作是指可以在應(yīng)用程序中執(zhí)行的某個步驟(如login()、create_user()、validate_user_created())。
3.測試腳本負責(zé)執(zhí)行一系列鏈再一起的業(yè)務(wù)步驟。
深入了解獨立測試(Separate Test)
考慮這樣一種簡單的記錄測試用例:執(zhí)行這個 – 驗證這個,執(zhí)行那個 – 驗證那個,執(zhí)行某某 – 驗證某某。合格的自動化開發(fā)者會創(chuàng)建一系列類似下面這樣的方法:
do_that(), verify_that(), do_this(), verify_this(), do_bla().
測試腳本會按照某種特定的順序調(diào)用這樣的方法:
mySpecifiedCase_1(){
do_that();
verify_that();
do_this();
verify_this();
do_bla();
verify_that();
verify_this();
}
由于腳本沒找到任何Bug,我們在某些特定階段的任務(wù)變成讓它查找潛在的系統(tǒng)問題。
隨機化方法1 – 裸隨機
從業(yè)務(wù)角度來說,自動化解決方案中任何步驟都是有效的。因此探索式測試使得我們可以自由地在任何時間點執(zhí)行任何步驟。這些步驟的混搭也很簡單。我們需要在執(zhí)行過少數(shù)幾次測試后,遵循已實現(xiàn)步驟打造“隨機”測試用例。
輸入:解決方案中所有業(yè)務(wù)方法的數(shù)量,要生成的測試腳本數(shù)量,生成每個測試腳本所需步驟數(shù)量。
輸出:類似于下列腳本:
myRandomCase_1(){
do_that();
do_bla();
verify_this();
}
很明顯,算某些測試用例可能(甚至已經(jīng))成功運行,大部分依然會失敗,因為大量用例實際上是在試圖完成無效操作。如果還沒執(zhí)行過do_this(),那么verify_this()無疑會失敗。
隨機化方法2 – 有先決條件的隨機方法
這種方式的想法在于只有在工作流中已包含先覺步驟后,才向工作流中加入后續(xù)步驟,但這需要對代碼庫進行必要的擴充,確保測試案例生成器可以理解并保證準確的序列。為此可在方法之上添加特性或注解:
@Reguires(do_this)
verify_this()
{…}
這樣我們得到了:
myRandomCase_2(){
do_bla();
do_this();
verify_this(); //can be added, because prerequisite step is already in test
}
這是一種更可預(yù)測的方法。但如果do_this()和verify_that()需要在同一個Page1上執(zhí)行,而do_bla()已經(jīng)到了Page2又該怎樣?
此時我們面臨一個新問題:verify_that()會失敗,因為無法找到執(zhí)行所需的控制/上下文。
人工隨機化方法3 – 上下文感知
如果你感覺到學(xué)編程有些吃力,但是又對IT行業(yè)非常喜愛的話,可以加測試交流群:1017539290,進群免費領(lǐng)取測試學(xué)習(xí)資料!
測試生成器必須了解執(zhí)行位置上下文(例如Web開發(fā)中的“頁面”)。當然,此時也可以通過特性/注解為生成器提供活躍上下文。
@ReguiresContext(pageThis)
verify_this()
{…}
@ReguiresContext(pageThis)
do_this()
{…}
@ReguiresContext(pageThis)
@MovesContextTo(pageThat)
do_bla()
{…}
本例中do_this()和verify_this()不會放在將上下文改為pageThat的方法,或上下文為pageThat的方法之后。
因此我們可以得到一個類似下面這樣的測試腳本:
myRandomCase_3(){
do_this();
do_bla();
do_that();
}
或者也可以通過方法鏈實現(xiàn)。假設(shè)業(yè)務(wù)方法返回的對象為頁面,測試案例生成器會持續(xù)追蹤執(zhí)行“步驟”前后瀏覽器中顯示的頁面,因此可以確定需要調(diào)用驗證或“步驟”方法的正確頁面。這種方法需要額外檢查以驗證流程是否正確,但這個操作可以無須注解實現(xiàn)。
篩選恰當?shù)挠美?/p>
至此介紹的方法已經(jīng)可以生成相當大量的測試用例。
主要問題在于,驗證過程本身,以及驗證失敗的測試場景是否是應(yīng)用程序內(nèi)的Bug,而非自動化測試腳本邏輯導(dǎo)致的,這些工作也需要耗費大量時間。
因此可以實現(xiàn)一種“預(yù)言”類,借此預(yù)測所獲得的結(jié)果是否滿意,或是否代表任何錯誤信息,并且必要時可進行后續(xù)分析。然而本例我們選擇了一個略微不同的方法。
可以通過下列這一套規(guī)則代表應(yīng)用程序的失敗是Bug引起的:
1.500錯誤或類似頁面
2.JavaScript錯誤
3.“未知錯誤”或因為誤用造成的類似的錯誤信息
4.應(yīng)用程序日志中有關(guān)異常和/或錯誤情況的信息
5.發(fā)現(xiàn)與任何其他產(chǎn)品有關(guān)的錯誤
本例中,可在每個步驟執(zhí)行完畢后驗證應(yīng)用程序狀態(tài)。因此自動生成的腳本看起來是這樣的:
myRandomCase_3(){
do_this();
validate_standard_rules();
do_bla();
validate_standard_rules();
do_that();
validate_standard_rules();
}
其中validate_standard_rules()方法可以搜索上文提到的各種問題。
注意:通過與OOP結(jié)合,這種方法會顯得更為強大,可以檢測出實際的Bug。在Page Object超類實現(xiàn)常規(guī)檢查需要查找“常規(guī)問題”,例如JavaScript錯誤、日志中的應(yīng)用程序錯誤等。對于與特定頁面有關(guān)的合理檢查,可以繞過這種方法額外增加針對具體頁面的檢查。
實驗
為了進行實驗,我們決定使用公開的郵件系統(tǒng)??紤]到Gmail和Yahoo的流行度,這些系統(tǒng)中所有存在的Bug都已被發(fā)現(xiàn)的可能性相當高。因此我們選擇了ProtonMail。
Taking Over Random
假設(shè)自動化解決方案已經(jīng)位,我們“采用”了Shiny系統(tǒng)的自動化測試機制:首先建立一個通用的Java/Selenium測試項目,其中包含幾個使用Page Object模式實現(xiàn)的冒煙測試。隨后按照佳實踐,所有業(yè)務(wù)方法可以返回一個新的Page Object(針對業(yè)務(wù)方法結(jié)束時依然顯示在瀏覽器中的頁面)或當前Page Object,除非頁面被更改。
為進行自動化探索式測試,我們增加了包含在explr.core包中的類,其中感興趣的當屬TestCaseGenerator和TesCaseExecutor。
TestCaseGenerator
為了生成新的“隨機”測試用例,可以通過TestCaseGenerator類調(diào)用兩個generateTestCase方法之一。這兩個方法都能以參數(shù)的方式接受代表所生成測試用例中“步驟驗證對”數(shù)量的整數(shù)。第二個方法還可額外接受一個代表要使用的“驗證策略”數(shù)量的參數(shù)(第一個方法使用默認策略,本例為USE_PAGE_SANITY_VERIFICATIONS)。
驗證策略代表在向測試用例添加“檢查”步驟時所用的方法。目前我們有兩個選項:
1.USE_RANDOM_VERIFICATIONS:第一個,同時也是明顯的策略。該策略的想法在于,使用來自頁對象的當前驗證方法。但不足之處在于嚴重依賴上下文。例如:我們隨機選擇了一個方法來驗證特定主題的消息是否存在。首先,我們必須知道要查找哪個主題。為此我們引入了@Default注解和DefaultTestData類。DefaultTestData包含的常規(guī)測試數(shù)據(jù)可用于隨機測試。@Default注解可用于將該數(shù)據(jù)綁定給特定的方法參數(shù)。隨后我們需要確保包含該主題的消息先于驗證操作已存在(可在執(zhí)行該規(guī)范的過程中,或之前的任何測試過程中創(chuàng)建)。為此可通過@Depends注解告訴TestCaseGenerator檢查特定方法的調(diào)用,如果當前步驟之前沒找到則直接添加。此外我們還需要確保消息沒有在驗證之前刪除。我們發(fā)現(xiàn)對于生成的測試用例,依賴性問題大幅降低了隨機化程度,并且這種方法的穩(wěn)定性也無法滿足要求。
2.USE_PAGE_SANITY_VERIFICATIONS:該策略可檢查顯而易見的應(yīng)用程序失敗,如顯示了錯誤的頁,錯誤信息,JavaScript錯誤,應(yīng)用程序日志中的錯誤等。在依賴性方面這個策略更靈活,可在需要時實現(xiàn)針對具體頁的檢查,例如已經(jīng)足夠靈活到可以找出實際的Bug。目前我們將其用作默認的驗證策略。
TestCaseGenerator類可按照類名搜索Page對象:每個名稱中包含“Page”字符串的類都會被看作是頁對象。頁對象的所有公開方法會被視作業(yè)務(wù)方法。名稱包含“Verify”字符串的業(yè)務(wù)方法會被視作驗證,所有其他方法會被視作測試步驟。@IgnoreInRandomTesting注解可用于從列表中排除某些工具方法或整個頁對象。
隨后可從兩個列表中隨機選擇方法生成測試用例:一個列表包含測試步驟,一個列表包含驗證步驟(如果所選驗證策略需要驗證步驟的話)。選擇第一個方法后,將檢查其返回值是否為另一個頁對象。如果返回值是另一個頁對象,那么將從其方法中選擇下一個步驟(參見上文備注)。為避免在兩個頁之間循環(huán)往復(fù),有一成的概率會跳轉(zhuǎn)至一個完全隨機的頁面。如果方法使用@Depends注解標注了任何依賴項,則會按需解決這些問題并添加。
為避免出現(xiàn)從當前所顯示頁之外其他對象調(diào)用測試方法的情況,生成的測試用例會傳遞一個額外的驗證,借此添加缺少的導(dǎo)航調(diào)用。
TesCaseExecutor
生成之后,測試用例基本上是一種“類-方法對”列表,可通過特定方式執(zhí)行或保存。盡管可在運行時執(zhí)行,但從調(diào)試和后續(xù)分析的角度來看,保存為文件是一種更好的做法。
如果你感覺到學(xué)編程有些吃力,但是又對IT行業(yè)非常喜愛的話,可以加測試交流群:1017539290,進群免費領(lǐng)取測試學(xué)習(xí)資料!
生成的測試用例可通過多種方式執(zhí)行,可以TesCaseExecutor作為其接口,以SaveToFileExecutor作為的實現(xiàn),借此可簡單地創(chuàng)建一個代表所生成測試用例的.java文件。令人驚異的是,這種相當簡單的解決方案完全滿足了我們的需求:實現(xiàn)速度快,可對測試結(jié)果進行深入分析,并能了解具體的生成方式。的不足在于,必須手工編譯并運行生成的測試用例,不過對于實驗來說,這也算不得什么大問題。
SaveToFileExecutor生成的測試用例代碼可通過模板轉(zhuǎn)換為可編譯的文件。這樣生成的測試范例如下:
@Test(dataProvider = "WebDriverProvider")
public void test(WebDriver driver){
login(driver);
//****<Generated>****
ContactsPage contactspage = new ContactsPage(driver, true);
InboxMailPage inboxmailpage = contactspage.inbox();
inboxmailpage.sanityCheck();
ComposeMailPage composemailpage = inboxmailpage.compose();
composemailpage.sanityCheck();
composemailpage.setTo("me@myself.com");
composemailpage.send();
inboxmailpage.sanityCheck();
List list = inboxmailpage.findBySubject("Seen that?");
inboxmailpage.sanityCheck();
inboxmailpage.inbox();
inboxmailpage.sanityCheck();
DraftsMailPage draftsmailpage = inboxmailpage.drafts();
draftsmailpage.sanityCheck();
inboxmailpage.inbox();
inboxmailpage.sanityCheck();
inboxmailpage.sendNewMessageToMe();
inboxmailpage.setMessagesStarred(true, "autotest", "Seen that?");
inboxmailpage.sanityCheck();
TrashMailPage trashmailpage = inboxmailpage.trash();
trashmailpage.sanityCheck();
//****</Generated>****
}
SaveToFileExecutor生成的代碼位于<Generated>備注之間,其余代碼由模板添加。
從所執(zhí)行的操作方面來看,我們生成的用例多樣化程度一般,但只要添加包含更多測試步驟的更多頁對象即可輕松解決。
如果你感覺到學(xué)編程有些吃力,但是又對IT行業(yè)非常喜愛的話,可以加測試交流群:1017539290,進群免費領(lǐng)取測試學(xué)習(xí)資料!
在進行過上千個“隨機”測試后,我們發(fā)現(xiàn)Protonmail沒什么大問題(例如錯誤頁),但瀏覽器匯報了一些JavaScript錯誤,對于依賴JavaScript進行郵件編解碼工作的系統(tǒng),這些問題非常重要。很明顯,整個實驗中我們并不能訪問服務(wù)器日志,但實驗的角度來說,已經(jīng)足夠展示出這樣的方法對被測試系統(tǒng)質(zhì)量的促進能起到多大的作用。
當然,隨機測試無法取代主觀或傳統(tǒng)測試技術(shù),但可在回歸測試過程中讓我們對應(yīng)用程序質(zhì)量更為自信。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。