- Web測(cè)試囧事
- 黃勇等
- 2234字
- 2019-01-05 03:43:28
提到測(cè)試,大家首先會(huì)想到的就是功能性的測(cè)試,因?yàn)橹挥斜WC了產(chǎn)品的基本功能和流程,產(chǎn)品才具備給用戶(hù)提供使用價(jià)值的能力,從而才有可能確定產(chǎn)品的核心競(jìng)爭(zhēng)力。基于這一點(diǎn),不僅測(cè)試人員和開(kāi)發(fā)人員,還有產(chǎn)品經(jīng)理、項(xiàng)目經(jīng)理、業(yè)務(wù)方對(duì)功能完備性和正確性的重視程度也往往都是最高的。這也使得功能測(cè)試成為任何測(cè)試類(lèi)型的基礎(chǔ)。
在進(jìn)行功能測(cè)試時(shí),我們會(huì)使用諸如邊界值分析、等價(jià)類(lèi)劃分、因果分析、組合測(cè)試(Pairwise Testing)等測(cè)試方法來(lái)設(shè)計(jì)和規(guī)劃測(cè)試用例,但是這些方法大多都是從書(shū)本上學(xué)來(lái)或者從別的渠道了解到的理論方法。而實(shí)際上在一個(gè)真實(shí)的項(xiàng)目中如何運(yùn)用,或者如何在特定的場(chǎng)景和情境下使用這些方法,去充分發(fā)揮這些測(cè)試方法的作用,并幫助我們高效地設(shè)計(jì)和執(zhí)行測(cè)試用例卻是更重要的問(wèn)題。
正因如此,我們?cè)诠δ軠y(cè)試部分并沒(méi)有介紹這些方法是什么,而重點(diǎn)在于展示在一個(gè)具體的場(chǎng)景下,讀者應(yīng)該如何思考,怎么把理論知識(shí)和實(shí)際工作結(jié)合起來(lái),以發(fā)現(xiàn)和避免可能遇到的陷阱。
功能測(cè)試部分的故事篇幅都會(huì)比較長(zhǎng),希望讀者能夠每讀完一個(gè)故事,都留出一段時(shí)間進(jìn)行思索和回味,從而理解故事的核心,觸類(lèi)旁通。
為了讓每一章的故事更凝練,我們把功能測(cè)試部分分成了4章,分別是:技術(shù)篇、測(cè)試覆蓋篇、測(cè)試實(shí)踐篇和業(yè)務(wù)需求篇。這4章從Web開(kāi)發(fā)流行的各種技術(shù)(例如響應(yīng)式設(shè)計(jì)、特性開(kāi)關(guān)、虛擬化等)、測(cè)試技術(shù)(例如實(shí)例化需求、集成測(cè)試、契約測(cè)試等)、測(cè)試實(shí)踐(例如探索性測(cè)試、回顧會(huì)議、缺陷大掃除等)和業(yè)務(wù)需求(例如用戶(hù)的并發(fā)操作、關(guān)聯(lián)操作以及產(chǎn)品功能的一致性等)方面向讀者全方位展示功能測(cè)試范疇中的常見(jiàn)問(wèn)題和解決辦法,更重要的是指引大家從一步一步的分析中得到解決問(wèn)題的思路。
本章(技術(shù)篇)介紹了在開(kāi)發(fā)和測(cè)試的技術(shù)方面引起的11個(gè)功能測(cè)試問(wèn)題,現(xiàn)在大家和我們一起來(lái)看看這些豐富多彩的故事。
1.1 輸入框中輸入超過(guò)最大允許值造成頁(yè)面跳轉(zhuǎn)溢出
作為計(jì)算機(jī)系畢業(yè)生的小蔡,一直覺(jué)得學(xué)校里學(xué)的理論知識(shí)和現(xiàn)在的測(cè)試工作差距太大,在實(shí)際的工作中也沒(méi)有什么作用,直到有一天她碰到這么一個(gè)有趣的問(wèn)題。
小蔡負(fù)責(zé)測(cè)試的是一個(gè)Web產(chǎn)品,基于不同的搜索條件會(huì)顯示大量的結(jié)果。由于搜索結(jié)果太多,所以頁(yè)面有分頁(yè)功能,為了方便用戶(hù)快捷跳轉(zhuǎn)到特定的頁(yè)面,開(kāi)發(fā)人員特意設(shè)計(jì)了一個(gè)頁(yè)面快速跳轉(zhuǎn)的功能(見(jiàn)圖1-1)。

圖1-1 搜索結(jié)果頁(yè)面快速跳轉(zhuǎn)
在設(shè)計(jì)測(cè)試用例的時(shí)候小蔡就留心了,因?yàn)楹芏鄿y(cè)試?yán)碚摰臅?shū)籍都描述過(guò),對(duì)于輸入框可以進(jìn)行的驗(yàn)證點(diǎn)很多,比如:特殊字符、超長(zhǎng)字符、負(fù)值、0值和null值,以及很大的數(shù)值等。小蔡發(fā)現(xiàn),對(duì)于大部分的測(cè)試用例,開(kāi)發(fā)人員都處理得很好,沒(méi)有發(fā)現(xiàn)缺陷,她也就松了口氣。
但是,當(dāng)她測(cè)試到輸入大數(shù)值的測(cè)試用例時(shí),由于不確定多大的數(shù)值會(huì)出錯(cuò),也不能拿到代碼,小蔡就探索性地選了一個(gè)數(shù)值:9999999999(10個(gè)“9”)。當(dāng)輸入10個(gè)“9”點(diǎn)擊“確定”按鈕時(shí),突然頁(yè)面崩潰了!她仔細(xì)回想剛才的測(cè)試過(guò)程:100以?xún)?nèi)的小數(shù)值,以及輸入小于等于搜索結(jié)果頁(yè)面數(shù)的數(shù)值等情況,測(cè)試結(jié)果都很正常。那到底數(shù)值大到什么程度的時(shí)候頁(yè)面會(huì)崩潰呢?一時(shí)想不到更好的辦法,小蔡只好硬著頭皮嘗試著定位出錯(cuò)的數(shù)值范圍。
她發(fā)現(xiàn),當(dāng)輸入10個(gè)“9”就會(huì)出錯(cuò),而輸入9個(gè)“9”,頁(yè)面正常跳轉(zhuǎn)到最后一頁(yè)。突然,小蔡想起來(lái)數(shù)據(jù)結(jié)構(gòu)課程不是學(xué)過(guò)很多查找法嘛!這樣,二分法就這么出現(xiàn)在了眼前,對(duì),二分查找法(見(jiàn)圖1-2)! 5000000000(9個(gè)“0”),出錯(cuò);2500000000(8個(gè)“0”),正常。她還是沒(méi)有線(xiàn)索,可是她堅(jiān)持這么一點(diǎn)一點(diǎn)查找。最后花了將近3個(gè)小時(shí),小蔡終于定位到了出錯(cuò)的數(shù)值:4294967295。這個(gè)時(shí)候,小蔡很納悶,怎么是這么一個(gè)奇怪的數(shù)值呢?有零有整的。計(jì)算機(jī)專(zhuān)業(yè)的背景給了小蔡一個(gè)提示,不會(huì)是2的多少次冪吧?果真,4294967295是232-1。當(dāng)小蔡收集到這些線(xiàn)索之后和開(kāi)發(fā)人員一溝通,才發(fā)現(xiàn)由于開(kāi)發(fā)人員設(shè)想頁(yè)面最大不會(huì)超過(guò)232,所以對(duì)這個(gè)字段可以輸入的最大數(shù)值的類(lèi)型,選擇的是int32。但是,開(kāi)發(fā)人員并沒(méi)有對(duì)超過(guò)這個(gè)范圍的數(shù)值進(jìn)行任何的處理,這就造成了程序判斷中請(qǐng)求更大數(shù)值頁(yè)面時(shí)的溢出,從而導(dǎo)致了產(chǎn)品頁(yè)面的崩潰。

