




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡介
1、 .測試用例的前置條件和后置條件除 了第二點(diǎn)中談到的數(shù)據(jù)需要準(zhǔn)備外,在測試用例這個(gè)Level,必須有一些條件滿足,您才能開始執(zhí)行它。比如準(zhǔn)備一個(gè)初始設(shè)置條件下的IE 瀏覽器和已安裝過老版本該軟件的XP系統(tǒng)。這些可重用的準(zhǔn)入條件,可以考慮不作為特定用例的Step,而是把它提取出來,作為Setup Section或叫Pre-Condition。對(duì)于后置條件或Post- condition,往往我們用它來做一些處理或恢復(fù),比如在上面的取款例子中,如果我們要用一樣的重復(fù)測試,在正好取完所有金額,余額為零的情況 下,可以通過一些步驟或數(shù)據(jù)庫腳本重置余額。同樣,您為某個(gè)用例設(shè)置瀏覽器禁用了Cookie,執(zhí)
2、行完該用例后,是不是也是需要回復(fù)到默認(rèn)設(shè)置的狀態(tài) 呢?集中的把這些步驟整理成一個(gè)相對(duì)獨(dú)立的操作單元,具體用例中只要引用就可以了,這樣會(huì)便于對(duì)用例的理解和在多處復(fù)用。順便說一下,對(duì)于一些類似軟件運(yùn)行環(huán)境的條件,比如安裝和配置測試中,需要3種操作系統(tǒng)和3種瀏覽器的組合等,我們可以把他放在Test Set這個(gè)Level上來,不用寫多個(gè)用例,只是在測試計(jì)劃和執(zhí)行的管理系統(tǒng)中作為測試集的一個(gè)環(huán)境參數(shù),恰當(dāng)?shù)乇磉_(dá)出來就可以。4. 常用業(yè)務(wù)操作(Knowledge Base)對(duì)于一個(gè)大型的應(yīng)用,比如銀行系統(tǒng),開發(fā)和測試工作是長期的,持續(xù)的一個(gè)過程,這樣的系統(tǒng)很適合引入自動(dòng)化測試。它業(yè)務(wù)邏輯復(fù)雜,測試技術(shù)性要
3、求高,往往使用了不同廠商的工具和多種腳本語言(如Shell,Python等),也存在了很多可用的遺留腳本。這些完成一些預(yù)定業(yè)務(wù)操作的腳本單元,是可以直接借用的。為了在公司和產(chǎn)品層面,管理好這些可復(fù)用的資源,一種好的方式是給它們標(biāo)上號(hào),如KB_PRJ01_Module02_XXX,集中管理起來,以后的用例中只要調(diào)用即可。舉 例來說,在銀行業(yè)務(wù)測試中我們,需要模擬和銀聯(lián)的接口,讓測試向外匯款,取得響應(yīng)信息,并保存結(jié)果,這可能是個(gè)復(fù)雜而底層的處理過程,對(duì)一般員工是不 需要,也沒有權(quán)限去深入掌握的。這時(shí),將他們包裝成一個(gè)個(gè)Shell腳本或小工具,做好使用說明和統(tǒng)檔,在以后的項(xiàng)目測試中,只要調(diào)用就可以了
4、。如 此,可以大大提高各個(gè)有相關(guān)接口的模塊的自動(dòng)化測試工作效率。根據(jù)以往工作中常見的一些問題,對(duì)于如何寫好測試用例(不僅針對(duì)自動(dòng)化測試),做以下做幾點(diǎn)補(bǔ)充: 推薦 不推薦 將用例的容描述清楚,強(qiáng)調(diào)怎么操作,驗(yàn)證什么,然后期待的結(jié)果是什么。 Copy需求和設(shè)計(jì)文檔中的容;描述成:什么條件下,邏輯會(huì)是怎樣。這樣對(duì)測試用例的閱讀和執(zhí)行人員,不具有可操作性。 期待的結(jié)果要寫具體,如:系統(tǒng)反應(yīng)是什么;結(jié)果數(shù)字是多少;用戶被帶到什么頁面;顯示什么成功信息;后臺(tái)或數(shù)據(jù)庫中該記錄的修改后結(jié)果是怎么樣的。 描述成:”驗(yàn)證系統(tǒng)返回正確結(jié)果“;”頁面元素顯示跟SPEC一致“;”操作成功“等 比較抽象的說法。 業(yè)務(wù)邏
5、輯性較強(qiáng)的應(yīng)用軟件,做到以業(yè)務(wù)流為主線,來組織用例。 以頁面形式組織用例。 以Module、Function、測試類型、基本業(yè)務(wù)流、備選業(yè)務(wù)流的樹狀結(jié)構(gòu)形式,分層次組織用例;使用用例管理工具。 Word格式的扁平組織結(jié)構(gòu),不利于管理和閱讀。 用一個(gè)屬性字段,建立用例和Spec等文檔的某個(gè)章節(jié)間的映射。 無法和需求對(duì)應(yīng),以后難以計(jì)算 用例覆蓋率,測試執(zhí)行覆蓋率。 每個(gè)Module、Function、特定業(yè)務(wù)的一組測試用例,之間做到獨(dú)立、沒有耦合。 用例之間有依賴,無法做到:挑選30%的用例做回歸測試。 在時(shí)間和成本允許的情況下,盡量做到:用例粒度為“一種不同的操作,得到不同的結(jié)果,就單獨(dú)寫一個(gè)用
6、例“。 在用例中的操作步驟中,甚至期待結(jié)果中,仍然存在條件分支。 對(duì)于復(fù)雜的業(yè)務(wù)操作過程,如”一次順序的表單簽核過程“和”一次完整的信貸手續(xù)“,單獨(dú)增加一些貫穿整個(gè)業(yè)務(wù)流的大型測試用例。 對(duì)于一個(gè)長業(yè)務(wù)操作,只存在比較零散的細(xì)節(jié)用例。 將用例分優(yōu)先等級(jí),便于在回歸測試時(shí)挑選核心業(yè)務(wù)或用戶操作密集的用例。 用例 沒有優(yōu)先級(jí)和重要程度的定義。 自動(dòng)化測試用例設(shè)計(jì)的原則很多公司在實(shí)施自動(dòng)化測試的過程中,往往會(huì)把所有的手工測試用例作為自動(dòng)化測試用例,并且直接進(jìn)行腳本的開發(fā)工作,甚至有些公司不寫自動(dòng)化測試用例,直接想當(dāng)然地開發(fā)測試腳本,這些都是極其不規(guī)的做法,甚至很有可能是導(dǎo)致最后自動(dòng)化測試項(xiàng)
7、目失敗的最大原因。那么問題就來了,為什么不能使用手工測試用例完全替代自動(dòng)化測試用例呢?有以下幾點(diǎn)原因,同時(shí)也是自動(dòng)化測試用例的設(shè)計(jì)原則 原則1:自動(dòng)化測試用例的圍往往是核心業(yè)務(wù)流程或者重復(fù)執(zhí)行率較高的。 在選取自動(dòng)化測試用例圍時(shí),很多測試工程師或者上級(jí)領(lǐng)導(dǎo)可能心里會(huì)過分依賴自動(dòng)化測試,會(huì)認(rèn)為自動(dòng)化測試就應(yīng)該覆蓋所有的手工測試用例,自動(dòng)化測試的 覆蓋率就應(yīng)該達(dá)到百分之百。其實(shí)恰好相反,這樣的想法往往會(huì)導(dǎo)致自動(dòng)化測試最終失敗。在一些大型項(xiàng)目中,往往測試用例的數(shù)量會(huì)很龐大,而且如果遇到一些繁 雜的被測程序(特別是C/S架構(gòu)),腳本開發(fā)工作往往會(huì)相當(dāng)耗時(shí)間,并且很多測試用例甚至根本就不能通過
8、自動(dòng)化來實(shí)現(xiàn)。舉些例子,現(xiàn)在很多公司自動(dòng)化測試 都是剛起步,對(duì)自動(dòng)化測試的了解程度只是停留在字面上,在公司對(duì)測試也不是非常重視的情況下,當(dāng)然不太愿意去花精力招一個(gè)具有自動(dòng)化測試開發(fā)經(jīng)驗(yàn)的工程 師,很多還是停留在使用工具的錄制回放功能來完成自動(dòng)化測試。正是存在這樣的技術(shù)限制情況下,往往在實(shí)施中,會(huì)出現(xiàn)很多錄制回放不能解決的問題,測試工具 完全無法識(shí)別測試對(duì)象,無法識(shí)別一些特殊的加密測試控件。還有,如果項(xiàng)目的變更頻率,測試用例數(shù)量大的話,增加了后期的維護(hù)工作量等,都是造成最終失敗的 一些隱患。投入越大,損失越大。因此,往往我們會(huì)選取最核心的一些業(yè)務(wù)路徑或者是重復(fù)執(zhí)行率較高的一些手工測試用例進(jìn)行自動(dòng)
9、化測試,這樣能夠充分發(fā)揮出自 動(dòng)化測試的優(yōu)勢。 原則2:自動(dòng)化測試用例的選擇一般以“正向”為主。手工測試用例分正常情況和異常情況,在設(shè)計(jì)的時(shí)候,可能往往會(huì)去設(shè)計(jì)很多異常情況來驗(yàn)證程序是否有Bug, 并且一個(gè)正常情況的測試用例往往會(huì)對(duì)應(yīng)幾十個(gè)非正常情況的測試用例,而每種異常情況的測試用例都會(huì)有各種各樣的預(yù)期結(jié)果。在自動(dòng)化測試中,很多人喜歡將正 常情況稱為“正向”;反之,異常情況則稱為“反向”。下面,我們試想以下,如果將這些異常情況全部轉(zhuǎn)化、反應(yīng)到自動(dòng)化測試腳本中,那肯定需要非常繁瑣的判 斷才能做到。這個(gè)對(duì)于自動(dòng)化測試工程師來說,其現(xiàn)有的工作量還是今后的腳本維護(hù)量都是不可小視的。對(duì)于整個(gè)
10、自動(dòng)化測試項(xiàng)目來說,如果每個(gè)異常情況都要寫進(jìn) 腳本中,那真的是花了大價(jià)錢買一堆小東西,小東西真正能發(fā)揮大作用的畢竟很少。因此,真正在自動(dòng)化測試項(xiàng)目實(shí)施中,往往會(huì)舍棄反向用例,個(gè)別比較重要的除 外。使每個(gè)東西都能發(fā)揮其最大的作用才是企業(yè)最想看到的。功能自動(dòng)化測試主要還是用于回歸測試,回歸測試的目的就是保證新增功能后老功能是否能夠正常繼續(xù) 運(yùn)作。而自動(dòng)化測試則是讓測試人員從繁瑣又枯燥的重復(fù)手工測試中解放出來,這就是目的和目標(biāo)。原則3:不是所有手工測試用例都可以使用自動(dòng)化測試來實(shí)現(xiàn)的。 這里糾正許多測試從業(yè)人員的一個(gè)錯(cuò)誤觀念,剛接觸測試自動(dòng)化的普遍都會(huì)認(rèn)為手工測試用例全部要轉(zhuǎn)化為自動(dòng)化測試用例,但是
11、在真正實(shí)施的時(shí)候,卻發(fā)現(xiàn)很多 測試用例是自動(dòng)化無法實(shí)現(xiàn)的,或者有些測試用例根本就沒有必要去自動(dòng)化的。例如,有些用例會(huì)牽涉到硬件設(shè)備輔助的,最簡單的例子就是用例執(zhí)行過程中需要使 用刷卡機(jī)才能獲取卡號(hào)信息(如果有技術(shù)能力,當(dāng)然不排除自行開發(fā)接口供測試工具調(diào)用,但畢竟能有技術(shù)實(shí)力做到這一步的不多,能有這樣的重視程度的更不 多);再比如,有些測試用例是需要與合作機(jī)構(gòu)進(jìn)行互動(dòng)聯(lián)調(diào),聯(lián)調(diào)時(shí)是需要和對(duì)方實(shí)時(shí)溝通,以與根據(jù)具體情況給予響應(yīng)的,這些情況多數(shù)還是只能使用手工人為 地來完成。當(dāng)然,決定是否轉(zhuǎn)化為自動(dòng)化測試,必須事先有一個(gè)規(guī)文檔來定義哪些是需要轉(zhuǎn)化為自動(dòng)化測試哪些是不需要的,否則測試工程師就會(huì)不知所措
12、,沒有 一個(gè)標(biāo)準(zhǔn)。一旦有了這個(gè)標(biāo)準(zhǔn),自動(dòng)化測試工程師就可以嚴(yán)格按照文檔里的流程去完成需要轉(zhuǎn)化部分的自動(dòng)化測試用例的腳本開發(fā)工作了。原則4:手工測試用例可以不用回歸原點(diǎn),而自動(dòng)化用例往往是必須的。 很多有經(jīng)驗(yàn)的自動(dòng)化測試從業(yè)人員一定有這樣的經(jīng)歷,很多時(shí)候腳本寫完后,第一次執(zhí)行沒有任何問題,而第二次執(zhí)行時(shí)立刻就會(huì)報(bào)錯(cuò),原因就是沒有回歸原點(diǎn)。 所謂回歸原點(diǎn)就是執(zhí)行的測試用例最終需要恢復(fù)其在執(zhí)行前的初始狀態(tài),如果沒有回歸原點(diǎn),就會(huì)把此腳本稱之為死腳本。舉個(gè)最簡單的例子,比如添加用戶功能, 我們都知道每個(gè)用戶名都是唯一的,當(dāng)寫完一個(gè)添加用戶的腳本之后,執(zhí)行第一次沒有問題,因?yàn)閳?zhí)行前此用戶還不存在,但是當(dāng)
13、執(zhí)行第二次時(shí),程序就會(huì)出現(xiàn)用戶 重復(fù)而報(bào)錯(cuò),此時(shí)這個(gè)添加用戶的腳本就失去了它的價(jià)值,在這種情況下,我們就需要在自動(dòng)化測試用例的最后加上刪除這個(gè)用戶的步驟,這樣在下次執(zhí)行用例時(shí)就 不會(huì)出現(xiàn)用戶重復(fù)的情況了。當(dāng)然,除了回歸原點(diǎn),還可以使用另一種方式進(jìn)行,那就是初始化數(shù)據(jù),比如ATM機(jī)取款,假設(shè)需要執(zhí)行取款100元的操作,而銀 行卡余額是120元,當(dāng)測試腳本第一次執(zhí)行時(shí)可能沒有任何問題,但是第二次系統(tǒng)就會(huì)報(bào)余額不足,這樣就成為了死腳本,解決方案有兩種:一種是直接進(jìn)行初始 化數(shù)據(jù),每次執(zhí)行用例之前都重置下余額(只需大于100即可);第二種方法可以在用例執(zhí)行前,先查詢下余額是否大于100,若大于等于則繼
14、續(xù),若小于則做 一筆充值100的操作,這樣即可解決。兩種方式可以看具體情況使用,數(shù)據(jù)初始化方便,但有時(shí)候初始化之后可能會(huì)影響到其他自動(dòng)化測試用例的執(zhí)行,而第二種 方式相對(duì)在腳本上需要稍微花點(diǎn)功夫。究竟使用哪種方式還需要具體情況具體分析??傊?,在執(zhí)行自動(dòng)化測試用例之前做好數(shù)據(jù)準(zhǔn)備,這也是自動(dòng)化測試的關(guān)鍵步 驟。原則5:自動(dòng)化測試用例和手工測試用例不同,不需要每個(gè)步驟都寫預(yù)期結(jié)果。 在手工測試用例的設(shè)計(jì)過程中,幾乎每一個(gè)測試步驟都有一個(gè)預(yù)期結(jié)果。但是,在自動(dòng)化測試用例的設(shè)計(jì)中并不采用,在自動(dòng)化測試用例中,只有準(zhǔn)備在測試腳本 中設(shè)置成檢查點(diǎn)的步驟才有預(yù)期結(jié)果,其他所有的步驟只將它看作一個(gè)步驟,這樣做
15、的好處是一目了然、目的明顯、層次分明,以后寫測試腳本直接跟著自動(dòng)化測試 用例就行了。因?yàn)榻?jīng)過前面的探討應(yīng)該已經(jīng)知道,自動(dòng)化測試中并不是所有的東西都需要驗(yàn)證的。所以,作者在前面的章節(jié)中也提到過,基本上手工測試用例多多少 少都要進(jìn)行一些轉(zhuǎn)換的,就是因?yàn)樗鼈冎g的格式是不一致的。舉一個(gè)簡單的例子,假設(shè)需要設(shè)計(jì)一個(gè)注冊頁面的自動(dòng)化測試用例,有10幾個(gè)表單 需要填寫,在手工測試用例中,每個(gè)表單的填寫都一定會(huì)有預(yù)期結(jié)果,因?yàn)樗拇_在檢查每一項(xiàng)是對(duì)了還是錯(cuò)了,只是用的是你的眼睛在檢查而已,所以速度非常的 快,甚至你自己潛意識(shí)都忽略了其實(shí)你已經(jīng)檢查了。但是,在自動(dòng)化測試中,我們知道如果你要檢查,那一定需要寫代
16、碼,如果每項(xiàng)都檢查,那代碼量有多大是可想 而知的,不是說做不到,只是這樣做根本不符合自動(dòng)化測試的特點(diǎn)。所以,絕大部分時(shí)候,這些在自動(dòng)化測試中可有可無的檢查,我們?nèi)俊安粰z查”,只當(dāng)做一個(gè)業(yè)務(wù)流程和步驟,是不需要設(shè)立預(yù)期結(jié)果的。難以對(duì)于UI樣式或UI邏輯進(jìn)行斷言以上圖為例,有一個(gè)UI樣式類的缺陷(左側(cè)菜單樹的根節(jié)點(diǎn)“console”下面多出來一條虛 線)和一個(gè)UI邏輯類的缺陷(右側(cè)用戶列表只有一頁,但“下一頁”和“最后一頁”圖標(biāo)依然是可以點(diǎn)擊的,即沒有灰顯)。此類缺陷即使對(duì)于經(jīng)驗(yàn)豐富、心思縝 密的測試人員,在人工測試時(shí)也是很可能發(fā)現(xiàn)不了的,并且在自動(dòng)化測試過程中也很難進(jìn)行斷言。即使存在上述問題,
17、測試腳本中是否有充分的斷言,依然是評(píng)判自動(dòng)化測試有效性的一個(gè)重要指標(biāo)。但實(shí)施過自動(dòng)化測試的人應(yīng)該都會(huì)有這樣的體會(huì):“大部分?jǐn)嘌栽诖蟛糠智闆r下只是佐證軟件是運(yùn)行正常的”。當(dāng)然,所有人都應(yīng)該是非常期待看到這樣的結(jié)果,畢竟誰也不希望每次回歸測試時(shí)都是用例大面積不通過。只是辛辛苦苦寫這些斷言語句的測試人員心里未免有些“小遺憾”。本系列上篇文章中談到“很多人一提到自動(dòng)化測試腳本,馬上就想到需要提供錄制工具”,但如果換個(gè)角度思考,很可能就是“柳暗花明又一村”。在這里,我們同樣換個(gè)角度思考,假設(shè)我們的自動(dòng)化測試主要目標(biāo)是為了證明軟件運(yùn)行正常,那么我們會(huì)怎么做?筆者這邊的一個(gè)經(jīng)驗(yàn)就是“按照完整的業(yè)務(wù)流程來組織
18、測試用例,只對(duì)少量、必要的關(guān)鍵點(diǎn)進(jìn)行斷言”。以“租戶對(duì)虛擬化資源的申請使用”為例,來具體看看測試用例的組織方式:1. 新租戶注冊;2. 管理員登錄系統(tǒng),對(duì)注冊租戶進(jìn)行審批,然后退出系統(tǒng);3. 審批后的租戶登錄系統(tǒng);4. 租戶申請所需要的虛擬化資源(比如,40G硬盤、2核CPU、2G存),然后退出系統(tǒng);5. 管理員登錄系統(tǒng),對(duì)租戶申請的資源進(jìn)行審批,然后退出系統(tǒng);6. 租戶登錄系統(tǒng),在已申請資源的基礎(chǔ)上創(chuàng)建安裝指定操作系統(tǒng)的虛擬機(jī);7. 斷言虛擬機(jī)是否創(chuàng)建成功;8. 租戶退出系統(tǒng);9. 管理員登錄系統(tǒng),刪除租戶;10. 斷言租戶之前申請的資源是否被完全釋放;11. 租戶再次登錄系統(tǒng),斷言是否無法
19、登錄;上述測試用例就是按照完整的業(yè)務(wù)流程進(jìn)行組織,并且只對(duì)少量關(guān)鍵點(diǎn)(7、10、11)進(jìn)行斷言,如果整個(gè)用例可以運(yùn)行通過,就能證明這個(gè)業(yè)務(wù)是沒有問題的。另外還有一個(gè)值得考慮的現(xiàn)象,就是相對(duì)于自動(dòng)化測試而言,一個(gè)優(yōu)秀的測試人員在人工測試時(shí)是如何判斷功能正確與否的呢?他不會(huì)死板的只盯著某幾個(gè)輸 入域的值,他一定還會(huì)同時(shí)關(guān)注頁面上所有數(shù)據(jù)的正確性、會(huì)更加關(guān)注業(yè)務(wù)流程是否正確、會(huì)更敏銳的發(fā)現(xiàn)頁面樣式或UI邏輯類的缺陷。為了兼顧“證明軟件正常運(yùn)行”和“人性化的識(shí)別軟件缺陷”,一個(gè)優(yōu)秀的測試工具應(yīng)該考慮提供以下多種斷言機(jī)制。一、 控件級(jí)細(xì)粒度斷言即前面提到的最常見的斷言方式。在測試過程中,可以在任何位置增
20、加斷言腳本,來判斷頁面指定控件是否存在、控件顯示值是否為預(yù)期結(jié)果等。通常建議只對(duì)關(guān)鍵校驗(yàn)點(diǎn)進(jìn)行斷言。二、 頁面級(jí)粗粒度斷言通過對(duì)比前(之前測試通過)后(后續(xù)持續(xù)發(fā)布)版本在測試用例路徑和輸入?yún)?shù)一樣的情 況下,整個(gè)頁面容(包括截圖和數(shù)據(jù))是否嚴(yán)格一樣來做粗粒度斷言。通過頁面截圖進(jìn)行斷言有兩個(gè)實(shí)現(xiàn)要點(diǎn):首先要選擇一個(gè)合適的截圖方案(筆者推薦采用Selenium WebDriver提供的TakesScreenshot接口);其次需要提供圖片對(duì)比工具,以便測試人員可以一眼看出兩個(gè)版本頁面截圖的差異。下面是筆者在測試框架中實(shí)現(xiàn)的截圖自動(dòng)化對(duì)比功能的實(shí)際效果。下圖中左側(cè)部分是“實(shí)際結(jié)果截圖”、右側(cè)是“預(yù)
21、期結(jié)果截圖”、中間部分是差異對(duì)比,測 試人員一眼便可看出其中的Bug:“表格行選中的翻頁緩存(在當(dāng)前頁選中幾條記錄,翻到下一頁再翻回本頁,需要保持之前的行選中狀態(tài))功能丟失了”。通過頁面數(shù)據(jù)進(jìn)行斷言的實(shí)現(xiàn)方式相對(duì)簡單一些,首先要提取頁面上所有的數(shù)據(jù)(或文本),接著進(jìn)行格式化,然后再自動(dòng)化對(duì)比。 “頁面級(jí)粗粒度斷言”的特點(diǎn)與應(yīng)用場景如下:· 無需編寫任何斷言語句;· 需要能夠提供可用于自動(dòng)對(duì)比的歷史正確版本,特別適用于可以持續(xù)構(gòu)建的項(xiàng)目;· 能判斷出UI樣式和UI邏輯類的錯(cuò)誤;· 由于對(duì)比絕對(duì)精準(zhǔn),導(dǎo)致可能存在誤判,因此需要人工對(duì)差異圖片進(jìn)行排查; 注由于
22、很多Web頁面都有漸入漸出、點(diǎn)擊時(shí)按鈕變色等很炫的效果,所以在兩次截圖的瞬間可能頁面的動(dòng)態(tài)樣式是不一樣的,這就是所謂的“誤判”。筆者對(duì) 于一個(gè)“動(dòng)態(tài)樣式”適中的項(xiàng)目采用這種斷言方式,統(tǒng)計(jì)結(jié)果表明誤判率在20%左右。· 鑒于回歸測試的時(shí)候,通常大部分用例應(yīng)該是可以通過的,所以“頁面級(jí)粗粒度斷言”的投入產(chǎn)出比非常占優(yōu)勢!三、 基于業(yè)務(wù)邏輯斷言在測試設(shè)計(jì)時(shí)把有依賴關(guān)系的用例一起執(zhí)行,如果某個(gè)步驟出現(xiàn)問題,即便不設(shè)置任何斷言語句,在當(dāng)前步驟或后續(xù)步驟的測試用例也會(huì)執(zhí)行失敗。下面以“增加、查詢、修改、刪除”這個(gè)最典型的流程來說明(如下圖所示)。假定在“增加”環(huán)節(jié)出現(xiàn)問題,那么我們的測試用例執(zhí)行
23、情況可能出現(xiàn)如下幾種結(jié)果:1. 如果在“增加記錄A”的用例中包含對(duì)是否增加成功的斷言,那么測試用例從“增加記錄A”開始出錯(cuò);2. 如果在“增加記錄A”中不包含斷言,而是在“查詢A”的用例中包含是否有查詢結(jié)果的斷言,那么測試用例會(huì)從“查詢A”開始出錯(cuò);3. 如果在“查詢A”中也不包含斷言,那么測試用例會(huì)從“修改查詢結(jié)果”開始出錯(cuò)。所謂“基于業(yè)務(wù)邏輯斷言”,就是指上述第三種情況,其特點(diǎn)與應(yīng)用場景如下:· 無需編寫任何斷言語句,但測試設(shè)計(jì)要考慮業(yè)務(wù)邏輯順序;· 與“頁面級(jí)粗粒度斷言”相比,不需要提供可用于對(duì)比的歷史正確版本,通常適用于項(xiàng)目剛開發(fā)或樣式做整體調(diào)整等情況;·
24、 斷言錯(cuò)誤的位置不精準(zhǔn),可能延后;· 執(zhí)行過程每一步都做截圖備份(通過Selenium WebDriver可以很方便的實(shí)現(xiàn)),可以非常有效的輔助定位準(zhǔn)確的出錯(cuò)原因;· 鑒于回歸測試的時(shí)候,通常大部分用例應(yīng)該是可以通過的,所以“基于業(yè)務(wù)邏輯斷言”的投入產(chǎn)出比非常占優(yōu)勢!四、 自定義擴(kuò)展斷言在人工測試時(shí)經(jīng)常有些操作結(jié)果的正確與否在當(dāng)前頁面無法做出判斷,需要到其它頁面甚至系統(tǒng)外部(比如,數(shù)據(jù)庫、輸出日志)獲取信息來做出判斷。以最常見的“基于數(shù)據(jù)庫進(jìn)行斷言”為例,測試工具需要支持把斷言時(shí)用到“預(yù)期結(jié)果”和“實(shí)際結(jié)果”配置為對(duì)應(yīng)的SQL語句。以上介紹了從測試工具的角度可以提供的多種斷
25、言機(jī)制,在自動(dòng)化測試過程中應(yīng)該根據(jù)項(xiàng)目實(shí)際情況,考慮采用上述多種斷言的組合,以彌補(bǔ)控件級(jí)細(xì)粒度斷言的不足。ASP.NET MVC集成EntLib實(shí)現(xiàn)“自動(dòng)化”異常處理實(shí)例篇個(gè)人覺得異常處理對(duì)于程序員來說是最為熟悉的同時(shí)也是最難掌握的。說它熟悉,因?yàn)閮H僅就是try/catch/finally而已。說它難以掌握,則是因?yàn)楹芏嚅_發(fā)人員卻說不清楚try/catch/finally應(yīng)該置于何處?什么情況下需要對(duì)異常進(jìn)行日志記錄?什么情況下需要對(duì)異常進(jìn)行封裝?什么情況下需要對(duì)異常進(jìn)行替換?對(duì)于捕獲的異常,在什么情況下需要將其再次拋出?什么情況下則不需要?合理的異常處理應(yīng)該是場景驅(qū)動(dòng)的,在不同的場景下,采用
26、的異常處理策略往往是不同的。異常處理的策略應(yīng)該是可配置的,因?yàn)閼?yīng)用程序出現(xiàn)怎樣的異常往往是不可預(yù)測的,現(xiàn)有異常策略的不足往往需要在真正出現(xiàn)某種異常的時(shí)候才會(huì)體現(xiàn)出來,所以我們需要一種動(dòng)態(tài)可配置的異常處理策略維護(hù)方式。目前有一些開源的異常處理框架提供了這種可配置的、場景驅(qū)動(dòng)的異常處理方式,EntLib的Exception Handling Application Block(以下簡稱EHAB)就是一個(gè)不錯(cuò)的選擇。源代碼從這里下載本文已經(jīng)同步到How ASP.NET MVC Works?中目錄 一、通過指定Handle-Error-Action響應(yīng)請求 二、通過Error View顯示錯(cuò)誤消息 三
27、、自動(dòng)創(chuàng)建JsonResult響應(yīng)Ajax請求一、通過指定Handle-Error-Action響應(yīng)請求在正式介紹如何通過擴(kuò)展實(shí)現(xiàn)與EntLib以實(shí)現(xiàn)自動(dòng)化異常處理之前,我們不妨先來體驗(yàn)一下異常處理具有怎樣的“自動(dòng)化”特性。以用戶登錄場景為例,我們在通過Visual Studio的ASP.NET MVC項(xiàng)目模板創(chuàng)建的Web應(yīng)用中定義了如下一個(gè)簡單的數(shù)據(jù)類型LoginInfo封裝用戶登錄需要輸入的用戶名和密碼。 1: public class LoginInfo 2: 3: DisplayName("用戶名") 4: Required(ErrorMessage="請
28、輸入0") 5: public string UserName get; set; 6: 7: DisplayName("密碼") 8: Required(ErrorMessage = "請輸入0") 9: DataType(DataType.Password) 10: public string Password get; set; 11: 然后我們定義了如下一個(gè)HomeController?;?-GET的Action方法Index將會(huì)呈現(xiàn)一個(gè)用戶登錄View,該View使用創(chuàng)建的LoginInfo對(duì)象作為其Model。真正的用
29、戶驗(yàn)證邏輯定義在另一個(gè)應(yīng)用了 PostAttrubute特性的Index方法中:如果用戶名不為Foo,拋出InvalidUserNameException異常;如果密碼不是“password”,則拋出InvalidPasswordException異常。InvalidUserNameException和InvalidPasswordException是我們自定義的兩種異常類型。 1: ExceptionPolicy("defaultPolicy") 2: public class HomeController : ExtendedController 3: 4: publi
30、c ActionResult Index() 5: 6: return View(new LoginInfo(); 7: 8: 9: Post 10: HandleErrorAction("OnIndexError") 11: public ActionResult Index(LoginInfo loginInfo) 12: 13: if (string pare(loginInfo.UserName, "foo", true) != 0) 14: 15: throw new InvalidUserNameException(); 16:
31、17: 18: if (loginInfo.Password != "password") 19: 20: throw new InvalidPasswordException(); 21: 22: return View(loginInfo); 23: 24: 25: Post 26: public ActionResult OnIndexError(LoginInfo loginInfo) 27: 28: return View(loginInfo); 29: 30: 上面定義的HomeController具有三點(diǎn)與自動(dòng)化異常處理相關(guān)的地方:
32、183; HomeController繼承自自定義的基類ExtendedController,后者完成了對(duì)異常的自動(dòng)化處理。 · HomeController類型上應(yīng)用了自定義的ExceptionPolicyAttribute特性用于指定默認(rèn)采用的異常處理策略名稱(“defaultPolicy”)。 · 基于 -POST的Index方法上應(yīng)用了HandleErrorActionAttribute特性用于指定一個(gè)Handle-Error-Action名稱,當(dāng)異常在目標(biāo)Action執(zhí)行過程中拋出并通過EHAB處理后,指定的Action會(huì)被執(zhí)行以實(shí)現(xiàn)對(duì)請求的響應(yīng)。對(duì)于我們的例子來
33、說,從Index方法拋出的異常被處理后會(huì)調(diào)用OnIndexError方法作為對(duì)當(dāng)前請求的響應(yīng)。 下面是代表登錄頁面的View的定義,這是一個(gè)Model類型為LoginInfo的強(qiáng)類型View。在該View中,作為Model的LoginInfo對(duì)象以編輯默認(rèn)呈現(xiàn)在一個(gè)表單中,表單中提供了一個(gè)“登錄”提交表單。除此之外,View中還具有個(gè)ValidationSummary。 1: model LoginInfo 2: <html> 3: <head> 4: <title>用戶登錄</title> 5: <style type="tex
34、t/css"> 6: .validation-summary-errorscolor:Red 7: </style> 8: </head> 9: <body> 10: using (Html.BeginForm() 11: 12: Html.ValidationSummary(true) 13: Html.EditorForModel() 14: <input type="submit" value="登錄" /> 15: 16: </body> 17: </html>
35、;通過HomeController的定義我們知道兩種不同類型的異常(InvalidUserNameException和InvalidPasswordException)分別在輸入無效用戶名和密碼是被拋出來,而我們需要處理的就是這兩種類型的異常。正對(duì)它們的異常處理策略定義在如下的配置中,策略名稱就是通過應(yīng)用在HomeController上的ExceptionPolicyAttribute特性指定的“defaultPolicy”。 1: <configuration> 2: <configSections> 3: <section name="excepti
36、onHandling" 4: type="Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.Configuration.ExceptionHandlingSettings, Microsoft.Practices.EnterpriseLibrary.ExceptionHandling" /> 5: </configSections> 6: <exceptionHandling> 7: <exceptionPolicies> 8: <add name=&qu
37、ot;defaultPolicy"> 9: <exceptionTypes> 10: <add type="MvcApp.InvalidUserNameException, MvcApp" postHandlingAction="ThrowNewException" name="InvalidUserNameException"> 11: <exceptionHandlers> 12: <add name ="ErrorMessageHandler" typ
38、e="MvcApp.ErrorMessageHandler, MvcApp" errorMessage="用戶名不存在"/> 13: </exceptionHandlers> 14: </add> 15: 16: <add type="MvcApp.InvalidPasswordException, MvcApp" postHandlingAction="ThrowNewException" name="InvalidPasswordException&qu
39、ot;> 17: <exceptionHandlers> 18: <add name ="ErrorMessageHandler" type="MvcApp.ErrorMessageHandler, MvcApp" errorMessage="密碼與用戶名不匹配"/> 19: </exceptionHandlers> 20: </add> 21: </exceptionTypes> 22: </add> 23: </exceptionPolicies&
40、gt; 24: </exceptionHandling> 25: . 26: </configuration>通過上面的這樣異常策略配置可以看到:我們使用一個(gè)自定義的名為ErrorMessageHandler的ExceptionHandler來處理拋出來的InvalidUserNameException和InvalidPasswordException異常,而ErrorMessageHandler僅僅是指定一個(gè)友好的錯(cuò)誤消息,該消息一般會(huì)呈現(xiàn)給最終的用戶。運(yùn)行該程序后一個(gè)用于登錄頁面會(huì)呈現(xiàn)出來,當(dāng)我們輸入錯(cuò)誤的用戶名和密碼的時(shí)候,相應(yīng)的錯(cuò)誤消息(在配置過ErrorMes
41、sageHandler設(shè)置的錯(cuò)誤消息)會(huì)以如圖7-16所示的效果顯示出來,其實(shí)整個(gè)View是通過執(zhí)行Action方法OnIndexError返回的ViewResult呈現(xiàn)出來的。二、通過Error View顯示錯(cuò)誤消息除了通過執(zhí)行對(duì)應(yīng)的Handle-Error-Action來呈現(xiàn)異常處理后的最終結(jié)果之外,還支持錯(cuò)誤頁面的錯(cuò)誤呈現(xiàn)方法。簡單起見,我們只是用名稱為Error的View來作為最終的錯(cuò)誤頁面。為了演示基于錯(cuò)誤頁面的呈現(xiàn)方式,我們按照如下的方式重新定義了ViewsShared目錄下的Error.cshtml。 1: model ExtendedHandleErrorInfo 2: 3:
42、Layout = null; 4: 5: <!DOCTYPE html> 6: <html> 7: <head> 8: <meta name="viewport" content="width=device-width" /> 9: <title>Error</title> 10: <style type="text/css"> 11: h3 color:Red; 12: </style> 13: </head> 14: <
43、;body> 15: <h3> 16: Html.DisplayFor(m=>m.ErrorMessage) 17: </h3> 18: <ul> 19: <li>Controller: Html.DisplayFor(m => m.ControllerName)</li> 20: <li>Action: Html.DisplayFor(m => m.ActionName)</li> 21: <li>Exception: 22: <ul> 23: <li&g
44、t;Message: Html.DisplayFor(m => m.Exception.Message)</li> 24: <li>Type: Model.Exception.GetType().FullName</li> 25: <li>StackTrace: Html.DisplayFor(m => m.Exception.StackTrace)</li> 26: </ul> 27: </li> 28: </ul> 29: </body> 30: </html>
45、;上面這個(gè)View的Model類型是具有如下定義的ExtendedHandleErrorInfo。它繼承自HandleErrorInfo,只額外定義了一個(gè)表示錯(cuò)誤消息的ErrorMessage屬性。在上面的這個(gè)View中,我們將錯(cuò)誤消息、異常類型和StackTrace和當(dāng)前Controller/Action的名稱呈現(xiàn)出來。 1: public class ExtendedHandleErrorInfo : HandleErrorInfo 2: 3: public string ErrorMessage get; private set; 4: public ExtendedHandleErro
46、rInfo(Exception exception, string controllerName, string actionName, string errorMessage) 5: : base(exception, controllerName, actionName) 6: 7: this.ErrorMessage = errorMessage; 8: 9: 當(dāng)利用EntLib的EHAB對(duì)從Index方法中拋出的異常進(jìn)行處理后采用錯(cuò)誤View的方式來響應(yīng)請求,我們需要按照如下的方式將應(yīng)用在該方法上的HandleErrorActionAttribute特性注釋掉。 1: Exceptio
47、nPolicy("defaultPolicy") 2: public class HomeController : ExtendedController 3: 4: /其他成員 5: Post 6: /HandleErrorAction("OnIndexError") 7: public ActionResult Index(LoginInfo loginInfo) 8: 9: /省略實(shí)現(xiàn) 10: 11: 再次運(yùn)行該程序并分別輸入錯(cuò)誤的用戶名和密碼后,默認(rèn)的錯(cuò)誤View(Error.cshtml)將會(huì)以如下圖所示地效果把處理后的異常結(jié)果呈現(xiàn)出來。三、自動(dòng)
48、創(chuàng)建JsonResult響應(yīng)Ajax請求用于實(shí)施認(rèn)證的Action方法Index可以通過普通的 -POST的形式來調(diào)用,同樣也可以通過Ajax請求的方式來調(diào)用。對(duì)于Ajax請求來說,我們最終會(huì)將通過EntLib處理后的異常封裝成如下一個(gè)類型為ExceptionDetail的對(duì)象。如下面的代碼片斷所示,ExceptionDetail具有與Exception對(duì)應(yīng)的屬性設(shè)置。最終根據(jù)拋出異常對(duì)象創(chuàng)建的ExceptionDetail對(duì)象會(huì)被用于創(chuàng)建一個(gè)JsonResult對(duì)象對(duì)當(dāng)前Ajax請求予以響應(yīng)。 1: public class ExceptionDetail 2: 3: public Exce
49、ptionDetail(Exception exception,string errorMessage=null) 4: 5: this.HelpLink = exception.HelpLink; 6: this.Message = string.IsNullOrEmpty(errorMessage) ? exception.Message : errorMessage; 7: this.StackTrace = exception.StackTrace; 8: this.Type = exception.GetType().ToString(); 9: if (exception.Inne
50、rException != null) 10: 11: this.InnerException = new ExceptionDetail(exception.InnerException); 12: 13: 14: 15: public string HelpLink get; set; 16: public ExceptionDetail InnerException get; set; 17: public string Message get; set; 18: public string StackTrace get; set; 19: public string Typ
51、e get; set; 20: 當(dāng)客戶端接收到回復(fù)的Json對(duì)象后,可以通過檢測其是否具有一個(gè)ExceptionType屬性(對(duì)于一個(gè)ExceptionDetail對(duì)象來說,該屬性不可能為Null)來判斷是否發(fā)生異常。作為演示我們對(duì)Action方法Index對(duì)應(yīng)的View進(jìn)行了如下的改動(dòng)。 1: model LoginInfo 2: <html> 3: <head> 4: <title>用戶登錄</title> 5: <script type="text/javascript" src="Url.Content
52、("/Scripts/jquery-1.6.2.js")"></script> 1: 2: <script type="text/javascript" src="Url.Content("/Scripts/jquery.unobtrusive-ajax.js")"> 1: </script> 2: <script type="text/javascript"> 3: function login(data) 4: if
53、 (data.ExceptionType) 5: alert(data.Message); 6: 7: else 8: alert("認(rèn)證成功"); 9: 10: 11: </script> 6: </head> 7: <body> 8: 9: AjaxOptions options = new AjaxOptionsOnSuccess = "login" 10: 11: using (Ajax.BeginForm(options) 12: 13: Html.EditorForModel() 14: <input
54、 type="submit" value="登錄" /> 15: 16: </body> 17: </html>如上面的代碼片斷所示,我們通過調(diào)用AjaxHelper的BuginForm生成了一個(gè)以Ajax形式提交的表單。表單成功提交(服務(wù)端因?qū)伋龅漠惓_M(jìn)行處理而返回一個(gè)封裝異常的Json對(duì)象,對(duì)于提交表單的Ajax請求來說依然屬于成功提交)后會(huì)調(diào)用我們定義的回調(diào)函數(shù)login。在該JavaScript函數(shù)中,我們通過得到的對(duì)象是否具有一個(gè)ExceptionType屬性來判斷服務(wù)端是否拋出異常。如果拋出異常,在通過調(diào)用al
55、ert方法將錯(cuò)誤消息顯示出來,否則顯示“認(rèn)證成功”。我們再次運(yùn)行我們的程序并分別輸入不合法的用戶名和密碼,相應(yīng)的錯(cuò)誤消息會(huì)以對(duì)話框的形式顯示出來,具體的顯示效果如下圖所示。對(duì)于一個(gè)新項(xiàng)目,QA通常會(huì)首先為新特性創(chuàng)建手工測試用例,為了之后維護(hù)方便,也通常將這些用例存放在一Excel表或者一個(gè)專門的測試用例管理 系統(tǒng)里。而在項(xiàng)目進(jìn)行過程中或之后,具備自動(dòng)化測試能力的QA團(tuán)隊(duì)會(huì)將手工測試用例轉(zhuǎn)化為代碼,加入套件(Suite)中,用于之后的回歸。以往我們認(rèn)為手工測試用例與自動(dòng)化代碼之間存在聯(lián)系,但并不緊密:· 手工測試用例文檔很容易閱讀,可以幫助學(xué)習(xí)業(yè)務(wù),但因?yàn)榫S護(hù)不夠靈活,很難跟上快速的變
56、化。依賴手工測試用例對(duì)項(xiàng)目進(jìn)行回歸又是與其痛苦的。· 自動(dòng)化測試代碼可以很明顯的提升效率,但不容易閱讀。因?yàn)槿藗兺ǔH鄙俑麓a注釋的動(dòng)力(沒什么外人會(huì)用到,老鳥又不依賴它),久而久之我們不知道那一堆自動(dòng)化用例究竟測了些什么,導(dǎo)致通過率逐步走低,又無人維護(hù)。自動(dòng)化測試最終土崩瓦解。這似乎是一種宿命般的失敗。有些團(tuán)隊(duì)希望建立自動(dòng)化測試體系,卻從一開始就遇到類似的問題,導(dǎo)致進(jìn)展緩慢,無法持續(xù)向老板秀出效果,最終又退縮回原點(diǎn)。原因是什么?怎么去破解這個(gè)困局呢?1. 用例文檔不應(yīng)該與自動(dòng)化代碼分離,而應(yīng)存在于代碼中,隨著代碼的變化而與時(shí)更新。2. 用例文檔應(yīng)該簡潔,可以自我組織與管理,并以一種清晰的結(jié)構(gòu)被展現(xiàn)和分享。3. 自動(dòng)化測試用例的運(yùn)行歷史應(yīng)該被測量和記錄,數(shù)據(jù)可以集中形成幾個(gè)直接清楚的度量指
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 意向合作借款合同范本
- 超長混凝土結(jié)構(gòu)溫度效應(yīng)與施工期后澆帶對(duì)溫度應(yīng)力的影響研究
- 科技創(chuàng)新對(duì)影視作品版權(quán)的影響及應(yīng)對(duì)
- “思維發(fā)展與提升”素養(yǎng)下高中古代論說文閱讀教學(xué)研究
- 鈷銅共摻雜氮化碳材料制備及其類芬頓降解典型污染物的性能研究
- 勞務(wù)外包費(fèi)合同范本
- 資本新規(guī)背景下資本監(jiān)管對(duì)商業(yè)銀行信貸結(jié)構(gòu)的影響研究
- Turbo碼盲識(shí)別技術(shù)研究
- 高中英語教師提問序列組織特征的會(huì)話分析研究
- 抵押合同范本 黃金
- 人力資源外包合同范本
- 成人重癥患者顱內(nèi)壓增高防控護(hù)理專家共識(shí)2024
- 110KV送出線路工程施工組織設(shè)計(jì)方案和對(duì)策
- 城市交通系統(tǒng)中的空間正義問題-深度研究
- 2024年03月江蘇2024年中國工商銀行蘇州分行社會(huì)招考筆試歷年參考題庫附帶答案詳解
- 2025年北師大新版高二物理上冊階段測試試卷
- 2024年青島職業(yè)技術(shù)學(xué)院高職單招語文歷年參考題庫含答案解析
- 北師大版數(shù)學(xué)三下集體備課計(jì)劃
- 《餐飲服務(wù)禮貌用語》課件
- 2025年中國融通資產(chǎn)管理集團(tuán)限公司春季招聘(511人)高頻重點(diǎn)提升(共500題)附帶答案詳解
- 2024年纖維混合絮片項(xiàng)目可行性研究報(bào)告
評(píng)論
0/150
提交評(píng)論