qileilove

          blog已經轉移至github,大家請訪問 http://qaseven.github.io/

          自動化測試最佳實踐 連載三

           第1章 敏捷團隊的自動化測試之旅:第一年

            Lisa Crispin

            瀏覽“如何閱讀本書”和“案例研究反思”,了解本書章節安排。

            Lisa Crispin以其特有的迷人方式描述了當一個敏捷團隊決定實施自動化測試時所發生的事情。由于Lisa在敏捷技術方面的專業能力,當看到這支團隊在實踐中確實非常敏捷時,我們一點兒也沒有感到驚訝。這個項目中一件有趣的事情就是:團隊(小型團隊)里面的每個人都參與了自動化。他們不僅擅長敏捷開發,而且非常敏捷地對其進行了自動化——并且他們成功了。實施敏捷開發并不是這支團隊取得成功的唯一要素,其他要素也同等重要,其中包括通過良好的溝通建立穩固的管理關系,以及建立自動化平臺來支持創造性的手動測試。另一個關鍵要素是在團隊將過程改進嵌入到整個流程的決策力,包括一年兩次的自動化重構的安排。毫無疑問,Lisa和她的團隊在他們第一年的時間里所取得的成就是非常顯著的。這個項目是為一家美國公司的財務部完成的,特征見表1-1。

            表1-1 案例研究特征

            (續)

            1.1 本案例研究的背景

            我們必須面對這樣的事實:對于從未進行過自動化測試的人來說,自動化測試是具有一定難度的。本故事告訴我們,面對無任何自動化的測試和有著糟糕設計的遺留系統,這支團隊通過一年多的努力,將所有的回歸測試都實現了自動化。在接下來的幾年時間里,我也與數十個其他面臨同樣困境并找到類似解決方案的團隊進行了交談。看看我們所遇到的這些困難是否與你所遇到的相似,并考慮用類似的方法進行嘗試。

            1.1.1 問題

            從這里開始著手:每兩周我們都需要把新的功能添加到產品中,但是代碼bug成災并且也沒有自動化測試,更嚴重的是,產品中有大量隨時會導致系統中斷的bug。我們如何擺脫這種情況呢?

          1.1.2 目標

            我們決心盡自己所能編寫出最高質量的代碼,但是從哪里開始呢?作為一支自組織的敏捷開發團隊,讓我們感到欣慰的是整個團隊的緊密協作。那是在2003年,我們中有些人在別的團隊中曾有過良好的自動化測試經驗,他們相信總是會有辦法的。我們發現,一個安全的自動化回歸測試網絡可以讓我們更快速地工作。如果我們知道是由于某段特殊的代碼而引入的非預期的操作,那么我們能夠立即穩定我們的代碼庫。通過充分的測試覆蓋來不斷進行集成,使我們每天都有一個穩定的構建過程。而在迭代的后期,現在很難得到穩定的集成,所以這個想法雖然并非那么容易實現,但聽起來很不錯!

            接下來,看看到底是什么幫助我們創建了一個成功的策略來實現自動化回歸測試套件。

            1.2 整個團隊的承諾

            我們是由多個程序員、一個測試人員、一個數據庫管理人員、一個系統管理人員和一個敏捷教練所組成的團隊。公司的業務專家可以隨時協助我們。我們整個團隊致力于在每次發布之前運行我們的手動回歸測試腳本。因為我們每兩周發布一次,這意味著兩周的迭代周期中我們要花1 ~ 2天的時間進行手動測試。在最終用戶使用之前,我們沒有足夠的時間來進行探索性測試,雖然這種測試可能會幫助我們找到嚴重的缺陷。

            【真知灼見】

            敏捷開發團隊中的每個人都進行手動測試,所以他們更能體會到自動化測試的好處。

            我們都很關心質量,并且我們都致力于保證所有的測試活動都是有計劃的且在每一次迭代中執行。這是一個好的開始!

            1.3 建立自動化策略

            我們需要在不破壞現有功能的前提下發布產品的新功能特性。而且,需要盡快知道一個新的代碼變動是否會引起回歸測試的失敗。手動回歸測試在每兩周的迭代后期才能給予我們反饋,以至于沒有時間進行充分的回歸測試。

            我們中一些人曾經在其他敏捷團隊中進行過測試驅動開發(Test-Driven Development, TDD)。我們發現TDD能幫助創建出設計良好的、健壯的代碼。

            我們現有的回歸測試是手動操作的,整個團隊通過使用團隊Wiki上所記錄的腳本進行手動測試。在每兩周的迭代周期中,這就花費了整個團隊的20%的時間。這些測試僅僅為程序最核心的部分提供了最小程度的覆蓋。產品中報告的缺陷表明,回歸測試的失敗仍有可能發生。在每次迭代周期中,我們至少要花20%的時間修復這些產品缺陷,從而限制了我們能開發的新功能的數量。

            自動化的回歸測試會帶來更高、更準確的覆蓋率,這需要投入大量的時間、金錢和精力,我們可能需要硬件和軟件來建立構建過程、持續運行測試所需要的環境,我們也需要使測試實現自動化的架構和驅動。然而,我們可以計算出這一自動化將會節省我們40%的時間,利用這些時間可以進行更多有價值的活動,比如進行新的開發,所以,其收益遠大于成本。

            繼續進行手動回歸測試必將會失敗,我們需要一個明確的決策來進行自動化。因為我們都在進行手動回歸測試,每個人都感受到了沒有自動化測試的痛苦。所以,我們有了解決這一問題的動力。首先,我們需要一個可測試的架構……

            1.3.1 一個可測試的架構

            TDD這條路是要走的,但是當前的代碼在業務邏輯、數據庫訪問和UI等處相結合時,情況比較復雜,自動化單元測試也就變得很難了。往往很難隔離任何一個組件單獨進行測試。

            這樣看來,似乎找到一種把軟件進行分層的新架構是非常明智的。我們開發出了這一新架構的所有新功能。

            【小竅門】

            不要嘗試解決老問題,進行新的開發來開展更好的實踐。

            如果進行自動化測試的成本比其收益高,那么進行自動化測試就沒什么意義。我們研究圖1-1所示的自動化測試金字塔(這一金字塔是由我們當時的經理Mike Cohn提出的)。單元級別的測試一般ROI最高。程序員可以很快寫出它們并運行,而且測試可以根據需要進行更新。因此可以將單元級別的測試作為自動化回歸測試的堅實基礎。

           我們的業務邏輯相當復雜,而且新架構將這一邏輯從數據庫和用戶接口層中分離出來,這樣就可以通過設置內存中數據并在其上運行產品代碼來進行測試。這是金字塔的中間層———比底層運行的測試要少但是依然很重要。

            我們還需要測試UI,但是通過UI進行的自動化測試本身就非常脆弱、維護費用高且運行緩慢。因為最終想使UI測試所占的比例盡量最小,所以它就處在金字塔的最頂端。盡管如此,與其他團隊一樣,我們從圖形用戶界面(GUI)冒煙測試(smoke test)開始,來獲取一些代碼防護。所以,從這個角度,我們的金字塔是上下顛倒的,但是沒關系———最終我們會將它翻轉過來。(我們最終花了4年時間才獲得為之努力的三角形形狀!)

          圖1-1 自動化測試金字塔

            【小竅門】

            解決問題的最直接途徑未必是最佳途徑。

            我們現在明白了我們需要做什么,所以我們開始著手實施那個能給我們帶來最大實惠的任務。

            1.3.2 建立構建過程

            我們只有4位程序員,但是他們會經常檢查源代碼控制系統中的變化。我們需要確保他們沒有不小心修改別人的內容或者破壞現有的任何功能。同時,我(測試人員)有時候不得不等待好幾天,部署在測試環境中的代碼才能完成一次構建。一個自動化的構建過程(build process)將保證在每次檢入后的幾分鐘內,最新代碼的可部署版本就是可用的。

            管理層向我們強調了質量是我們的第一目標,他們樂意寬限一些時間來讓我們搭建一個好的基礎結構。

            【真知灼見】

            好的管理者會準許團隊花時間去開發自動化的基礎結構。

            我們停下正在做的事情,使用CruiseControl和一個新的Linux服務器建立了一個持續集成(Continuous Integration, CI)過程。因為我們還沒有可以運行的任何測試實例,所以只是簡單編譯代碼和構建可部署的二進制文件。我可以看到每次構建的檢入文件并能夠選擇想部署到產品中的二進制文件。這很有用,但是還不夠。

            1.3.3 獲取測試的基準:GUI冒煙測試

            程序員正在學習如何使單元測試自動化并編寫測試先行(test-first)的代碼,但是要真正實施測試驅動開發需要花好幾個月的時間。針對遺留代碼,使用GUI冒煙測試可能是一個快速獲得自動化測試覆蓋的途徑。但是使用什么工具最好呢?

            我們有購買一個付費工具的預算資金,但是團隊里的程序員是Java程序員,他們萬不得已是不愿意使用另一種腳本語言來進行測試的。捕獲/回放并不適合我們,因為我們需要可維護的、穩定的測試腳本。我們選中了 Cannoo WebTest——一個可以讓我們修改XML文件中的測試用例,并使用Ant運行它們的開源框架。而且它很容易與我們的構建過程集成。

          【真知灼見】

            昂貴的商業工具不一定是最好的選擇。

            我讓業務專家把需要用冒煙測試來保護的系統核心區域按優先等級進行劃分。每個沖刺時間段里,都安排了時間讓我用WebTest工具自動運行測試腳本。我們首先追求的是“快贏”,針對系統中每個用戶角色的基本功能實現自動測試。

            首先, CI構建過程只運行了少量單元測試和一些覆蓋系統高得分點的GUI冒煙測試。隨著在這兩個級別引入更多測試,我們將GUI測試移到單獨的構建過程中并只在晚上運行,這樣,我們可以更快得到的反饋信息。

            與此同時,我們將單元測試和每個新用戶故事(user story)的GUI冒煙測試都放在迭代中完成。新的功能將會在自動化的單元測試和GUI測試中被覆蓋。一旦程序員能夠熟練使用TDD,我們就將進入金字塔的中間層。

            1.3.4 在單元級別驅動開發

            我們的程序員中只有一人曾經實施過TDD,但每個人都支持這種理念。我們根據別人的介紹,找到了我們能找到的最好的顧問來幫助我們學習如何實施TDD,很多時候我們都是自帶午餐以便擠出時間來進行TDD試驗。但是很遺憾的是:它很難學!我們團隊需要時間來掌握它。

            我們的管理層知道這個道理:目標是寫出優美的代碼,優美到可以拿回家給媽媽,當做冰箱貼。我們的公司——一個剛剛成立3年的商業公司,因為網絡應用問題和無能力及時發布新功能而面臨倒閉。我們的商業合作伙伴也準備放棄我們了,但自從我們實施敏捷開發(Scrum)以后,他們看到了我們為提高穩定性和響應能力所做的努力。我們的執行者致力于具有長遠收益的投資。

            【經驗教訓】

            一個迫在眉睫的災難可能是巨大進步的推動力。

            我們知道這些單元級別的測試具有最好ROI。我們也理解TDD事實上是代碼設計,而不是測試。考慮“代碼是用來做什么的”可以幫助程序員寫出正確的代碼,而快速實施測試,才能及時地提供重要的反饋信息。

            單元級別測試的最大好處就是能夠提供最快速的反饋。在研究一些好的實踐之后,我們決定將代碼構建過程的時間控制在10分鐘內。這需要單元測試的隨機重構。早些時候,單元測試需要訪問數據庫,之后,程序員掌握了如何構造、模擬它,以及消除它的影響,使測試快速運行又能提供正確的測試覆蓋。

            1.4 利用驗收測試驅動開發,使用FitNesse測試GUI

            現在已經是我們自動化之旅的第8個月了,程序員已經建立了一個自動化單元測試的實用庫。對于應用程序的核心區域我們已經進行了冒煙測試,覆蓋微量代碼的大約100個JUnit測試已經完成了。但是中間層還什么都沒有,TDD此時變成了一個空殼。現在我們開始對自動化測試金字塔的中間層進行填充。

            1.4.1 內存內測試

            我們的金融理財產品有許多復雜的算法,這可以通過在內存中提供輸入來進行測試。與單元測試相比,這種測試的級別要高很多,但我們還是不想通過GUI來進行測試,因為其速度慢、成本高。我們發現可以很迅速、方便地編寫FitNesse夾具(fixture)來自動進行這類測試。在客戶測試層次,我們開始用FitNesse測試來驅動新的用戶故事的開發。這些測試使用夾具在內存中構建測試輸入,并把這些輸入發送到應用層代碼,就如同產品在實際使用時進行的輸入一樣。然后夾具會返回代碼的實際輸出,并把它與FitNesse表中的期望結果進行對比。

            測試人員和客戶填寫FitNesse測試用例,之后程序員用夾具來自動運行它們。這意味著我們需要交流!提高團隊的交流能力是使用這種工具進行自動化測試的最大好處之一。我們測試人員與產品所有者和其他利益相關者坐在一起分析每個用戶故事預期的和非預期的行為。我們將這些用戶故事轉化為FitNesse測試用例表,并與客戶核對以保證當測試用例通過測試的時候能夠滿足客戶的要求。我們與開發人員核對測試,以保證我們清楚需求并保證測試設計與代碼設計兼容。開發人員編寫夾具來自動運行測試。這一過程在單個用戶故事的很多小的迭代中不斷重復,直到開發和測試都完成。 1.4.2 使用數據庫的測試

            我們的應用是數據密集型應用,我們想自動運行更加端到端(end-to-end)的測試。我們也可以使用FitNesse在數據庫中構建測試數據,并使用遺留代碼在它上面運行,以此來測試遺留代碼。

            這種類型的測試腳本編寫和維護都更加昂貴。作為FitNesse的初學者,我們犯了一些錯誤,如,不知道將測試組件模塊化,而這可以通過FitNesse中現有的部件來完成。我們徹底違反了代碼設計中的“不要重復自我”準則。例如,在幾十個不同的測試頁面中,有包含同樣員工信息的表,如果又有一列新數據需要添加到員工信息表中,那么在每個測試頁面中都要加進去,這很糟糕。等到我們知道如何正確去做的時候,又遇到了一個更難以處理的麻煩。

            【經驗教訓】

            在前期進行工具使用的培訓,之后就可以避免因工具使用不熟練而造成的巨大的時間浪費。

            我們將每個能想到的測試用例都進行了自動化,包括發生幾率低、影響小的邊緣測試用例,并把它們都放在自動回歸測試套件(test suite)里面。上述過程花費的時間并不長,但是接下來,這個測試套件要花費大量時間和主機功率(machine power)來運行,維護成本也隨之提高了。所以,我們要學會慎重選擇測試用例,確保它們能提供充分的測試覆蓋,并只將這些測試用例放在回歸測試套件中。

            【小竅門】

            精化回歸測試套件可以在保證收益的同時降低維護費用。

            正如在產品應用代碼中所做的那樣,我們現在不斷地重復訪問和重構FitNesse測試用例,以保證我們所需要的測試覆蓋,同時不會過多地延長反饋周期或者花費太多時間維護測試。

            【真知灼見】

            經常檢查自動化測試用例以保證它們是有效的。

            1.4.3 使用FitNesse測試的好處

            我們的FitNesse測試提供了比GUI測試套件更快的反饋,盡管比JUnit測試要慢很多。FitNesse測試套件需要60 ~ 90分鐘來運行,而JUnit測試的運行時間僅僅只需要不到8分鐘。像GUI測試腳本那樣,我們將FitNesse測試集成到構建過程中,并且在其中運行。一開始,我們只在晚上運行這種“完全構建”(full build),但這無法提供及時的反饋,并且如果測試失敗的話,我們只有在第二個晚上才能知道問題是否修復了。我們投入了更多的硬件,這樣我們就可以“連續地”運行單元級別上的所有測試的完全構建。如同運行單元級別測試的構建一樣,這是為了使源代碼控制每接收到一次檢入就能運行。大概需要90分鐘運行一次,所以經常同時測試幾個新的檢入。

            (未完待續...)

          相關鏈接:

          自動化測試最佳實踐 連載一

          自動化測試最佳實踐 連載二

          posted on 2013-04-23 10:42 順其自然EVO 閱讀(329) 評論(0)  編輯  收藏 所屬分類: selenium and watir webdrivers 自動化測試學習

          <2013年4月>
          31123456
          78910111213
          14151617181920
          21222324252627
          2829301234
          567891011

          導航

          統計

          常用鏈接

          留言簿(55)

          隨筆分類

          隨筆檔案

          文章分類

          文章檔案

          搜索

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 桐柏县| 湘潭市| 南溪县| 松滋市| 武城县| 通化县| 澄城县| 林州市| 灵武市| 蓬安县| 海兴县| 政和县| 桂林市| 花莲市| 西乌珠穆沁旗| 富锦市| 北碚区| 昌吉市| 紫云| 塘沽区| 河北区| 柞水县| 丹寨县| 龙州县| 广宁县| 隆尧县| 玉田县| 洛川县| 广饶县| 万全县| 布拖县| 勃利县| 蒲城县| 黑龙江省| 喜德县| 麻阳| 庆安县| 诏安县| 开江县| 嘉黎县| 敖汉旗|