圖1-2 二分查找的原理
提示
二分查找算法(binary search)或者折半查找算法,是一種在有序數(shù)組中查找某一特定元素的搜索算法。
搜索過(guò)程從數(shù)組的中間元素開(kāi)始,如果中間元素正好是要查找的元素,則搜索過(guò)程結(jié)束;如果某一特定元素大于或者小于中間元素,則在數(shù)組大于或小于中間元素的那一半中查找,而且跟開(kāi)始一樣從中間元素開(kāi)始比較。如果在某一步驟數(shù)組為空,則代表找不到。這種搜索算法每一次比較都使搜索范圍縮小一半。
發(fā)現(xiàn)了這個(gè)隱藏的缺陷,小蔡很有成就感,但又覺(jué)得如果能早點(diǎn)知道代碼的邏輯,可能自己就不會(huì)花這么長(zhǎng)的時(shí)間了。同時(shí),小蔡一直覺(jué)得計(jì)算機(jī)的理論知識(shí)不會(huì)應(yīng)用到測(cè)試實(shí)踐中,可沒(méi)想到這次多虧了學(xué)校中學(xué)到的這些基礎(chǔ)知識(shí),不只是int32,232,甚至還有二分查找算法也給了自己解決問(wèn)題的靈感。沒(méi)有這些知識(shí),定位問(wèn)題就更困難了。
核心知識(shí):邊界值分析法
邊界值分析法是一種常見(jiàn)的黑盒測(cè)試方法。
測(cè)試界的前輩們通過(guò)分析常見(jiàn)Bug,發(fā)現(xiàn)絕大多數(shù)的Bug都出現(xiàn)在輸入/輸出范圍的邊界處。因此,如果能夠針對(duì)這些邊界來(lái)設(shè)計(jì)用例,通常能夠更加有效。
邊界值測(cè)試法通常是作為等價(jià)類(lèi)測(cè)試法的補(bǔ)充,和等價(jià)類(lèi)測(cè)試法結(jié)合起來(lái)用。即每個(gè)等價(jià)類(lèi)的邊界部分就可以作為邊界值的測(cè)試用例之一。
舉個(gè)例子。假設(shè)有一個(gè)日期選擇器(date picker)的需求,要求我們能夠輸入時(shí)間后,點(diǎn)擊搜索查詢(xún)輸入日期前后一年范圍內(nèi)的數(shù)據(jù)。假設(shè)我們把輸入的時(shí)間分為如下幾個(gè)等價(jià)類(lèi):
1)正常時(shí)間范圍內(nèi):now-1年< test data < now+1年;
2)正常時(shí)間范圍外:test data < now-1年或者test data > now+1年
3)特殊時(shí)間:例如now=2月29,1970/01/01等
4)輸入非時(shí)間的input value:比如輸入值為@等
……
結(jié)合分類(lèi)1、2,這個(gè)時(shí)候邊界值的取值則可以取:
▼test data=now-1年;
▼test data=now+1年;
▼test data=now-1年-1天;
▼test data=now-1年+1天
……
考慮到輸出范圍是一整年的數(shù)據(jù),結(jié)合特殊時(shí)間和時(shí)間的邊界(跨年、跨月等),還可以增加
▼test data=2月29
▼test data=12月31號(hào)
▼test data=1月1號(hào)
……
總之,邊界值的取值,應(yīng)該著重考慮邊界情況。如果測(cè)試對(duì)象是時(shí)間,則應(yīng)該重點(diǎn)考慮跨年、跨月等;如果測(cè)試對(duì)象是純數(shù)字,則應(yīng)該重點(diǎn)考慮數(shù)字的類(lèi)型與取值范圍;如果測(cè)試對(duì)象是數(shù)據(jù)表,則應(yīng)該重點(diǎn)考慮數(shù)據(jù)表設(shè)計(jì)的字段長(zhǎng)度,等等。
拓展知識(shí):測(cè)試用例設(shè)計(jì)
測(cè)試用例記錄了測(cè)試的過(guò)程,我們可以通過(guò)測(cè)試用例了解哪些場(chǎng)景已經(jīng)被驗(yàn)證了,哪些場(chǎng)景還沒(méi)有被驗(yàn)證。除此之外,在傳統(tǒng)的測(cè)試行業(yè)中,測(cè)試用例數(shù)量通常也被作為度量測(cè)試工作量和指定測(cè)試工作計(jì)劃的重要輸入。
測(cè)試用例通常會(huì)包含幾個(gè)基本要素:用例編號(hào)、輸入數(shù)據(jù)、期望結(jié)果以及前置條件等。測(cè)試覆蓋率則是評(píng)價(jià)測(cè)試用例好壞的關(guān)鍵標(biāo)準(zhǔn)。覆蓋率高的測(cè)試用例能夠提高開(kāi)發(fā)、產(chǎn)品以及其他驗(yàn)收人員對(duì)產(chǎn)品的信心。在設(shè)計(jì)過(guò)程中,我們通常會(huì)通過(guò)邊界值、等價(jià)類(lèi)等測(cè)試方法,結(jié)合配對(duì)組合測(cè)試(pairwise testing),基本路徑分析法等測(cè)試策略?xún)?yōu)化測(cè)試用例,以達(dá)到提升測(cè)試覆蓋率和減少冗余測(cè)試用例的方法。
以下是測(cè)試用例設(shè)計(jì)原則。
1)測(cè)試用例的代表性:能夠代表并覆蓋各種合理的和不合理的、合法的和非法的、邊界的和越界的以及極限的輸入數(shù)據(jù)、操作和環(huán)境設(shè)置等。
2)測(cè)試結(jié)果的可判定性:即測(cè)試執(zhí)行結(jié)果的正確性是可判定的,每一個(gè)測(cè)試用例都應(yīng)有相應(yīng)的期望結(jié)果。
3)測(cè)試結(jié)果的可再現(xiàn)性:即對(duì)同樣的測(cè)試用例,系統(tǒng)的執(zhí)行結(jié)果應(yīng)當(dāng)是相同的。
1.2 索引值計(jì)算錯(cuò)誤使資源縮略圖顯示和大圖展現(xiàn)不一致
業(yè)務(wù)方希望在商品展示的頁(yè)面,不僅能添加展示圖片,還可以展示關(guān)于商品的視頻(見(jiàn)圖1-3)。

圖1-3 商品展示頁(yè)面支持展示圖片和視頻
業(yè)務(wù)方希望通過(guò)圖1-3下方的統(tǒng)一翻頁(yè)操作,實(shí)現(xiàn)無(wú)縫瀏覽圖片和視頻。如果商品既有圖片又有視頻,當(dāng)用戶(hù)在瀏覽圖片時(shí),在圖1-3右下角顯示“Video”(視頻),這時(shí)用戶(hù)可以通過(guò)點(diǎn)擊“Video”鏈接打開(kāi)第一個(gè)視頻;同樣當(dāng)用戶(hù)在瀏覽視頻時(shí),在圖1-3右下角顯示“Image”(圖片),這時(shí)用戶(hù)可以通過(guò)點(diǎn)擊“Image”鏈接打開(kāi)第一張圖片。
小蔡按照通常的步驟編寫(xiě)完測(cè)試用例,開(kāi)始使用標(biāo)準(zhǔn)測(cè)試數(shù)據(jù)執(zhí)行測(cè)試。小蔡首先發(fā)現(xiàn)點(diǎn)擊右下角鏈接時(shí),本應(yīng)該顯示第1張圖片或者視頻,但是打開(kāi)的卻是第2張圖片或者視頻。
小蔡覺(jué)得這可能是開(kāi)發(fā)人員在處理圖片和視頻展示的數(shù)組時(shí),使用的是自然數(shù)計(jì)數(shù),從1開(kāi)始作為第1個(gè)數(shù)據(jù)項(xiàng),而非計(jì)算機(jī)程序數(shù)組中通常使用的把從0開(kāi)始計(jì)數(shù)作為第一個(gè)數(shù)據(jù)項(xiàng)。當(dāng)小蔡把這一問(wèn)題上報(bào)之后,開(kāi)發(fā)人員發(fā)現(xiàn)確實(shí)是這個(gè)原因,并進(jìn)行了快速修正。
小蔡在開(kāi)發(fā)人員新發(fā)布的包上又一次進(jìn)行了測(cè)試,這次測(cè)試用例基本沒(méi)有什么問(wèn)題,她就開(kāi)始在類(lèi)真實(shí)環(huán)境中執(zhí)行探索性測(cè)試,結(jié)果發(fā)現(xiàn)在某些商品頁(yè)面進(jìn)行圖片和視頻跳轉(zhuǎn)時(shí),出現(xiàn)圖片或視頻顯示錯(cuò)誤或者顯示成空白的問(wèn)題。
在老牛的協(xié)助下,小蔡發(fā)現(xiàn)了問(wèn)題出現(xiàn)的兩個(gè)規(guī)律:①當(dāng)從第n張圖片切換到視頻的時(shí)候,系統(tǒng)顯示的并不是用戶(hù)期待的第1個(gè)視頻,而是第n個(gè)視頻;②當(dāng)商品的圖片和視頻數(shù)量不一致,從數(shù)量多的資源切換到另一個(gè)數(shù)量少的資源時(shí),內(nèi)容就會(huì)出現(xiàn)空白。
小蔡和老牛都覺(jué)得出現(xiàn)問(wèn)題的原因比較明確了,是因?yàn)樵趫D片和視頻跳轉(zhuǎn)時(shí),打開(kāi)資源的索引值并沒(méi)有清零,而是保存著前一個(gè)元素的索引值。
為什么這個(gè)問(wèn)題在測(cè)試環(huán)境中沒(méi)有發(fā)現(xiàn),而在類(lèi)真實(shí)環(huán)境中才被發(fā)現(xiàn)?原來(lái)最初小蔡在測(cè)試環(huán)境中執(zhí)行測(cè)試用例的時(shí)候,使用的是基本測(cè)試數(shù)據(jù),圖片和視頻都只有兩個(gè),而且兩張圖片和兩個(gè)視頻的內(nèi)容分別都是一樣的,因此不會(huì)出現(xiàn)這個(gè)問(wèn)題。
小蔡和老牛商量了下,決定為了避免遺漏這樣的問(wèn)題,需要豐富測(cè)試環(huán)境的測(cè)試數(shù)據(jù),使得測(cè)試數(shù)據(jù)更像真實(shí)數(shù)據(jù),這樣測(cè)試結(jié)果才更為準(zhǔn)確。
同時(shí)他們認(rèn)為這個(gè)問(wèn)題在開(kāi)發(fā)人員的開(kāi)發(fā)過(guò)程中也是不應(yīng)該引入的,因?yàn)檫@樣的錯(cuò)誤比較初級(jí)。于是小蔡和開(kāi)發(fā)人員進(jìn)行了溝通,發(fā)現(xiàn)引入該問(wèn)題的根源在于開(kāi)發(fā)人員的疏忽。由于圖片的文件格式和視頻的文件格式不同,所以開(kāi)發(fā)人員使用了兩個(gè)庫(kù)來(lái)支持圖片和視頻的打開(kāi),但是兩個(gè)庫(kù)之間的跳轉(zhuǎn)需要通過(guò)在兩個(gè)庫(kù)之間傳遞參數(shù)來(lái)實(shí)現(xiàn),然而開(kāi)發(fā)人員并沒(méi)有仔細(xì)檢查兩個(gè)庫(kù)之間所傳遞的參數(shù),導(dǎo)致并不需要被傳遞的索引值也傳遞到另一個(gè)庫(kù)中。
老牛帶著小蔡和開(kāi)發(fā)人員立下一個(gè)約定:在使用第三方庫(kù)實(shí)現(xiàn)功能時(shí),一定要把使用的函數(shù)方法中的所有參數(shù)都核對(duì)清楚。
核心知識(shí)①:探索性測(cè)試
探索性測(cè)試(Exploratory Testing)是軟件測(cè)試方法的一種。這種方法強(qiáng)調(diào)測(cè)試者的主觀能動(dòng)性,以及測(cè)試設(shè)計(jì)和測(cè)試執(zhí)行的同時(shí)性。目的是探索開(kāi)發(fā)更多不同形態(tài)的測(cè)試方法,以便改善測(cè)試流程。
“先設(shè)計(jì),再測(cè)試”的傳統(tǒng)做法,通常是先分析出測(cè)試點(diǎn),然后針對(duì)測(cè)點(diǎn)設(shè)計(jì)好測(cè)試方法,最后執(zhí)行測(cè)試。這種模式也帶來(lái)了一些問(wèn)題,比如在測(cè)試目標(biāo)不確定的情況下(改需求、輸出范圍過(guò)大等)經(jīng)常可能出現(xiàn)測(cè)試遺漏等,而且在一定程度上也限制了測(cè)試思維的發(fā)散。而探索性測(cè)試的出現(xiàn),正好彌補(bǔ)了傳統(tǒng)測(cè)試中出現(xiàn)的這種問(wèn)題。
探索式軟件測(cè)試一共分為自由式探索式測(cè)試、基于場(chǎng)景的探索式測(cè)試、基于策略的探索式測(cè)試和基于反饋的探索式測(cè)試。
(1)自由式探索
純粹從使用的角度出發(fā),拋開(kāi)規(guī)則、模式,測(cè)試人員可以以任意順序和方式對(duì)軟件進(jìn)行使用測(cè)試。這種測(cè)試通常會(huì)被選作快速冒煙測(cè)試用例。
(2)基于場(chǎng)景的探索式測(cè)試
這種測(cè)試跟傳統(tǒng)基于場(chǎng)景的測(cè)試比較像,不同的是,在這種測(cè)試中測(cè)試人員會(huì)擴(kuò)大測(cè)試范圍。例如,對(duì)某搜索框的測(cè)試,傳統(tǒng)的場(chǎng)景測(cè)試用例可能是:
1)輸入“電視”,期望結(jié)果是搜索到電視;
2)輸入“123”,搜索到123相關(guān)的內(nèi)容。
而基于場(chǎng)景的探索性測(cè)試下,測(cè)試場(chǎng)景則可能是:
1)輸入“電視”,探索搜索結(jié)果;
2)粘貼“ 1@3”,搜索結(jié)果;
3)輸入一個(gè)亂碼,搜索結(jié)果;
4)輸入電視,搜索結(jié)果后回退到搜索首頁(yè)再搜索;
……
(3)基于策略的探索性測(cè)試
這是一種比較依靠經(jīng)驗(yàn)的測(cè)試方式。簡(jiǎn)單講就是測(cè)試?yán)鲜郑诤献约旱慕?jīng)驗(yàn)、技能、感知等條件,結(jié)合自由式探索性測(cè)試,用自己積累下來(lái)的知識(shí)來(lái)指導(dǎo)測(cè)試。是一種經(jīng)驗(yàn)結(jié)合隨機(jī)性的測(cè)試。
(4)基于反饋的探索性測(cè)試
反饋指的是當(dāng)測(cè)試人員對(duì)被測(cè)程序做出指令后得到的響應(yīng)結(jié)果。基于這個(gè)結(jié)果,測(cè)試人員可以調(diào)整自己的輸入,以期望得到不同的結(jié)果。例如,在基于場(chǎng)景的探索性測(cè)試的描述中,輸入電視和輸入電冰箱會(huì)得到不同的結(jié)果,而其中電視的搜索結(jié)果就是對(duì)電視這個(gè)輸入的反饋,電冰箱的結(jié)果就是對(duì)電冰箱這個(gè)輸入的反饋。
核心知識(shí)②:軟件開(kāi)發(fā)中的各種環(huán)境
1)開(kāi)發(fā)環(huán)境:就是每個(gè)開(kāi)發(fā)人員進(jìn)行編程的電腦,包括軟硬件及其配置,為了開(kāi)發(fā)調(diào)試方便,一般打開(kāi)全部錯(cuò)誤報(bào)告。
2)測(cè)試環(huán)境:測(cè)試人員進(jìn)行產(chǎn)品部署,并進(jìn)行功能等測(cè)試的環(huán)境。
3)預(yù)生產(chǎn)環(huán)境(非必須):與生產(chǎn)環(huán)境不定期同步,保持和生產(chǎn)環(huán)境的設(shè)置、數(shù)據(jù)的一致性,也是用于測(cè)試的環(huán)境。與測(cè)試環(huán)境的最大區(qū)別就是它和生產(chǎn)系統(tǒng)同步性最高,有些比如數(shù)據(jù)遷移測(cè)試,用這個(gè)環(huán)境測(cè)試比測(cè)試環(huán)境(一般情況下數(shù)據(jù)較少)更準(zhǔn)確。
4)生產(chǎn)環(huán)境:正式使用的系統(tǒng)環(huán)境,一般會(huì)關(guān)掉錯(cuò)誤報(bào)告,打開(kāi)錯(cuò)誤日志。
通常情況下,一個(gè)環(huán)境對(duì)應(yīng)一個(gè)服務(wù)器,不同環(huán)境代表著系統(tǒng)開(kāi)發(fā)的不同階段:開(kāi)發(fā)→測(cè)試→部署→上線(xiàn)。
1.3 測(cè)試Web Service能否正常提供JSON數(shù)據(jù)
某一天,小蔡所在的項(xiàng)目組剛開(kāi)發(fā)完成一個(gè)Web Service,服務(wù)的功能是,通過(guò)在客戶(hù)端調(diào)用時(shí)指定的一個(gè)ID,可以從后臺(tái)數(shù)據(jù)庫(kù)中讀取對(duì)應(yīng)的房產(chǎn)信息,還有與這個(gè)房產(chǎn)關(guān)聯(lián)的一到多個(gè)房東信息、一到多個(gè)圖片信息,以及地址信息等。Web Service最終把這些信息組合成JSON格式的數(shù)據(jù)返回給調(diào)用方,調(diào)用方可以通過(guò)界面來(lái)展示相關(guān)信息,也可以通過(guò)其他方式去使用這些信息。但是,調(diào)用方具體如何使用這些信息與Web Service服務(wù)本身的測(cè)試關(guān)系不大,所以暫且不表了。小蔡需要做的是驗(yàn)證這個(gè)Web Service服務(wù)能否正常地提供JSON數(shù)據(jù)。
1.尋找測(cè)試關(guān)鍵點(diǎn)
和開(kāi)發(fā)人員討論后,小蔡了解到,給Web Service服務(wù)發(fā)送ID后,后臺(tái)系統(tǒng)會(huì)根據(jù)這個(gè)ID去查詢(xún)數(shù)據(jù)庫(kù),數(shù)據(jù)庫(kù)對(duì)應(yīng)的對(duì)象模型如圖1-4所示。

圖1-4 生成JSON的對(duì)象模型
在這個(gè)對(duì)象關(guān)系圖里可以看到,Building對(duì)象是圖的核心,其他對(duì)象分別和Building對(duì)象是一對(duì)一或者一對(duì)多的關(guān)系。那么小蔡覺(jué)得,測(cè)試的關(guān)鍵點(diǎn)就是這些數(shù)據(jù)之間的關(guān)系能否正確反映在生成的JSON數(shù)據(jù)里。(特別是要確保生成的JSON數(shù)據(jù)的格式?jīng)]有被破壞,否則解析器就無(wú)法解析JSON數(shù)據(jù)了。)
2.爬樓梯開(kāi)始了
在確定好測(cè)試點(diǎn)之后,小蔡測(cè)試思路如下。
1)依據(jù)邊界值進(jìn)行測(cè)試。由于數(shù)據(jù)庫(kù)的數(shù)據(jù)存在多種情況:0條記錄、單條記錄、多條記錄,需要驗(yàn)證根據(jù)這些數(shù)據(jù)條數(shù)生成的JSON文件是否正確。
2)需要關(guān)注對(duì)象之間的關(guān)聯(lián)關(guān)系限制。例如一個(gè)Building對(duì)應(yīng)0到4個(gè)Callout,那么需要測(cè)試當(dāng)多于4個(gè)Callout時(shí),生成的JSON的情況。
3)Web Service允許用戶(hù)輸入?yún)?shù),所以需要驗(yàn)證輸入特殊數(shù)據(jù)后,系統(tǒng)是否出現(xiàn)異常或者崩潰的現(xiàn)象,以及是否會(huì)出現(xiàn)SQL注入的問(wèn)題。
4)Web Service有可能會(huì)被多個(gè)客戶(hù)端并發(fā)調(diào)用,因此需要驗(yàn)證其性能是否符合設(shè)計(jì)要求。
根據(jù)測(cè)試思路,小蔡設(shè)計(jì)了如下測(cè)試用例。
1)Building對(duì)象可以有多個(gè)Space,所以可以選取0個(gè)、1個(gè)、6個(gè)Space去看生成的JSON是否正確,這個(gè)可以通過(guò)修改數(shù)據(jù)庫(kù)數(shù)據(jù)的方式生成假數(shù)據(jù)去完成相關(guān)測(cè)試。另外,如圖1-4所示,小蔡還需要測(cè)試Building和其他對(duì)象的關(guān)系,包括Customer、MediaLink等。小蔡還特別注意了邊界值測(cè)試,比如,一個(gè)Building對(duì)應(yīng)0~4個(gè)Callout,那么可以用0、1、4、5個(gè)Callout去測(cè)試。當(dāng)有5個(gè)Callout的時(shí)候,要去查看返回的JSON數(shù)據(jù)是返回了前4個(gè)Callout,還是返回了前5個(gè),又或者拋出了異常,當(dāng)然,具體哪種結(jié)果是程序設(shè)計(jì)所期望的,需要和開(kāi)發(fā)人員去溝通。
2)調(diào)用Web Service時(shí)需要指定ID,所以可以測(cè)試在ID存在和不存在兩種情況下JSON結(jié)果是否返回正常。
3)異常處理,調(diào)用Web Service時(shí)可以把ID換成錯(cuò)誤的參數(shù),例如null、非常長(zhǎng)的字符串、空字符串、英文字符、其他文字(例如中文字符)等。接著小蔡就去驗(yàn)證服務(wù)對(duì)異常是否做出了正確的處理。
4)安全測(cè)試,這個(gè)Web Service會(huì)被外網(wǎng)使用,那就需要在安全性上投入更多的測(cè)試。例如,如果URL可以輸入任何參數(shù),這些參數(shù)是否包含危險(xiǎn)數(shù)據(jù)導(dǎo)致SQL注入這類(lèi)安全問(wèn)題。還有,因?yàn)閃eb Service被外網(wǎng)使用,那在調(diào)用這個(gè)服務(wù)時(shí)是否需要提供用戶(hù)名和密碼。
JSON使用了一種特殊描述數(shù)據(jù)的方式,用“, ”、“[”、“]”、“{”、“}”等分割數(shù)據(jù),小蔡需要測(cè)試,如果數(shù)據(jù)庫(kù)存儲(chǔ)的數(shù)據(jù)恰好有這些符號(hào),這些數(shù)據(jù)被讀取并生成為JSON后是否會(huì)破壞JSON的格式。
5)性能測(cè)試,如何對(duì)Web Service進(jìn)行性能測(cè)試呢,快速測(cè)試方式就是通過(guò)一些工具的多線(xiàn)程調(diào)用,或者手工編寫(xiě)簡(jiǎn)單多線(xiàn)程代碼去調(diào)用,然后查看持續(xù)調(diào)用兩小時(shí)之后服務(wù)是否正常,服務(wù)后臺(tái)內(nèi)存曲線(xiàn)是否出現(xiàn)異常,有沒(méi)有出現(xiàn)內(nèi)存泄露等問(wèn)題。另外,查看Web Service是否能在符合性能期望的時(shí)間內(nèi)返回?cái)?shù)據(jù)。
還有一個(gè)邊緣的性能測(cè)試路徑是:一個(gè)對(duì)象有成千上萬(wàn)個(gè)關(guān)聯(lián)子對(duì)象,能否正常生成對(duì)應(yīng)的JSON文件,以及性能是否能達(dá)到期望目標(biāo)。慶幸小蔡這次測(cè)試任務(wù)不需要這么做,因?yàn)楹笈_(tái)數(shù)據(jù)明確了不可能存在這種情況,但是在別的測(cè)試任務(wù)中可能需要測(cè)試。
提示
假設(shè)一種大數(shù)據(jù)量的場(chǎng)景,如果關(guān)聯(lián)的對(duì)象有10萬(wàn)個(gè),我們可以通過(guò)工具在數(shù)據(jù)庫(kù)中生成10萬(wàn)條數(shù)據(jù)。這時(shí)候,生成的JSON文件可能會(huì)有幾十兆,那么我們要看需求文檔,對(duì)這種場(chǎng)景期待的性能指標(biāo)是多少,例如單個(gè)用戶(hù)調(diào)用的話(huà)5分鐘之內(nèi)需要生成完畢,20個(gè)用戶(hù)并發(fā)情況下10分鐘生成完畢。我們需要驗(yàn)證是否5分鐘或者10分鐘內(nèi)能生成完畢,同時(shí)還要驗(yàn)證,在這個(gè)過(guò)程中,后臺(tái)內(nèi)存增長(zhǎng)曲線(xiàn)是否出現(xiàn)過(guò)于陡峭的現(xiàn)象。
6)查看生成的JSON數(shù)據(jù)中,一些特殊類(lèi)型的數(shù)據(jù)是否和數(shù)據(jù)庫(kù)完全一致。例如,對(duì)于float類(lèi)型,有個(gè)Bug是該類(lèi)型數(shù)據(jù)精度在數(shù)據(jù)庫(kù)中是保存到小數(shù)點(diǎn)后8位,但生成的JSON中只保留小數(shù)點(diǎn)后2位;類(lèi)似的特殊數(shù)據(jù)還包括非常長(zhǎng)的字符串,需要查看是否被截?cái)啵蝗绻跀?shù)據(jù)庫(kù)中保存的是0,在JSON中是否會(huì)生成0.00,此外還可以查看空字符串是否正確生成在JSON中。
7)確定服務(wù)是否需要支持HTTPS加密,如果需要,就要去測(cè)試返回結(jié)果是否正常。
哈哈!終于爬完樓梯了,小蔡可以松口氣了,走!喝杯啤酒,再來(lái)塊炸雞么?
1.4 利用JavaScript加載的漏洞提前購(gòu)買(mǎi)搶購(gòu)商品
自從小米手機(jī)推出以來(lái),搶購(gòu)風(fēng)潮在各類(lèi)網(wǎng)站上盛行起來(lái),小蔡測(cè)試的網(wǎng)站自然也不能免俗,項(xiàng)目組開(kāi)發(fā)的網(wǎng)站也包含了搶購(gòu)功能。
對(duì)于搶購(gòu)來(lái)說(shuō),只有到了特定的時(shí)間后,商品才會(huì)開(kāi)放并允許搶購(gòu),并且搶購(gòu)網(wǎng)頁(yè)的代碼里使用的時(shí)間會(huì)定期和服務(wù)器進(jìn)行同步。
小蔡設(shè)計(jì)了豐富和全面的測(cè)試用例,在執(zhí)行基礎(chǔ)測(cè)試用例過(guò)程中沒(méi)有發(fā)現(xiàn)搶購(gòu)功能的Bug,不過(guò)在進(jìn)行多地區(qū)和多語(yǔ)言的性能測(cè)試時(shí),她發(fā)現(xiàn)了一個(gè)功能上的漏洞,發(fā)現(xiàn)漏洞的過(guò)程是這樣的。
在執(zhí)行性能測(cè)試時(shí),需要選取不同國(guó)家和地區(qū)的服務(wù)器去模擬用戶(hù)的真實(shí)訪(fǎng)問(wèn),以驗(yàn)證產(chǎn)品性能是否能滿(mǎn)足用戶(hù)體驗(yàn)的要求。顯然,通過(guò)這些不同國(guó)家和地區(qū)的服務(wù)器訪(fǎng)問(wèn)網(wǎng)站,會(huì)比小蔡在公司內(nèi)部使用內(nèi)網(wǎng)訪(fǎng)問(wèn)速度慢,更別提有些國(guó)家和地區(qū)網(wǎng)絡(luò)發(fā)展慢,這些區(qū)域的訪(fǎng)問(wèn)速度就更慢了。
然而正是通過(guò)使用這些網(wǎng)速很慢的服務(wù)器,小蔡發(fā)現(xiàn)了這個(gè)功能上的漏洞。
1)在高速或者說(shuō)正常網(wǎng)速的情況下,當(dāng)用戶(hù)打開(kāi)搶購(gòu)商品的頁(yè)面時(shí),頁(yè)面JavaScript會(huì)很快加載并執(zhí)行完成,這時(shí)“加入購(gòu)物車(chē)”的按鈕會(huì)變灰,無(wú)法進(jìn)行操作(見(jiàn)圖1-5)。

圖1-5 正常網(wǎng)速,等JavaScript加載完成之后“加入購(gòu)物車(chē)”不能操作
2)而當(dāng)網(wǎng)速很慢時(shí),由于網(wǎng)頁(yè)中JavaScript是順序加載執(zhí)行的,所以“加入購(gòu)物車(chē)”按鈕先會(huì)顯示為可以操作的狀態(tài),等JavaScript加載完成后,才會(huì)變灰,不可操作(見(jiàn)圖1-6)。

圖1-6 慢速網(wǎng)絡(luò),在JavaScript加載完成之前“加入購(gòu)物車(chē)”按鈕可以操作
3)所以在慢速網(wǎng)絡(luò)中,當(dāng)頁(yè)面JavaScript沒(méi)有加載完成時(shí),用戶(hù)會(huì)看到“加入購(gòu)物車(chē)”按鈕是可用狀態(tài),因此用戶(hù)可以點(diǎn)擊該按鈕,并把搶購(gòu)商品加入購(gòu)物車(chē),于是用戶(hù)就可以在正式搶購(gòu)開(kāi)始之前順利地?fù)尩皆撋唐妨恕?shí)際上甚至在商品無(wú)貨的情況下,用戶(hù)也可以在JavaScript沒(méi)有加載完時(shí)點(diǎn)擊“加入購(gòu)物車(chē)”按鈕,并且成功把無(wú)貨商品加入購(gòu)物車(chē)(見(jiàn)圖1-7和圖1-8)。

圖1-7 慢速網(wǎng)絡(luò),無(wú)貨的商品也可以添加到購(gòu)物車(chē)

圖1-8 慢速網(wǎng)絡(luò),無(wú)貨的商品也可以支付購(gòu)買(mǎi)
這個(gè)問(wèn)題是由JavaScript沒(méi)有加載完成引起的,但是稍懂技術(shù)的人甚至可以禁用瀏覽器的JavaScript,或者通過(guò)查看網(wǎng)絡(luò)訪(fǎng)問(wèn)的URL后,在按鈕是灰色的狀態(tài)下也有可能提交購(gòu)買(mǎi)請(qǐng)求。所以,修改這個(gè)Bug時(shí),還需要在提交訂單時(shí)做二次驗(yàn)證,去驗(yàn)證該商品是否有貨,或者是否已經(jīng)處于搶購(gòu)狀態(tài),當(dāng)狀態(tài)為“是”的時(shí)候,才允許后續(xù)操作。
當(dāng)小蔡把這個(gè)問(wèn)題提交給開(kāi)發(fā)人員和產(chǎn)品經(jīng)理后,經(jīng)過(guò)大家的討論,發(fā)現(xiàn)如果調(diào)整商品頁(yè)面上的JavaScript加載順序,會(huì)涉及很多JavaScript文件的修改,影響范圍會(huì)很廣,包括移動(dòng)頁(yè)面上的代碼也需要大幅修正,因此整體工作量比較大。鑒于剛才提到的在提交訂單時(shí)做二次驗(yàn)證也能避免這樣的問(wèn)題,所以他們一致決定采取做二次驗(yàn)證這種方案來(lái)進(jìn)行修復(fù)。
拓展知識(shí):JavaScript的加載與執(zhí)行
瀏覽器的渲染線(xiàn)程和JS執(zhí)行線(xiàn)程是互斥的,并且JavaScript默認(rèn)是阻塞加載的。頁(yè)面的下載和渲染都必須停下來(lái)等待腳本執(zhí)行完成。JavaScript執(zhí)行過(guò)程耗時(shí)越久,瀏覽器等待響應(yīng)用戶(hù)輸入的時(shí)間就越長(zhǎng)。
(1)加載
不管是script標(biāo)簽直接引入的情況,還是src加載的外部資源,都會(huì)阻塞頁(yè)面的渲染。所以一般為了從體驗(yàn)上考慮,我們會(huì)將JS文件放置在body標(biāo)簽閉合之前。不過(guò)新版的IE、Firefox、Safari和Chrome都允許并行下載JavaScript文件。但是只是JavaScript文件可以并行下載,渲染還是被阻塞的,頁(yè)面仍然必須等待所有JavaScript代碼下載并執(zhí)行完成才能繼續(xù)。
(2)執(zhí)行
每當(dāng)JavaScript文件加載完成后,都會(huì)立刻執(zhí)行該文件。所以你會(huì)看到下一次的請(qǐng)求并不是在上一次請(qǐng)求結(jié)束之后立即開(kāi)始,中間的耗時(shí)就是上一個(gè)腳本文件的執(zhí)行時(shí)間。
一般對(duì)于JavaScript的優(yōu)化建議如下。
1)將script腳本文件放置在body標(biāo)簽閉合之前。
2)減少script請(qǐng)求數(shù)量。
3)無(wú)阻塞腳本,在頁(yè)面加載完成后才加載JavaScript代碼。這就意味著在window對(duì)象的onload事件觸發(fā)后再下載腳本。
▼Defer, async。
▼動(dòng)態(tài)添加script元素。
不過(guò)在上面這個(gè)故事中,正是由于對(duì)JavaScript的優(yōu)化引發(fā)了搶購(gòu)頁(yè)面先顯示元素可操作,然后在JavaScript加載完成后,JavaScript執(zhí)行使元素不可操作。
1.5 過(guò)長(zhǎng)的控件名稱(chēng)造成其他元素顯示錯(cuò)位
小蔡接到一個(gè)公司內(nèi)部在線(xiàn)表單項(xiàng)目的測(cè)試任務(wù),這個(gè)項(xiàng)目中有3個(gè)獨(dú)立的角色:管理員A負(fù)責(zé)編輯和布局表單控件,用戶(hù)B負(fù)責(zé)填寫(xiě)表單中控件的內(nèi)容,而審核員C只能查看B操作后的結(jié)果。
這個(gè)需求看上去不難,小蔡快速分析并且記錄了以下幾個(gè)測(cè)試點(diǎn),開(kāi)始了測(cè)試工作。
1)A可以正常添加不同類(lèi)型控件(文本框、富文本框、下拉列表、多選框、單選框等)到頁(yè)面中。
2)B可以正常在這些控件中輸入數(shù)據(jù)。
3)C可以正常查看B所有的操作內(nèi)容。
4)針對(duì)各個(gè)角色所具有的不同的操作權(quán)限進(jìn)行驗(yàn)證。
5)A更新表單后,B要可以看到對(duì)應(yīng)的變化。
6)A未完成操作或者未保存的表單,B是無(wú)法看到和使用的。
7)B不保存后者提交操作結(jié)果,C無(wú)法看到B的操作內(nèi)容。
8)跨瀏覽器和跨平臺(tái)測(cè)試。
在測(cè)試過(guò)程中,小蔡發(fā)現(xiàn)這個(gè)表單做的類(lèi)似于我們熟知的Office應(yīng)用的所見(jiàn)即所得的形式,即A在屏幕左上方放置一個(gè)多選框并保存后,B打開(kāi)頁(yè)面后也可以在屏幕左上方看到一個(gè)多選框,最后C登錄后也可以在屏幕左上方看到這個(gè)多選框。這使得整個(gè)功能變得更加容易測(cè)試,幾乎是瞥一眼就能看到有沒(méi)有問(wèn)題。
三下五除二就跑完用例,小蔡正準(zhǔn)備結(jié)束測(cè)試,偶然間一眼瞥到表單上的多選框選項(xiàng)上,她突然意識(shí)到既然多選框和單選框中的選項(xiàng)內(nèi)容都是自己定義的,那在選項(xiàng)內(nèi)容中輸入超長(zhǎng)字符串時(shí),會(huì)不會(huì)導(dǎo)致該控件的顯示位置發(fā)生變化呢?
帶著這個(gè)疑問(wèn),小蔡重新使用A角色設(shè)置了一個(gè)超長(zhǎng)的多選框選項(xiàng)名稱(chēng),然后用B角色做了勾選操作,最后再用C去查看結(jié)果。結(jié)果她發(fā)現(xiàn)了問(wèn)題:C查看到的結(jié)果中,勾選后的內(nèi)容和多選框顯示錯(cuò)位了。
再仔細(xì)重現(xiàn)了一遍問(wèn)題后,小蔡發(fā)現(xiàn)A在編輯模式給多選框設(shè)置超長(zhǎng)的選項(xiàng)名稱(chēng)的時(shí)候,在界面上多選框的位置被擠到了文本中央,如圖1-9所示。

圖1-9 表單編輯界面
B在操作視圖中看到的這個(gè)多選框又被強(qiáng)制對(duì)齊到了文字最左側(cè),如圖1-10所示。

圖1-10 表單操作界面
而C在審核視圖中看到的情況卻是A和C的結(jié)合體,即多選框被重置到了文字中央,而被勾選的位置卻出現(xiàn)在文字的最左端(見(jiàn)圖1-11)。

圖1-11 操作結(jié)果查看頁(yè)面
有了小蔡的過(guò)程重現(xiàn),開(kāi)發(fā)人員很快就定位到出現(xiàn)問(wèn)題的原因:首先是在A用戶(hù)使用的過(guò)程中(見(jiàn)圖1-9),沒(méi)有把操作結(jié)果查看視圖中的多選框強(qiáng)制左對(duì)齊。其次是在用戶(hù)C使用過(guò)程中(見(jiàn)圖1-11),由于使用jQuery定制化多選框中的代碼邏輯錯(cuò)誤,導(dǎo)致勾選狀態(tài)下的可勾選位置和多選框本身出現(xiàn)了分離,最終導(dǎo)致問(wèn)題出現(xiàn)。
核心知識(shí):常見(jiàn)的HTML元素及常見(jiàn)檢查點(diǎn)
1)<select>標(biāo)簽,可創(chuàng)建單選或多選菜單。
常見(jiàn)檢查點(diǎn):下拉列表數(shù)據(jù)的正確性;數(shù)據(jù)被選中是否正確,是否變形,是否只讀,多選/單選是否正確。
2)<label>標(biāo)簽,相當(dāng)于一個(gè)展示文本框。
常見(jiàn)檢查點(diǎn):文本是否正確;文本字體、大小、顏色、間距是否正確;for屬性是否綁定了正確的元素等。
3)<input>標(biāo)簽,用于收集用戶(hù)信息。
根據(jù)不同的type屬性值,輸入字段擁有很多種形式。可以是文本字段、復(fù)選框、掩碼后的文本控件、單選按鈕、按鈕等。
4)button可點(diǎn)擊的按鈕,點(diǎn)擊后通常會(huì)觸發(fā)相應(yīng)事件。
常見(jiàn)檢查點(diǎn):點(diǎn)擊按鈕后觸發(fā)的行為和期望不符合;頁(yè)面卡死未響應(yīng);點(diǎn)擊后變形等。
5)text文本輸入。
常見(jiàn)檢查點(diǎn):是否只讀;SQL注入攻擊;輸入內(nèi)容超過(guò)文本框長(zhǎng)度是否引起形變等。
6)checkbox多選框。
常見(jiàn)檢查點(diǎn):選中/取消勾選是否有效;文本長(zhǎng)度過(guò)長(zhǎng)是否引起形變;頁(yè)面刷新后是否被自動(dòng)取消/勾選等。
7)radio單選框。
常見(jiàn)檢查點(diǎn):單選是否有效;文本長(zhǎng)度過(guò)長(zhǎng)是否引起形變;頁(yè)面刷新后是否被自動(dòng)取消/勾選等。
8)image圖片區(qū)域。
常見(jiàn)檢查點(diǎn):圖片加載是否正確;圖片加載失敗或者關(guān)閉時(shí)行為是否符合預(yù)期;鼠標(biāo)指針移動(dòng)到圖片上后顯示的文本是否正確;圖片是否可以正確點(diǎn)擊/拖曳等。
9)submit提交按鈕,提交當(dāng)前<form>表單信息到指定頁(yè)面。
常見(jiàn)檢查點(diǎn):提交信息完整性等。
1.6 多次操作本該禁用的頁(yè)面組件造成服務(wù)器出錯(cuò)
對(duì)頁(yè)面上的組件進(jìn)行多次點(diǎn)擊是測(cè)試人員經(jīng)常使用的小技巧之一,通常小蔡在執(zhí)行完基本測(cè)試用例之后,開(kāi)始進(jìn)行探索性測(cè)試時(shí)會(huì)使用這個(gè)技巧,并且利用這個(gè)測(cè)試技巧發(fā)現(xiàn)了不少問(wèn)題。
這些問(wèn)題主要集中在用戶(hù)提交服務(wù)器請(qǐng)求后服務(wù)器進(jìn)行處理的相關(guān)功能上,例如讀取、保存、提交、刪除等功能(見(jiàn)圖1-12)。

圖1-12 用戶(hù)通過(guò)“刪除”“保存”等功能和服務(wù)器交互
小蔡發(fā)現(xiàn)如果網(wǎng)絡(luò)速度比較慢或者產(chǎn)品本身性能不夠好,在用戶(hù)點(diǎn)擊了這些功能按鈕后,而頁(yè)面刷新完成之前這段時(shí)間內(nèi),該功能按鈕仍然可能被用戶(hù)繼續(xù)點(diǎn)擊。即使有些頁(yè)面上的按鈕處于灰色不可用狀態(tài),但當(dāng)你嘗試點(diǎn)擊這些灰色的按鈕,會(huì)發(fā)現(xiàn)點(diǎn)擊后仍然會(huì)給服務(wù)器端發(fā)送請(qǐng)求(見(jiàn)圖1-13)。

圖1-13 功能按鈕在被置灰后仍然可以使用
這樣帶來(lái)了一系列問(wèn)題,舉例來(lái)說(shuō),對(duì)于保存功能,用戶(hù)多次點(diǎn)擊后會(huì)向后臺(tái)發(fā)送多次請(qǐng)求,數(shù)據(jù)庫(kù)中也會(huì)產(chǎn)生多條重復(fù)的數(shù)據(jù),這樣不僅會(huì)造成數(shù)據(jù)統(tǒng)計(jì)錯(cuò)誤,更會(huì)給再次使用這些數(shù)據(jù)的人或程序造成很大的麻煩。一個(gè)更極端的例子是免密碼支付的場(chǎng)景,當(dāng)用戶(hù)不小心多次點(diǎn)擊支付按鈕后,會(huì)給用戶(hù)造成不小的損失;對(duì)于刪除功能來(lái)說(shuō),多次點(diǎn)擊“刪除”按鈕后,實(shí)際上第一個(gè)請(qǐng)求已經(jīng)讓數(shù)據(jù)庫(kù)將對(duì)應(yīng)的數(shù)據(jù)刪除了,接下來(lái)的刪除請(qǐng)求可能會(huì)造成后臺(tái)程序的大量異常。
小蔡發(fā)現(xiàn)解決此類(lèi)問(wèn)題也很簡(jiǎn)單,只需要開(kāi)發(fā)人員在編寫(xiě)代碼時(shí)注意,只允許對(duì)該類(lèi)功能按鈕操作一次,在用戶(hù)操作之后,不僅需要把對(duì)應(yīng)的功能按鈕置灰,同時(shí)需要取消這些功能按鈕上面綁定的事件響應(yīng)處理機(jī)制。
通常小蔡除了會(huì)在小組的回顧會(huì)議上向開(kāi)發(fā)人員分析這些問(wèn)題產(chǎn)生的原因和避免方式,還在每張開(kāi)發(fā)故事卡上明確地標(biāo)注需要測(cè)試多次快速點(diǎn)擊按鈕的場(chǎng)景,這樣可以讓開(kāi)發(fā)人員從意識(shí)上提高對(duì)這類(lèi)缺陷的警惕,從而在編寫(xiě)代碼時(shí)注意預(yù)防此類(lèi)問(wèn)題的發(fā)生。
拓展知識(shí):回顧會(huì)議
無(wú)論一個(gè)Scrum團(tuán)隊(duì)有多出色,總有需要改進(jìn)的地方。即使一個(gè)好的Scrum團(tuán)隊(duì)會(huì)不斷尋找需要改進(jìn)的方面,這個(gè)團(tuán)隊(duì)也應(yīng)該做一個(gè)簡(jiǎn)單回顧,目的是在每個(gè)迭代的最后來(lái)回顧團(tuán)隊(duì)目前做得如何以及找到改進(jìn)的方法。
回顧會(huì)議(Sprint Retrospective)通常發(fā)生在每個(gè)迭代最后一天,用來(lái)幫助團(tuán)隊(duì)進(jìn)行自我改進(jìn)。會(huì)議長(zhǎng)度通常為1個(gè)小時(shí),團(tuán)隊(duì)成員在一起列出團(tuán)隊(duì)?wèi)?yīng)該做的事情、需要停止做的事情、應(yīng)該保持下去的事情。接著團(tuán)隊(duì)成員對(duì)所有提議進(jìn)行投票,這樣可以在有限的時(shí)間里優(yōu)先討論大家最關(guān)心的幾個(gè)問(wèn)題。通過(guò)集思廣益,提出改進(jìn)方法,在緊接著的迭代中進(jìn)行改進(jìn)。
在下個(gè)迭代的回顧會(huì)議一開(kāi)始,會(huì)首先關(guān)注上一次回顧會(huì)議的結(jié)果是否被落實(shí)。
1.7 頁(yè)面跳轉(zhuǎn)后出現(xiàn)HTTP 400錯(cuò)誤
公司網(wǎng)站又升級(jí)了!這次升級(jí)后網(wǎng)站增加了一個(gè)保險(xiǎn)報(bào)價(jià)功能:客戶(hù)先在網(wǎng)站上回答公司設(shè)計(jì)的各種問(wèn)題(單選題),系統(tǒng)會(huì)把答案匯總起來(lái),傳給后臺(tái)計(jì)算價(jià)格,然后后臺(tái)系統(tǒng)把計(jì)算出的保險(xiǎn)報(bào)價(jià)返回給網(wǎng)站并顯示在頁(yè)面上。
從功能上看,小蔡覺(jué)得這個(gè)功能需求的關(guān)鍵是網(wǎng)站上設(shè)計(jì)的每一個(gè)問(wèn)題都會(huì)作為一個(gè)價(jià)格因子并對(duì)最終報(bào)價(jià)產(chǎn)生影響。測(cè)試的重點(diǎn)應(yīng)該是檢查每個(gè)因子能夠引起的價(jià)格變化是否符合預(yù)期。另外由于每類(lèi)問(wèn)題都分布在不同的頁(yè)面上,所以需要確保在頁(yè)面切換后,系統(tǒng)能保存之前選擇的答案而不丟失。最后性能要求是在后臺(tái)系統(tǒng)返回報(bào)價(jià)的時(shí)間上,根據(jù)業(yè)務(wù)方的需求需要遵守2/5/8原則,最長(zhǎng)不能超過(guò)8秒,所以還需要增加對(duì)應(yīng)的性能測(cè)試。
設(shè)計(jì)完用例,小蔡和開(kāi)發(fā)人員一起進(jìn)行了冒煙測(cè)試,結(jié)果每個(gè)功能都符合預(yù)期。于是小蔡在正式測(cè)試階段把大部分精力都放到了驗(yàn)證各個(gè)價(jià)格因子對(duì)價(jià)格變化的影響上面。
經(jīng)過(guò)大量的反復(fù)選擇問(wèn)題答案和頁(yè)面切換操作后,小蔡像之前一樣準(zhǔn)備進(jìn)入到報(bào)價(jià)匯總頁(yè)面查看最終價(jià)格,突然發(fā)現(xiàn)頁(yè)面出現(xiàn)HTTP 400錯(cuò)誤(見(jiàn)圖1-14)!

圖1-14 HTTP 400異常
小蔡眼睛一亮,趕緊回退到上一個(gè)頁(yè)面,重新點(diǎn)擊報(bào)價(jià)匯總按鈕再次進(jìn)入報(bào)價(jià)匯總頁(yè)面,反復(fù)試了好幾次,發(fā)現(xiàn)仍然會(huì)碰到HTTP 400這個(gè)問(wèn)題。于是她關(guān)閉并重新啟動(dòng)瀏覽器,嘗試再次重現(xiàn)這個(gè)問(wèn)題,準(zhǔn)備整理下出現(xiàn)問(wèn)題的場(chǎng)景,然后報(bào)給研發(fā)人員修復(fù),結(jié)果這次卻正常進(jìn)入到報(bào)價(jià)匯總頁(yè)面。
小蔡覺(jué)得挺奇怪的,難道剛才是服務(wù)器“抽風(fēng)”才導(dǎo)致HTTP 400異常?于是她又一連操作了好幾次到匯總頁(yè)面的場(chǎng)景,結(jié)果都沒(méi)有重現(xiàn)問(wèn)題。雖然感覺(jué)很神奇,但是因?yàn)闆](méi)有能夠重現(xiàn)問(wèn)題,小蔡也只能暫時(shí)作罷,一邊想著肯定是服務(wù)器抽風(fēng)了吧,一邊繼續(xù)測(cè)試價(jià)格因子。
5分鐘以后,當(dāng)她再次準(zhǔn)備進(jìn)入到價(jià)格匯總頁(yè)面時(shí),問(wèn)題又出現(xiàn)了,再次顯示HTTP 400錯(cuò)誤頁(yè)面!看著頁(yè)面上提示的錯(cuò)誤信息,小蔡突然間有點(diǎn)兒明白了,提示信息說(shuō)HTTP Request Header長(zhǎng)度過(guò)長(zhǎng),因此問(wèn)題應(yīng)該是在HTTP Request Header上。小蔡利用瀏覽器自帶的開(kāi)發(fā)工具查看了下HTTP的請(qǐng)求頭,結(jié)果瞬間就發(fā)現(xiàn)Cookie看上去似乎比平時(shí)看到的要長(zhǎng)好多(見(jiàn)圖1-15)。

圖1-15 從瀏覽器工具中查看Cookie
小蔡懷疑是Cookie有問(wèn)題,于是就找開(kāi)發(fā)人員確認(rèn)。在給開(kāi)發(fā)人員演示了一遍這個(gè)Bug后,開(kāi)發(fā)人員終于分析出造成這一結(jié)果的直接原因是Cookie長(zhǎng)度太長(zhǎng),導(dǎo)致Request Header長(zhǎng)度超標(biāo),最后發(fā)生HTTP Error 400。而再深入一層的根本原因是開(kāi)發(fā)人員為了在切換頁(yè)面時(shí)保存前幾個(gè)頁(yè)面的答案狀態(tài),把這些狀態(tài)存到了Cookie里面,而每次翻頁(yè)的時(shí)候又把答案信息錯(cuò)誤地添加到Cookie已有信息之后,導(dǎo)致隨著小蔡翻頁(yè)操作越來(lái)越多,Cookie也越來(lái)越長(zhǎng),最后當(dāng)Cookie長(zhǎng)度超過(guò)瀏覽器限制后就產(chǎn)生了錯(cuò)誤。
知道了問(wèn)題原因,小蔡仔細(xì)回想了下整個(gè)用例設(shè)計(jì)過(guò)程,覺(jué)得這樣的問(wèn)題即使通過(guò)覆蓋各種用戶(hù)使用場(chǎng)景仍然會(huì)不好發(fā)現(xiàn)。但如果測(cè)試人員在測(cè)試之前能夠?qū)φ麄€(gè)功能的設(shè)計(jì)或者實(shí)現(xiàn)有一些了解的話(huà),就可以注意到這個(gè)點(diǎn),并且加以測(cè)試了。例如這次的Cookie超長(zhǎng)問(wèn)題,如果測(cè)試人員和開(kāi)發(fā)人員先進(jìn)行一些溝通,了解到代碼是通過(guò)把信息存儲(chǔ)到Cookie中去實(shí)現(xiàn)該功能,那么測(cè)試人員會(huì)很自然地想到Cookie長(zhǎng)度通常是有限制的,因此會(huì)對(duì)這種存儲(chǔ)信息的方式做特定的測(cè)試。
核心知識(shí):HTTP Request Header長(zhǎng)度限制
Request Header就是往服務(wù)器發(fā)送的請(qǐng)求頭,HTTP協(xié)議中并沒(méi)有限制Header的大小。理論上無(wú)論我們的Header有多大都是可以的。
但實(shí)際上各個(gè)主流瀏覽器都會(huì)對(duì)Header長(zhǎng)度進(jìn)行限制,從幾十KB到幾百M(fèi)B不等,基本上能滿(mǎn)足平時(shí)的需求。此外,在服務(wù)端也可以對(duì)Heder長(zhǎng)度做限制。比如Nginx就可以限制Header的長(zhǎng)度。
HTTP Header如果不限制大小會(huì)有什么影響?
如果某個(gè)網(wǎng)站的服務(wù)器是不限制Header大小的,那么它就有可能被黑客利用實(shí)施攻擊,比如DDoS。黑客可以利用這一點(diǎn),發(fā)送一個(gè)非常大(比如幾MB)的請(qǐng)求,會(huì)占用服務(wù)器一個(gè)進(jìn)程來(lái)專(zhuān)門(mén)處理這個(gè)請(qǐng)求。此類(lèi)請(qǐng)求數(shù)量過(guò)多時(shí),服務(wù)器就無(wú)法提供其他對(duì)外服務(wù)。
1.8 使用沒(méi)有添加時(shí)間戳的緩存使用戶(hù)看到過(guò)期數(shù)據(jù)
當(dāng)代主流的網(wǎng)站都使用了緩存技術(shù),目的在于減少用戶(hù)請(qǐng)求對(duì)服務(wù)器的壓力。當(dāng)用戶(hù)首次通過(guò)瀏覽器請(qǐng)求服務(wù)器的資源時(shí),服務(wù)器會(huì)返回所有的資源;當(dāng)用戶(hù)再次請(qǐng)求服務(wù)器資源時(shí),瀏覽器會(huì)判斷資源是否已更新,如果更新了,再向服務(wù)器發(fā)起請(qǐng)求,如果沒(méi)有更新,就使用瀏覽器中緩存的資源。
這里有一個(gè)問(wèn)題,瀏覽器是如何判斷資源是否更新了?一般來(lái)說(shuō),資源文件在文件名中要么添加時(shí)間戳(見(jiàn)圖1-16),要么添加標(biāo)識(shí)符(標(biāo)識(shí)符可以是任何一組區(qū)別資源不同版本的數(shù)值,如v1、v2,或者GUID等)來(lái)唯一區(qū)分資源的不同版本(見(jiàn)圖1-17)。只要本地緩存的資源文件和服務(wù)器端最新的資源文件名稱(chēng)不一樣,瀏覽器就要從服務(wù)器端獲取新的資源文件,如果一樣,就使用本地緩存的資源。

圖1-16 帶有時(shí)間戳的資源文件

圖1-17 帶有標(biāo)識(shí)符的資源文件
如果資源文件沒(méi)有被添加時(shí)間戳或者標(biāo)識(shí)符呢?那用戶(hù)只能通過(guò)手動(dòng)清除瀏覽器的緩存來(lái)強(qiáng)制獲取最新的資源文件了,不過(guò)這樣等于所有用戶(hù)請(qǐng)求的文件都沒(méi)有從瀏覽器緩存中讀取,也就沒(méi)有為服務(wù)器緩解訪(fǎng)問(wèn)壓力。并且絕大多數(shù)用戶(hù)并不會(huì)去手動(dòng)清除瀏覽器的緩存,這就導(dǎo)致用戶(hù)看到網(wǎng)頁(yè)的資源文件不是最新的。
最近小蔡測(cè)試的商品詳細(xì)信息頁(yè)面出現(xiàn)的Bug就屬于這種情況。根據(jù)用戶(hù)線(xiàn)上反饋,當(dāng)用戶(hù)修改了商品圖片并且發(fā)布之后,不能及時(shí)看到更新后的圖片,而是需要等一段不確定的時(shí)間才能看到更新后的圖片。
經(jīng)過(guò)小蔡和開(kāi)發(fā)人員的調(diào)查,發(fā)現(xiàn)導(dǎo)致這個(gè)問(wèn)題的原因是緩存資源文件沒(méi)有被設(shè)置時(shí)間戳或者標(biāo)識(shí)符,導(dǎo)致用戶(hù)修改后不能看到更新后的圖片。而之所以會(huì)造成不確定時(shí)間后才能看到更新后的圖片,是由于不同瀏覽器對(duì)于沒(méi)有設(shè)置時(shí)間戳或者標(biāo)識(shí)符的緩存資源文件處理不一致造成的。
例如IE緩存時(shí)間就是一個(gè)Session的時(shí)間,如果用戶(hù)打開(kāi)一個(gè)新的IE窗口時(shí),他們就會(huì)獲取最新的靜態(tài)資源;而其他瀏覽器(例如Firefox),則會(huì)通過(guò)HTTP頭文件中Last-Modified參數(shù)的具體定義來(lái)判斷是否需要去重新獲取資源。
而小蔡在之前的測(cè)試中,為了避免緩存數(shù)據(jù)對(duì)測(cè)試結(jié)果的影響,她在瀏覽器中設(shè)置了每次退出瀏覽器時(shí)清空緩存(見(jiàn)圖1-18),這反而導(dǎo)致小蔡漏測(cè)了緩存沒(méi)有及時(shí)刷新的問(wèn)題。

圖1-18 退出IE時(shí)自動(dòng)刪除緩存
由于緩存在Web產(chǎn)品中是普遍存在的,所以小蔡立刻取消了瀏覽器中清除緩存的設(shè)置,改為使用手工清除緩存的方式。當(dāng)她之后在測(cè)試中遇到測(cè)試結(jié)果和預(yù)期結(jié)果不同,并且有可能是緩存未清除造成的情況時(shí),她會(huì)手動(dòng)清除緩存,這樣可以更準(zhǔn)確地進(jìn)行測(cè)試。
核心知識(shí):Web緩存
瀏覽器本身有緩存機(jī)制,比較常見(jiàn)的是瀏覽器會(huì)緩存訪(fǎng)問(wèn)過(guò)的網(wǎng)頁(yè),當(dāng)再次訪(fǎng)問(wèn)這個(gè)URL地址的時(shí)候,如果網(wǎng)頁(yè)沒(méi)有更新,就不會(huì)再次下載網(wǎng)頁(yè),而是直接使用本地緩存中的網(wǎng)頁(yè)。只有當(dāng)網(wǎng)站明確標(biāo)識(shí)資源已經(jīng)更新,瀏覽器才會(huì)再次下載網(wǎng)頁(yè)。
使用Web緩存可以減少網(wǎng)絡(luò)帶寬消耗、降低服務(wù)器壓力、減少網(wǎng)絡(luò)延遲,加快頁(yè)面打開(kāi)速度。同時(shí)我們也可以使用代理服務(wù)器,在代理過(guò)程中做緩存處理,也可以使用CDN網(wǎng)絡(luò)提供的緩存能力。
除了上述提到的軟件之外的緩存方式,服務(wù)器端軟件內(nèi)部也經(jīng)常使用各種緩存,例如使用數(shù)據(jù)庫(kù)進(jìn)行緩存,或者使用內(nèi)存進(jìn)行緩存,也可以提高用戶(hù)訪(fǎng)問(wèn)網(wǎng)頁(yè)的速度。
1.9 代理服務(wù)器過(guò)度緩存文件導(dǎo)致讀取錯(cuò)誤的賬號(hào)信息
緩存不僅僅是Web產(chǎn)品為了緩解用戶(hù)訪(fǎng)問(wèn)帶給服務(wù)器的壓力而設(shè)置的,而且用戶(hù)(例如企業(yè))為了減少多用戶(hù)訪(fǎng)問(wèn)同一個(gè)網(wǎng)站占用過(guò)多帶寬,也可以設(shè)置自己內(nèi)部的緩存服務(wù)器。
小蔡的公司就為大家設(shè)置了這樣一組緩存服務(wù)器。這些緩存服務(wù)器的原理和瀏覽器的緩存原理類(lèi)似,當(dāng)大家訪(fǎng)問(wèn)網(wǎng)頁(yè)時(shí),首先請(qǐng)求的是這些服務(wù)器上的資源,如果沒(méi)有命中,也就是說(shuō)這些資源不在公司內(nèi)部的緩存服務(wù)器上,這些服務(wù)器才向公司外部真實(shí)的服務(wù)器發(fā)送請(qǐng)求,等請(qǐng)求返回后,緩存服務(wù)器還需要把這些資源保存在本地,以便于其他用戶(hù)對(duì)同一網(wǎng)頁(yè)的再次訪(fǎng)問(wèn),然后才把這些資源發(fā)送回最開(kāi)始發(fā)送請(qǐng)求的用戶(hù)(見(jiàn)圖1-19)。

圖1-19 企業(yè)內(nèi)部緩存服務(wù)器
當(dāng)然我們這里只是簡(jiǎn)單地介紹一下內(nèi)部緩存服務(wù)器進(jìn)行緩存的過(guò)程,很多例如緩存如何過(guò)期這些細(xì)節(jié)在這里就不詳述了。
小蔡在測(cè)試網(wǎng)站的過(guò)程中,發(fā)現(xiàn)自己登錄測(cè)試賬號(hào)后,首先會(huì)看到其他測(cè)試賬號(hào)信息(而且這個(gè)賬號(hào)不固定),如果這時(shí)候進(jìn)行任何操作,很有可能出現(xiàn)錯(cuò)誤頁(yè)面,尤其是與賬戶(hù)信息相關(guān)的操作,所以小蔡只有強(qiáng)制刷新或者退出后,再次登錄才能看到剛才登錄的賬號(hào)信息,并且正常地進(jìn)行測(cè)試。這個(gè)問(wèn)題在早上一般不會(huì)發(fā)生,而其他時(shí)間出現(xiàn)的頻率就要高很多。
發(fā)生幾次之后,小蔡覺(jué)得很好奇,就詢(xún)問(wèn)了其他的測(cè)試人員,發(fā)現(xiàn)大家都有同樣的問(wèn)題,在和老牛一起分析后,他們覺(jué)得有可能是公司內(nèi)部緩存服務(wù)器機(jī)制導(dǎo)致了這個(gè)問(wèn)題,但是至于為什么早上這個(gè)問(wèn)題不容易發(fā)生,還是不太了解。
帶著這個(gè)問(wèn)題還有他們的懷疑,小蔡和老牛找到了公司信息維護(hù)的相關(guān)人員。經(jīng)確認(rèn),確實(shí)是他們緩存了測(cè)試服務(wù)器的資源,而且還緩存了登錄用戶(hù)的Cookie文件。
所以當(dāng)測(cè)試人員訪(fǎng)問(wèn)測(cè)試服務(wù)器時(shí),緩存服務(wù)器將輸入的用戶(hù)名和密碼以及Cookie文件一起發(fā)送給了測(cè)試服務(wù)器。雖然服務(wù)器接收了新的登錄用戶(hù)名和密碼,但是顯示卻使用的是Cookie里面的信息。所以,在進(jìn)行賬戶(hù)相關(guān)操作時(shí),服務(wù)器并不知道應(yīng)該對(duì)哪個(gè)賬號(hào)進(jìn)行操作,于是出現(xiàn)了錯(cuò)誤頁(yè)面。
那為什么早上這個(gè)問(wèn)題出現(xiàn)的幾率會(huì)小很多呢?根據(jù)小蔡他們的猜測(cè),很可能是因?yàn)樵缟险介_(kāi)始執(zhí)行測(cè)試的人員比較少,時(shí)間間隔長(zhǎng),導(dǎo)致Cookie文件雖然被發(fā)送,但是過(guò)期了,所以服務(wù)器很少會(huì)出現(xiàn)錯(cuò)誤頁(yè)面。
最后,經(jīng)過(guò)公司信息維護(hù)的相關(guān)人員的重新配置,取消了對(duì)登錄用戶(hù)Cookie文件的緩存,小蔡他們?cè)僖矝](méi)有遇到這個(gè)賬號(hào)顯示錯(cuò)亂的問(wèn)題。
拓展知識(shí):Session和Cookie
由于HTTP是一個(gè)無(wú)狀態(tài)協(xié)議,客戶(hù)端每次發(fā)出請(qǐng)求時(shí),本次請(qǐng)求無(wú)法得知上一次請(qǐng)求的狀態(tài)信息。在常見(jiàn)的網(wǎng)站中,服務(wù)端需要在多次HTTP請(qǐng)求間共享數(shù)據(jù),例如用戶(hù)在購(gòu)物網(wǎng)站登錄后,跳轉(zhuǎn)到商品頁(yè)面,這時(shí)候服務(wù)器端需要知道該用戶(hù)是否已經(jīng)登錄過(guò)。在技術(shù)上可以使用Session和Cookie去做這件事情。
簡(jiǎn)單來(lái)說(shuō),Session是在服務(wù)端保存的數(shù)據(jù),Cookie是在客戶(hù)端瀏覽器中保存的數(shù)據(jù),它們一起合作,來(lái)實(shí)現(xiàn)跨HTTP請(qǐng)求的數(shù)據(jù)共享。例如,當(dāng)服務(wù)器第一次創(chuàng)建Session時(shí),在內(nèi)存中記錄了用戶(hù)的信息,同時(shí)會(huì)在HTTP協(xié)議中告訴客戶(hù)端,需要在Cookie里面記錄一個(gè)Session ID,以后每次請(qǐng)求都會(huì)把這個(gè)Session ID發(fā)送到服務(wù)器,服務(wù)器就可以知道這個(gè)用戶(hù)是誰(shuí)了,從而能從服務(wù)器端查詢(xún)出此用戶(hù)的各種相關(guān)信息。
1.10 多余的空格造成服務(wù)器被刪除
在敏捷測(cè)試中,測(cè)試工作不僅包括設(shè)計(jì)和執(zhí)行測(cè)試用例、編寫(xiě)測(cè)試報(bào)告,以及測(cè)試計(jì)劃和策略的制定,還有測(cè)試部署腳本等工作。這次小蔡在執(zhí)行部署腳本的測(cè)試過(guò)程中發(fā)現(xiàn)了一個(gè)嚴(yán)重的問(wèn)題,這個(gè)Bug會(huì)導(dǎo)致整個(gè)測(cè)試服務(wù)器被刪除,事情的緣由是這樣的。
小蔡根據(jù)開(kāi)發(fā)人員提交的部署腳本和執(zhí)行步驟,一步步在測(cè)試環(huán)境中進(jìn)行部署,同時(shí)去驗(yàn)證部署腳本中是否有遺漏和錯(cuò)誤。當(dāng)執(zhí)行完部署腳本中刪除臨時(shí)文件的步驟后,小蔡發(fā)現(xiàn)后續(xù)步驟都不能執(zhí)行了!經(jīng)過(guò)調(diào)查發(fā)現(xiàn)原因是測(cè)試服務(wù)器已經(jīng)被格式化了。
雖然測(cè)試服務(wù)器都是虛擬化的,可以很快在測(cè)試環(huán)境重新建立一臺(tái)測(cè)試服務(wù)器,但是,如果這個(gè)Bug出現(xiàn)在生產(chǎn)環(huán)境,那將會(huì)是非常大的災(zāi)難!
小蔡找到了剛才執(zhí)行過(guò)程中出現(xiàn)問(wèn)題的語(yǔ)句,是“rm -rf / tmp”。她仔細(xì)檢查了整個(gè)語(yǔ)句,發(fā)現(xiàn)測(cè)試服務(wù)器被格式化的原因是在tmp前面多了一個(gè)空格,這個(gè)空格不仔細(xì)看還看不出來(lái)(業(yè)內(nèi)也有同樣的知名例子:Bumblebee誤刪用戶(hù)文件夾,如圖1-20所示,在最后一行的/usr /lib…語(yǔ)句中在usr后就被多寫(xiě)了一個(gè)空格)。

圖1-20 Bumblebee誤刪用戶(hù)文件夾
不過(guò)在Linux系統(tǒng)中,即使輸入了災(zāi)難性的操作語(yǔ)句,但如果沒(méi)有管理員的權(quán)限也是無(wú)法執(zhí)行的,因?yàn)樵趫?zhí)行這條語(yǔ)句的時(shí)候,只會(huì)出現(xiàn)權(quán)限不足,無(wú)法操作的提示,不會(huì)把服務(wù)器整個(gè)刪除。如圖1-21所示,執(zhí)行刪除語(yǔ)句的用戶(hù)由于沒(méi)有管理員權(quán)限而被拒絕執(zhí)行了。

圖1-21 刪除文件需要相應(yīng)的權(quán)限
所以小蔡下一步需要在腳本中找出是哪里賦予了管理員權(quán)限,導(dǎo)致后來(lái)刪除語(yǔ)句被允許執(zhí)行的。再仔細(xì)查找之前的部署腳本,果然不出所料,之前有一個(gè)操作步驟需要用管理員權(quán)限來(lái)復(fù)制幾個(gè)不同的文件到管理員文件夾。通常做此類(lèi)操作時(shí),會(huì)只針對(duì)這條語(yǔ)句賦予權(quán)限,例如使用sudo命令的這條語(yǔ)句:“sudo cp xxx.zip /var/xxx/xxx/”,但開(kāi)發(fā)人員在這里為了簡(jiǎn)化腳本的書(shū)寫(xiě),把每一句最開(kāi)始的sudo轉(zhuǎn)換成單獨(dú)的一條“su-root”,這種改變?cè)斐芍髨?zhí)行的所有語(yǔ)句都被賦予管理員權(quán)限進(jìn)行執(zhí)行,最終導(dǎo)致格式化測(cè)試服務(wù)器的命令也被執(zhí)行了。
小蔡把這一發(fā)現(xiàn)告訴了開(kāi)發(fā)人員后,開(kāi)發(fā)人員修改了兩處代碼:一是刪除“su-root”命令,改為針對(duì)每次執(zhí)行需要特定權(quán)限的語(yǔ)句時(shí)單獨(dú)添加sudo的方式,確保腳本執(zhí)行的權(quán)限是正確的;第二是刪除了導(dǎo)致測(cè)試服務(wù)器被格式化的那個(gè)空格。
核心知識(shí)①:sudo和su
sudo用于類(lèi)UNIX操作系統(tǒng)(如BSD)、Mac OS X,以及GNU/Linux,以允許用戶(hù)通過(guò)安全的方式使用特殊的權(quán)限去運(yùn)行程序,例如使用系統(tǒng)的超級(jí)用戶(hù)權(quán)限去運(yùn)行程序。
su命令可以讓操作者在虛擬控制臺(tái)切換當(dāng)前用戶(hù)賬戶(hù),使用su的缺點(diǎn)之一是必須要先獲取超級(jí)用戶(hù)的密碼。
核心知識(shí)②:Linux文件權(quán)限
Linux系統(tǒng)中的文件和目錄通過(guò)使用訪(fǎng)問(wèn)許可權(quán)限,來(lái)確定誰(shuí)能通過(guò)何種方式進(jìn)行訪(fǎng)問(wèn)與操作。文件或目錄的訪(fǎng)問(wèn)權(quán)限分為只讀、只寫(xiě)和可執(zhí)行3種。
確定了文件的訪(fǎng)問(wèn)權(quán)限后,用戶(hù)能使用Linux系統(tǒng)自帶的chmod命令來(lái)重新設(shè)定訪(fǎng)問(wèn)權(quán)限,也能利用chown命令來(lái)更改文件或目錄的所有者,或者使用chgrp命令來(lái)更改文件或目錄的用戶(hù)組。
拓展知識(shí):虛擬化
在計(jì)算機(jī)技術(shù)中,虛擬化(virtualization)是一種資源管理技術(shù),將計(jì)算機(jī)的各種實(shí)體資源,如服務(wù)器、網(wǎng)絡(luò)、內(nèi)存及存儲(chǔ)等,予以抽象、轉(zhuǎn)換后呈現(xiàn)出來(lái),供多個(gè)用戶(hù)共享使用。
1.11 IE 9不支持占位符導(dǎo)致搜索行為異常
對(duì)于瀏覽器兼容性測(cè)試,一直都是Web測(cè)試中重要的一環(huán),小蔡在測(cè)試產(chǎn)品中自然也不能漏掉。
由于小蔡測(cè)試的產(chǎn)品是面向普通用戶(hù)的,所以小蔡選擇進(jìn)行測(cè)試的瀏覽器,也是開(kāi)發(fā)團(tuán)隊(duì)選擇優(yōu)先支持的瀏覽器,是基于市場(chǎng)占有率最高的幾款瀏覽器:Chrome、Firefox、Safari和IE。這些瀏覽器的版本也很多,如果全部支持也是不可能的,所以開(kāi)發(fā)團(tuán)隊(duì)選擇支持最新版本的Chrome、Firefox和Safari,以及IE 9~I(xiàn)E 11,還有IE EDGE。
Chrome和Safari都是基于WebKit核心的,所以差別不大。Firefox雖然基于Gecko,但是對(duì)于絕大多數(shù)Web標(biāo)準(zhǔn)協(xié)議都是支持的,所以和Chrome及Safari的差別也很小。IE因?yàn)槭褂玫氖俏④涀约旱膬?nèi)核,所以和其他瀏覽器的差別會(huì)大不少,尤其是版本較早的IE 9~I(xiàn)E 11,不過(guò)微軟在IE EDGE上已經(jīng)開(kāi)始兼容WebKit,并且兼容最新的Web標(biāo)準(zhǔn)協(xié)議,所以和其他瀏覽器的差別也不大了。
小蔡根據(jù)搜集到的這些瀏覽器差異的信息,決定兼容性測(cè)試的重點(diǎn)放在測(cè)試Chrome和IE 9兩個(gè)瀏覽器上面。
由于產(chǎn)品是大型購(gòu)物網(wǎng)站,所以用戶(hù)需要使用搜索特定商品來(lái)查看商品詳細(xì)信息。而在搜索框中,業(yè)務(wù)方希望推廣一些暢銷(xiāo)產(chǎn)品,所以使用了占位符(Placeholder)的方式,使用戶(hù)在點(diǎn)擊搜索框之前,在搜索框的搜索關(guān)鍵字部分,看到的是通過(guò)占位符設(shè)置的推廣產(chǎn)品的信息。
小蔡在執(zhí)行瀏覽器兼容性測(cè)試時(shí)發(fā)現(xiàn),由于添加了占位符,導(dǎo)致Chrome和IE 9瀏覽器上搜索功能的行為不一致(見(jiàn)圖1-22)。

圖1-22 IE 9的占位符會(huì)被當(dāng)作搜索關(guān)鍵字
▼在Chrome上當(dāng)用戶(hù)點(diǎn)擊搜索框時(shí),占位符會(huì)消失,用戶(hù)輸入的字符會(huì)被當(dāng)作搜索關(guān)鍵字進(jìn)行搜索。
▼在IE 9上當(dāng)用戶(hù)點(diǎn)擊搜索框時(shí),占位符并不會(huì)消失,用戶(hù)輸入的字符以及占位符的內(nèi)容會(huì)一起被當(dāng)作搜索關(guān)鍵字進(jìn)行搜索。
這就導(dǎo)致用戶(hù)在兩個(gè)瀏覽器上使用相同的操作步驟進(jìn)行搜索時(shí)的搜索結(jié)果不一致。想要解決這個(gè)問(wèn)題,用戶(hù)只有一個(gè)一個(gè)字符地刪除IE 9瀏覽器中搜索框里的占位符,這對(duì)用戶(hù)來(lái)說(shuō)并不友好。
經(jīng)過(guò)開(kāi)發(fā)人員調(diào)查發(fā)現(xiàn),這個(gè)問(wèn)題的原因是IE 9瀏覽器本身就不支持占位符,所以對(duì)于占位符的操作也是有問(wèn)題的。開(kāi)發(fā)人員只好對(duì)IE 9上的搜索框單獨(dú)處理,給搜索框先添加一組灰色的默認(rèn)文字,來(lái)展示暢銷(xiāo)商品,等用戶(hù)點(diǎn)擊搜索框時(shí)再清除這些字符。
小蔡慶幸IE 9是支持的最低版本的IE,如果需要再兼容IE 6~I(xiàn)E 8,那瀏覽器之間的差異更多更復(fù)雜,也會(huì)讓開(kāi)發(fā)和測(cè)試工作的難度加大不少。同時(shí)她決定定期查看用戶(hù)的瀏覽器使用率和使用量,等大量用戶(hù)不再使用IE 9時(shí),就可以不用再做現(xiàn)在這種針對(duì)特定瀏覽器編寫(xiě)代碼和測(cè)試某項(xiàng)功能了。
拓展知識(shí):瀏覽器內(nèi)核
排版引擎負(fù)責(zé)解析標(biāo)記式內(nèi)容(如HTML、XML、CSS、XSL及圖像文件等),并將排版后的內(nèi)容輸出至顯示器或打印機(jī)。Chromium/Chrome(iOS版除外)與Opera使用的瀏覽器引擎是基于Blink,是WebKit的一個(gè)分支,F(xiàn)irefox網(wǎng)頁(yè)瀏覽器使用了Gecko網(wǎng)頁(yè)瀏覽器引擎,Internet Explorer使用的是Trident網(wǎng)頁(yè)瀏覽器引擎。
1.12 小結(jié)
本章我們介紹了由特定技術(shù)引起的功能測(cè)試問(wèn)題,下一章我們會(huì)接觸到由于測(cè)試覆蓋導(dǎo)致的問(wèn)題。
- 零基礎(chǔ)玩轉(zhuǎn)區(qū)塊鏈
- 樂(lè)高機(jī)器人設(shè)計(jì)技巧:EV3結(jié)構(gòu)設(shè)計(jì)與編程指導(dǎo)
- AngularJS深度剖析與最佳實(shí)踐
- Hands-On Reinforcement Learning with Python
- Keras深度學(xué)習(xí)實(shí)戰(zhàn)
- Yii Project Blueprints
- 微服務(wù)架構(gòu)深度解析:原理、實(shí)踐與進(jìn)階
- LabVIEW虛擬儀器入門(mén)與測(cè)控應(yīng)用100例
- 遠(yuǎn)方:兩位持續(xù)創(chuàng)業(yè)者的點(diǎn)滴思考
- 多媒體技術(shù)及應(yīng)用
- 從零開(kāi)始構(gòu)建深度前饋神經(jīng)網(wǎng)絡(luò):Python+TensorFlow 2.x
- Getting Started with Web Components
- 零基礎(chǔ)學(xué)Java(第5版)
- JavaScript編程精解(原書(shū)第3版)
- VMware vRealize Orchestrator Essentials