【摘要】 我們對自動化測試充滿了希望,然而,自動化測試卻經常帶給我們沮喪和失望。雖然,自動化測試可以把我們從困難的環境中解放出來,在實施自動化測試解決問題的同時,又帶來同樣多的問題。在開展自動化測試的工作中,關鍵問題是遵循軟件開發的基本規則。本文介紹自動化測試的 7 個步驟:改進自動化測試過程,定義需求,驗證概念,支持產品的可測試性,具有可延續性的設計( design for sustainability ),有計劃的部署和面對成功的挑戰。按照以上 7 個步驟,安排你的人員、工具和制定你的自動化測試項目計劃,你將會通往一條成功之路。
一個故事 :
我在很多軟件公司工作過,公司規模有大有小,也和來自其他公司的人員交流,因此經歷過或者聽說過影響自動化測試效果的各種各樣的的問題。本文將提供若干方法規避可能在自動化測試中出現的問題。我先給大家講一個故事,以便各位了解自動化測試會出現哪些問題。
以前,我們有一個軟件項目,開發小組內所有的人都認為應該在項目中采用自動化測試。軟件項目的經理是 Anita Delegate 。她評估了所有可能采用的自動化測試工具,最后選擇了一種,并且購買了幾份拷貝。她委派一位員工 ——Jerry Overworked 負責自動化測試工作。 Jerry 除了負責自動化測試工作,還有其他的很多任務。他嘗試使用剛剛購買的自動化測試工具。當把測試工具應用到軟件產品測試中的時候,遇到了問題。這個測試工具太復雜,難于配置。他不得不給測試工具的客戶支持熱線打了幾個電話。最后, Jerry 認識到,他需要測試工具的技術支持人員到現場幫助安裝測試工具,并找出其中的問題。在打過幾個電話后,測試工具廠商派過來一位技術專家。技術專家到達后,找出問題所在,測試工具可以正常工作了。這還算是順利了。但是,幾個月后,他們還是沒有真正實現測試自動化, Jerry 拒絕繼續從事這個項目的工作,他害怕自動化測試會一事無成,只是浪費時間而已。
項目經理 Anita 把項目重新指派給 Kevin Shorttimer ,一位剛剛被雇傭來做軟件測試的人員。 Kevin 剛剛獲得計算機科學的學位,希望通過這份工作邁向更有挑戰性的、值得去做的工作。 Anita 送 Kevin 參加工具培訓,避免 Kevin 步 Jerry 的后塵 —— 由于使用測試工具遇到困難而變得沮喪,導致放棄負責的項目。 Kevin 非常興奮。這個項目的測試需要重復測試,有點令人討厭,因此,他非常愿意采用自動化測試。一個主要的版本發布后, Kevin 準備開始全天的自動化測試,他非??释玫揭粋€機會證明自己可以寫非常復雜的,有難度的代碼。他建立了一個測試庫,使用了一些技巧的方法,可以支持大部分的測試,這比原計劃多花費了很多時間,不過, Kevin 使整個測試工作開展的很順利。他用已有的測試套測試新的產品版本,并且確實發現了 bug 。接下來, Kevin 得到一個從事軟件開發職位的機會,離開了自動化的崗位。
Ahmed Hardluck 接手 Kevin 的工作,從事自動化測試執行工作。他發現 Kevin 留下的文檔不僅少,并且沒有太多的價值。 Ahmed 花費不少時間去弄清楚已有的測試設計和研究如何開展測試執行工作。這個過程中, Ahmed 經歷了很多失敗,并且不能確信測試執行的方法是否正確。測試執行中,執行失敗后的錯誤的提示信息也沒有太多的參考價值,他不得不更深的鉆研。一些測試執行看起來仿佛永遠沒有結束。另外一些測試執行需要一些特定的測試環境搭建要求,他更新測試環境搭建文檔,堅持不懈地工作。后來,在自動化測試執行中,它發現幾個執行失敗的結果,經過分析,是回歸測試的軟件版本中有 BUG ,導致測試執行失敗,發現產品的 BUG 后,每個人都很高興。接下來,他仔細分析測試套中的內容,希望通過優化測試套使測試變得更可靠,但是,這個工作一直沒有完成,預期的優化結果也沒有達到。按照計劃,產品的下一個發布版本有幾個主要的改動, Ahmed 立刻意識到產品的改動會破壞已有的自動化測試設計。接下來,在測試產品的新版本中,絕大多數測試用例執行失敗了, Ahmed 對執行失敗的測試研究了很長時間,然后,從其他人那里尋求幫助。經過商討,自動化測試應該根據產品的新接口做修改,自動化測試才能運轉起來。最后,大家根據新接口修改自動化測試,測試都通過了。產品發布到了市場上。接下來,用戶立刻打來投訴電話,投訴軟件無法工作。大家才發現自己改寫了一些自動化測試腳本,導致一些錯誤提示信息被忽略了。雖然,實際上測試執行是失敗的,但是,由于改寫腳本時的一個編程錯誤導致失敗的測試執行結果被忽略了。這個產品終于失敗了。
這是我的故事?;蛟S您曾經親身經歷了故事當中某些情節。不過,我希望你沒有這樣的相似結局。本文將給出一些建議,避免出現這樣的結局。
問題
這個故事闡明了幾個使自動化測試項目陷入困境的原因:
自動化測試時間不充足:根據項目計劃的安排,測試人員往往被安排利用自己的個人時間或者項目后期介入自動化測試。這使得自動化測試無法得到充分的時間,無法得到真正的關注。
缺乏清晰的目標:有很多好的理由去開展自動化測試工作,諸如自動化測試可以節省時間,使測試更加簡單,提高測試的覆蓋率,可以讓測試人員保持更好的測試主動性。但是,自動化測試不可能同時滿足上述的目標。不同的人員對自動化測試有不同的希望,這些希望應該提出來,否則很可能面對的是失望。
缺乏經驗:嘗試測試自己的程序的初級的程序員經常采用自動化自動化測試。由于缺乏經驗,很難保證自動化測試的順利開展。
更新換代頻繁( High turnover ):測試自動化往往需要花費很多時間學習的,當自動化測試更新換代頻繁的時候,你就喪失了剛剛學習到的自動化測試經驗。
對于絕望的反應:在測試還遠沒有開始的時候,問題就已經潛伏在軟件中了。軟件測試不過是發現了這些潛伏的問題而已。就測試本身而言,測試是一件很困難的工作。當在修改過的軟件上一遍接一遍的測試時,測試人員變得疲勞起來。測試什么時候后結束?當按照計劃的安排,軟件應該交付的時候,測試人員的絕望變得尤其強烈。如果不需要測試,那該有多好呀!在這種環境中,自動化測試可能是個可以選擇的解決方法。但是,自動化測試卻未必是最好的選擇,他不是一個現實的解決方法,更像是一個希望。
不愿思考軟件測試:很多人發現實現產品的自動化測試比測試本身更有趣。在很多軟件項目發生這樣的情況,自動化工程師不參與到軟件測試的具體活動中。由于測試的自動化與測試的人為割裂,導致很多自動化對軟件測試并沒有太大的幫助。
關注于技術:如何實現軟件的自動化測試是一個很吸引人的技術問題。不過,過多的關注如何實現自動化測試,導致忽略了自動化測試方案是否符合測試需要。
遵守軟件開發的規則
你可能了解 SEI (軟件工程研究所)提出的 CMM (能力成熟度模型)。 CMM 分為 5 個界別,該模型用來對軟件開發組織劃分等級。 Jerry Weinberg (美國著名軟件工程專家)也創建了自己的一套軟件組織模型,在他的組織模型中增加了一個額外的級別,他稱之為零級別。很顯然,一個零模式的組織實際上也是開發軟件;零模式組織中,在開發人員和用戶之間沒有差別 [Weinberg 1992] 。恰恰在這類組織環境中,經常采用自動化測試方法。因此,把資源用于自動化測試,并且把自動化測試當作一個軟件開發活動對待,把軟件測試自動化提升到一級。這是解決測試自動化的核心的方案。我們應該像運作其他的開發項目一樣來運作軟件自動化測試項目。
像其他軟件開發項目一樣,我們需要軟件開發人員專注于測試自動化的開發任務;像其他軟件開發項目一樣,自動化測試可以自動完成具體的測試任務,對于具體的測試任務來說,自動化開發人員可能不是這方面的專家,因此,軟件測試專家應該提供具體測試任務相關的咨詢,并且提供測試自動化的需求;像其他軟件開發項目一樣,如果在開發編碼之前,對測試自動化作了整體設計有助于測試自動化開發的順利開展。像其他軟件開發項目一樣,自動化測試代碼需要跟蹤和維護,因此,需要采用源代碼管理。像其他軟件開發項目一樣,測試自動化也會出現 BUG ,因此,需要有計劃的跟蹤 BUG ,并且對修改后的 BUG 進行測試。像其他軟件開發項目一樣,用戶需要知道如何使用軟件,因此,需要提供用戶使用手冊。
本文中不對軟件開發做過多講述。我假定您屬于某個軟件組織,該組織已經知道采用何種合理的、有效的方法開發軟件。我僅僅是推動您在自動化測試開發過程中遵守已經建立的軟件開發規則而已。本文按照在軟件開發項目中采用的標準步驟組織的,重點關注測試自動化相關的事宜和挑戰。
改進軟件測試過程
定義需求
驗證概念
支持產品的可測試性
可延續性的設計( design for sustainability )
有計劃的部署
面對成功的挑戰
步驟一:改進軟件測試過程
如果你負責提高一個商業交易操作的效率,首先,你應該確認已經很好的定義了這個操作的具體過程。然后,在你投入時間和金錢采用計算機提供一套自動化的商業交易操作系統之前,你想知道是否可以采用更簡單、成本更低的的方法。同樣的,上述過程也是用于自動化測試。我更愿意把 “ 測試自動化 ” 這個詞解釋成能夠使測試過程簡單并有效率,使測試過程更為快捷,沒有延誤。運行在計算機上的自動化測試腳本只是自動化測試的一個方面而已。
例如,很多測試小組都是在回歸測試環節開始采用測試自動化的方法。回歸測試需要頻繁的執行,再執行,去檢查曾經執行過的有效的測試用例沒有因為軟件的變動而執行失敗?;貧w測試需要反復執行,并且單調乏味。怎樣才能做好回歸測試文檔化的工作呢?通常的做法是采用列有產品特性的列表,然后對照列表檢查。這是個很好的開始,回歸測試檢查列表可以告訴你應該測試哪些方面。不過,回歸測試檢查列表只是合于那些了解產品,并且知道需要采用哪種測試方法的人。
在你開始測試自動化之前,你需要完善上面提到的回歸測試檢查表,并且,確保你已經采用了確定的的測試方法,指明測試中需要什么樣的數據,并給出設計數據的完整方法。如果測試掌握了基本的產品知識,這會更好。確認可以提供上面提到的文檔后,需要明確測試設計的細節描述,還應該描述測試的預期結果,這些通常被忽略,建議測試人員知道。太多的測試人員沒有意識到他們缺少什么,并且由于害怕尷尬而不敢去求助。這樣一份詳細的文檔給測試小組帶來立竿見影的效果,因為,現在任何一個具有基本產品知識的人根據文檔可以開展測試執行工作了。在開始更為完全意義上的測試自動化之前,必須已經完成了測試設計文檔。測試設計是測試自動化最主要的測試需求說明。不過,這時候千萬不要走極端去過分細致地說明測試執行的每一個步驟,只要確保那些有軟件基本操作常識的人員可以根據文檔完成測試執行工作既可。但是,不要假定他們理解那些存留在你頭腦中的軟件測試執行的想法,把這些測試設計的思路描述清楚就可以了。
我以前負責過一個軟件模塊的自動化測試工作。這個模塊的一些特性導致實現自動化非常困難。當我了解到這項工作無需在很短的時間內完成后,決定制定一個詳細回歸測試設計方案。我仔細地檢查了缺陷跟蹤庫中與該模塊相關的每個已經關閉的缺陷,針對每個缺陷,我寫了一個能夠發現該問題的測試執行操作。我計劃采用這種方法提供一個詳細的自動化需求列表,這可以告訴我模塊的那一部分最適合自動化測試。在完成上述工作后,我沒有機會完成測試自動化的實現工作。不過,當我們需要對這個模塊做完整回歸測試的時候,我將上面提到的文檔提供給若干只了解被測試產品但是沒有測試經驗的測試人員。依照文檔的指導,幾乎不需要任何指導的情況下,各自完成了回歸測試,并且發現了 BUG 。從某種角度看,這實際上是一次很成功的自動化測試。在這個項目中,我們與其開發自動化測試腳本,還不如把測試執行步驟文檔化。后來,在其它項目中,我們開發了自動化測試腳本,發現相關人員只有接受相關培訓才能理解并執行自動化測試腳本,如果測試自動化設計的很好,可能會好一些。不過,經過實踐我們總結出完成一份設計的比較好的測試文檔,比完成一份設計良好的測試腳本簡單的多。
另外一個提高測試效率的簡單方法是采用更多的計算機。很多測試人員動輒動用幾臺計算機,這一點顯而易見。我之所以強調采用更多的計算機是因為,我曾經看到一些測試人員被誤導在單機上努力的完成某些大容量的自動化測試執行工作,這種情況下由于錯誤的使用了測試設備、測試環境,導致測試沒有效果。因此,自動化測試需要集中考慮所需要的支撐設備。
針對改進軟件測試過程,我的最后一個建議是改進被測試的產品,使它更容易被測試,有很多改進措施既可以幫助用戶更好的使用產品,也可以幫助測試人員更好的測試產品。稍后,我將討論自動化測試的可測試需求。這里,我只是建議給出產品的改進點,這樣對手工測試大有幫助。
一些產品非常難安裝,測試人員在安裝和卸載軟件上花費大量的時間。這種情況下,與其實現產品安裝的自動化測試,還不如改進產品的安裝功能。采用這種解決辦法,最終的用戶會受益的。另外的一個處理方法是考慮開發一套自動安裝程序,該程序可以和產品一同發布。事實上,現在有很多專門制作安裝程序的商用工具。
另一些產品改進需要利用工具在測試執行的日志中查找錯誤。采用人工方法,在日志中一頁一頁的查詢報錯信息很容易會讓人感到乏味。那么,趕快采用自動化方法吧。如果你了解日志中記錄的錯誤信息格式,寫出一個錯誤掃描程序是很容易的事情。如果,你不能確定日志中的錯誤信息格式,就開始動手寫錯誤掃描程序,很可能面臨的是一場災難。不要忘記本文開篇講的那個故事中提到的測試套無法判斷測試用例是否執行失敗的例子。最終用戶也不愿意采用通過搜索日志的方法查找錯誤信息。修改錯誤信息的格式,使其適合日志掃描程序,便于掃描工具能夠準確的掃描到所有的錯誤信息。這樣,在測試中就可以使用掃描工具了。
通過改進產品的性能對測試也是大有幫助的。很顯然的,如果產品的性能影響了測試速度,鑒別出性能比較差的產品功能,并度量該產品功能的性能,把它作為影響測試進度的缺陷,提交缺陷報告。
上面所述的幾個方面可以在無需構建自動化測試系統的情況下,大幅度的提高測試效率。改進軟件測試過程會花費你構建自動化測試系統的時間,不過改進測試過程無疑可以使你的自動化測試項目更為順利開展起來。
步驟二:定義需求
在前面的故事中,自動化工程師和自動化測試的發起者的目標存在偏差。為了避免這種情況,需要在自動化測試需求上保持一致。應該有一份自動化測試需求,用來描述需要測試什么。測試需求應該在測試設計階段詳細描述出來,自動化測試需求描述了自動化測試的目標。很多人認為自動化測試顯然是一件好事情,但是,他們不愿意對自動化測試的目標給出清晰的描述。下面是人們選用自動化測試的幾個原因:
加快測試進度從而加快產品發布進度
更多的測試
通過減少手工測試降低測試成本
提高測試覆蓋率
保證一致性
提高測試的可靠性
測試工作可以由技術能力不強測試人員完成
定義測試過程,避免過分依賴個人
測試變得更加有趣
提高了編程技能
開發管理、測試管理和測試人員實現自動化測試的目標常常是有差別的。除非三者之間達成一致,否則很難定義什么是成功的自動化測試。
當然,不同的情況下,有的自動化測試目標比較容易達到,有的則比較難以達到。測試自動化往往對測試人員的技術水平要求很高,測試人員必須能理解充分的理解自動化測試,從而通過自動化測試不斷發現軟件的缺陷。不過,自動化測試不利于測試人員不斷的積累測試經驗。不管怎么樣,在開始自動化測試之前應該確定自動化測試成功的標準。
手工測試人員在測試執行過程中的一些操作能夠發現不引人注意的問題。他們計劃并獲取必要的測試資源,建立測試環境,執行測試用例。測試過程中,如果有什么異常的情況發生,手工測試人員立刻可以關注到。他們對比實際測試結果和預期測試結果,記錄測試結果,復位被測試的軟件系統,準備下一個軟件測試用例的環境。他們分析各種測試用例執行失敗的情況,研究測試過程可疑的現象,尋找測試用例執行失敗的過程,設計并執行其他的測試用例幫助定位軟件缺陷。接下來,他們寫作缺陷報告單,保證缺陷被修改,并且總結所有的缺陷報告單,以便其他人能夠了解測試的執行情況。
千萬不要強行在測試的每個部分都采用自動化方式。尋找能夠帶來最大回報的部分,部分的采用自動化測試是最好的方法?;蛟S你可能發現采用自動化執行和手動確認測試執行結果的方式是個很好的選擇,或許你可以采用自動化確認測試結果和手工測試執行相結合和方式。我聽到有人講,除非測試的各個環節都采用自動化方式,否則不是真正意義上的自動化測試,這真是胡言亂語。如果僅僅是為了尋找挑戰,可以嘗試在測試的每個環節都采用自動化方法。但是,如果尋找成功測試的方法,請關注那些可以快速建立的,可以反復利用的自動化測試。
定義自動化測試項目的需求要求我們全面地、清楚地考慮各種情況,然后給出權衡后的需求,并且可以使測試相關人員更加合理的提出自己對自動化測試的期望。通過定義自動化測試需求,距離成功的自動化測試近了一步。
步驟三:驗證概念
在前面的故事當中,那個自動化測試人員在對測試方向一片茫然的情況下一頭扎進了自動化測試項目中。不過,在項目的進行中,他得到了來自各個方面的支持。
你可能還沒有認識到這一點,不過,你必須驗證自動化測試項目的可行性。驗證過程花費的時間往往比人們預期的要長,并且需要來自你身邊的各種人的幫助。
很多年前,我從事一個測試自動化項目的工作,參加項目的人員有各種各樣的好點子。我們設計了一個復雜的自動化測試系統,并且非常努力工作去實現系統的每個模塊。我們定期的介紹測試自動化的設計思路和工作進度,甚至演示已經完成的部分功能。但是,我們沒有演示如何利用該套測試自動化系統如何開展實際的測試工作。最后,整個項目被取消了,此后,我再也沒有犯這個錯誤。
你需要盡可能快地驗證你采用的測試工具和測試方法的可行性,站在產品的角度驗證你所測試的產品采用自動化測試的可行性。這通常是很困難的,需要盡快地找出可行性問題的答案,需要確定你的測試工具和測試方法對于被測試的產品和測試人員是否合適。你需要做是驗證概念 —— 一個快速、有說服力的測試套可以證明你選在測試工具和測試方法的正確性,從而驗證了你的測試概念。你選擇的用來驗證概念的測試套是評估測試工具的最好的方式。
對于很多人來說,自動化測試意味著 GUI 自動化測試,我不同意這種觀點。我曾經做過 GUI 和非 GUI 自動化測試,并驚奇的發現這兩類測試的測試計劃有很大的互補性。不過, GUI 測試工具很昂貴、并且過分講究。選擇合適的 GUI 測試工具是很重要的,因為,如果沒有選擇合適的測試工具,你會遇到很多不可預測的困難。 Elisabeth Hendrickson 曾經寫過一篇關于選擇測試的工具的指導性文章 [Hendrickson 1999] 。我建議在評估測試工具中,找出能夠驗證你的想法的證據是很重要的環節。這需要測試工具至少有一個月試用期,你可能打算現在購買一份測試工具,然后直到評估完成后再購買更多份。你需要在付出大筆金錢購買測試工具的之前,找出工具存在的問題。這樣,你可以從測試工具供應商得到更好的幫助,當你打算更換工具的時候,你不會感覺很為難。
下面是一些候選的驗證概念的試驗:
回歸測試:你準備在每個版本運行同樣的測試用例嗎?回歸測試是最宜采用自動化測試的環節。
配置測試:你的軟件支持多少種不同的平臺?你打算在所有支持的平臺上測試執行所有的測試用例嗎?如果是的,那么采用自動化測試是有幫助的。
測試環境建立:對于大量不同的測試用例,可能需要相同的測試環境搭建過程。在開展自動化測試執行之前,先把測試環境搭建實現自動化。
非 GUI 測試:實現命令行和 API 的測試自動化比 GUI 自動化測試容易的多。
無論采用什么測試方法,定義一個看得見的目標,然后集中在這個目標上。驗證你自動化測試概念可以使自動化更進一步邁向成功之路。
步驟四:支持產品的可測試性
軟件產品一般會用到下面三種不同類別的接口:命令行接口( command line interfaces ,縮寫 CLIs) 、應用程序接口( API )、圖形用戶接口( GUI )。有些產品會用到所有三類接口,有些產品只用到一類或者兩類接口,這些是測試中所需要的接口。從本質上看, API 接口和命令行接口比 GUI 接口容易實現自動化,去找一找你的被測產品是否包括 API 接口或者命令行接口。有些時候,這兩類接口隱藏在產品的內部,如果確實沒有,需要鼓勵開發人員在產品中提供命令行接口或者 API 接口,從而支持產品的可測試性。
下面,更多多的講解 GUI 自動化測試相關內容。這里有幾個原因導致 GUI 自動化測試比預期的要困難。第一個原因是需要手工完成部分腳本。絕大多數自動化測試工具都有 “ 錄制回放 ” 或者 “ 捕捉回放 ” 功能,這確實是個很好的方法??梢允止绦袦y試用例,測試工具在后臺記住你的所有操作,然后產生可以用來重復執行的測試用例腳本。這是一個很好的方法,但是很多時候卻不能奏效。很多軟件測試文章的作者得出結論 “ 錄制回放 ” 雖然可以生成部分測試腳本,但是有很多問題導致 “ 錄制回放 ” 不能應用到整個測試執行過程中。 [Bach 1996, Pettichord 1996, Kaner 1997, Linz 1998, Hendrickson 1999, Kit 1999, Thomson 1999, Groder 1999]. 結果, GUI 測試還是主要由手工完成。
第二個原因,把 GUI 自動化測試工和被測試的產品有機的結合在一起需要面臨技術上的挑戰。經常要在采用眾多專家意見和最新的 GUI 接口技術才能使 GUI 測試工具正常工作。這個主要的困難也是 GUI 自動化測試工具價格昂貴的主要原因之一。非標準的、定制的控件會增加測試的困難,解決方法總是有的,可以采用修改產品源代碼的方式,也可以從測試工具供應商處升級測試工具。另外,還需要分析測試工具中的 BUG ,并且給工具打補丁。也可能測試工具需要做相當的定制,以便能有效地測試產品界面上的定制控件。 GUI 測試中,困難總是意外出現,讓人驚奇。你也可能需要重新設計你的測試以規避那些存在問題的界面控件。
第三個原因, GUI 設計方案的變動會直接帶來 GUI 自動化測試復雜度的提高。在開發的整個過程中,圖形界面經常被修改或者完全重設計,這是出了名的事情。一般來講,第一個版本的圖形界面都是很糟糕。如果處在圖形界面方案不停變動的時候,就開展 GUI 自動化測試是不會有任何進展的,你只能花費大量的時間修改測試腳本,以適應圖形界面的變更。不管怎樣,即便界面的修改會導致測試修改腳本,你也不應該反對開發人員改進圖形界面。一旦原始的設計完成后,圖形界面接口下面的編程接口就固定下來了。
上面提到的這些原因都是基于采用 GUI 自動化測試的方法完成產品的功能測試。圖形界面接口當然需要測試,可以考慮實現 GUI 測試自動化。不過,你也應該考慮采用其他方法測試產品的核心功能,并且這些測試不會因為圖形界面發生變化而被中斷,這類測試應該采用命令行接口或者 API 接口。我曾經看到有人選擇 GUI 自動化測試,因為,他們不打算修改被測試產品,但是,最終他們認識到必須對產品做修改,以保證 GUI 測試自動化可以正常工作。無論你選擇哪種方法,自動化都需要對被測試的產品做修改。因此,采用可編程的接口是最可靠的。
為了讓 API 接口測試更為容易,應該把接口與某種解釋程序,例如 Tcl 、 Perl 或者 Python 綁定在一起。這使交互式測試成為可能,并且可以縮短自動化測試的開發周期。采用 API 接口的方式,還可以實現獨立的產品模塊的單元測試自動化。
一個關于隱藏可編程接口的例子是關于 InstallShield—— 非常流行的制作安裝盤的工具。 InstallShield 有命令行選項,采用這種選項可以實現非 GUI 方式的安裝盤,采用這種方式,從提前創建好的文件中讀取安裝選項。這種方式可能比采用 GUI 的安裝方式更簡單更可靠。
另一個例子是關于如何避免基于 WEB 軟件的 GUI 自動化測試。采用 GUI 測試工具可以通過瀏覽器操作 WEB 界面。 WEB 瀏覽器是通過 HTTP 協議與 WEB 服務器交互的,所以直接測試 HTTP 協議更為簡單。 Perl 可以直接連接 TCP/IP 端口,完成這類的自動化測試。采用高級接口技術,譬如客戶端 JAVA 或者 ActiveX 不可能利用這種方法。但是,如果在合適的環境中采用這種方式,你將發現這種方式的自動化測試比 GUI 自動化測試更加便宜更加簡單。
我曾經受雇在一家公司負責某個產品 GUI 相關的自動化測試,該產品也提供命令行接口,不過,他們已經實現了 GUI 的自動化測試。經過一段時間的研究,我發現找到圖形界面中的 BUG 并不困難,不過,用戶并不關注圖形界面,他們更喜歡使用命令行。我還發現我們還沒有針對最新的產品功能(這些功能即可通過 GUI 的方式,也可以通過命令行的方式使用)實現自動化測試。我決定推遲 GUI 自動化測試,擴展命令行測試套,測試新增的產品功能?,F在回過頭看這個決定,我沒有選擇 GUI 自動化測試是最大的成功之處,如果采用了 GUI 自動化測試所有的時間和努力都會浪費在其中。他們已經準備好做 GUI 自動化測試了,并且已經購買了一套測試工具和其他需要的東西,但我知道在開展具體的 GUI 自動化測試活動中,會遇到各種各樣的困難和障礙。
無論你需要支持圖形界面接口、命令行接口還是 API 接口,如果你盡可能早的在產品設計階段提出產品的可測試性設計需求,未來的測試工作中,你很可能成功。盡可能早的啟動自動化測試項目,提出可測試性需求,會使您走向自動化測試成功之路。
步驟五:具有可延續性的設計
在開篇的故事中,我們看到由于自動化工程師把注意力僅僅集中在如何使自動化運轉起來,導致測試自動化達不到預期的效果。自動化測試是一個長期的過程,為了與產品新版本的功能和其他相關修改保持一致,自動化測試需要不停的維護和擴充。自動化測試設計中考慮自動化在未來的可擴充性是很關鍵的,不過,自動化測試的完整性也是很重要的。如果自動化測試程序報告測試用例執行通過,測試人員應該相信得到的結果,測試執行的實際結果也應該是通過了。其實,有很多存在問題的測試用例表面上執行通過了,實際上卻執行失敗了,并且沒有記錄任何錯誤日志,這就是失敗的自動化。這種失敗的自動化會給整個項目帶來災難性的后果,而當測試人員構建的測試自動化采用了很糟糕的設計方案或者由于后來的修改引入了錯誤,都會導致這種失敗的測試自動化。失敗的自動化通常是由于沒有關注自動化測試的性能或者沒有充分的自動化設計導致的。
性能: 提高代碼的性能往往增加了代碼的復雜性,因此,會威脅到代碼的可靠性。很少有人關心如何對自動化本身加以測試。通過我對測試套性能的分析,很多測試套都是花費大量的時間等候產品的運行。因此,在不提高產品運行性能的前提下,無法更有效的提高自動化測試執行效率。我懷疑測試自動化工程師只是從計算機課程了解到應該關注軟件的性能,而并沒有實際的操作經驗。如果測試套的性能問題無法改變,那么應該考慮提高硬件的性能;測試套中經常會出現冗余,也可以考慮取出測試套中的冗余或者減少一個測試套中完成的測試任務,都是很好的辦法。
便于分析: 測試自動化執行失敗后應該分析失敗的結果,這是一個棘手的問題。分析執行失敗的自動化測試結果是件困難的事情,需要從多方面著手,測試上報的告警信息是真的還是假的?是不是因為測試套中存在缺陷導致測試執行失敗?是不是在搭建測試環境中出現了錯誤導致測試執行失敗?是不是產品中確實存在缺陷導致測試執行失敗?有幾個方法可以幫助測試執行失敗的結果分析,某些方法可以找到問題所在。通過在測試執行之前檢查常見的測試環境搭建問題,從而提高測試套的可靠性;通過改進錯誤輸出報告,從而提高測試自動化的錯誤輸出的可分析性;此外,還可以改進自動化測試框架中存在的問題。訓練測試人員如何分析測試執行失敗結果。甚至可以找到那些不可靠的、冗余的或者功能比較獨立的測試,然后安全地將之刪除。上面這些都是減少自動化測試誤報告警、提高測試可分析性的積極有效的方法。另外,有一種錯誤的測試結果分析方法,那就是采用測試結果后處理程序對測試結果自動分析和過濾,盡管也可以采用這種測試結果分析方法,不過這種方法會使自動化測試系統復雜化,更重要的是,后處理程序中的 BUG 會嚴重損害自動化測試的完整性。如果由于自動化測試本身存在的缺陷誤把產品中的正常功能視為異常,那該怎么辦?我曾經看到測試小組花費開發測試自動化兩倍的時間來修改測試腳本,并且不愿意開展培訓過程。那些僅僅關注很淺層次測試技術的測試管理者對這種方法很感興趣,他們排斥采用隱藏測試復雜度的方法。
綜上所述,應該集中精力關注可以延續使用的測試套,從以下幾方面考慮,測試的可檢視性、測試的可維護性、測試的完整性、測試的獨立性、測試的可重復性。
可讀性: 很多情況下,在測試人員開始測試項目之前,公司已經有了一套測試腳本,并且已經存在很多年了。我們可以稱之為 “ 聰明的橡樹 ”(wise oak tree)[Bach 1996] 。大家很依賴它,但是并不知道它是什么。由于 “ 聰明的橡樹 ” 類型的測試腳本缺乏可讀性,在具體應用中,那些腳本常常沒有多大的實用價值,越來越讓人迷惑。因此,測試人員很難確定他們實際在測試什么,反而會導致測試人員對自身的測試能力有過高的估計。測試人員能夠檢視測試腳本,并且理解測試腳本究竟測試了什么,這是很關鍵的。好的文檔是解決問題的手段之一,對測試腳本全面分析是另外一個手段。由上面兩種方法可以引申出其它的相關方法,我曾經在一個項目中使用過引申之后的方法。在測試腳本中插樁,把所有執行的產品相關的命令記錄到日志里。這樣,當分析日志確定執行了哪些產品命令,命令采用了何種參數配置時,可以提供一個非常好的測試記錄,里面記錄了自動化測試執行了什么,沒有執行什么。如果測試腳本可讀性不好,很容易變得過分依賴并沒有完全理解的測試腳本,很容易認為測試腳本實際上做的工作比你想象中的還要多。測試套的可讀性提高后,可以更容易的開展同行評審活動。
可維護性: 在工作中,我曾經使用過一個測試套,它把所有的程序輸出保存到文件中。然后,通過對比輸出文件內容和一個已有的輸出文件內容的差別,可以稱已有的輸出文件為 “ 標準文件 ” ( “gold file” )。在回歸測試中,用這個方法查找 BUG 是不是明智之舉。這種方法太過于敏感了,它會產生很多錯誤的警告。隨著時間的推移,軟件開發人員會根據需要修改產品的很多輸出信息,這會導致很多自動化測試失敗。很明顯,為了保證自動化測試的順利進行,應該在對 “ 標準文件 ” 仔細分析的基礎上,根據開發人員修改的產品輸出信息對之做相應的修改。比較好的可維護性方法是,每次只檢查選定的產品的某些特定輸出,而不是對比所有的結果輸出。產品的接口變動也會導致原來的測試無法執行或者執行失敗。對于 GUI 測試,這是一個更大的挑戰。研究由于產品接口變化引起的相關測試修改,并研究使測試修改量最小的方法,測試中采用庫是解決問題的方法。當產品發生變化的時候,只需要修改相關的庫,保證測試與產品的變動同步修改即可。
完整性: 當自動化測試執行后,報告測試執行通過,可以斷定這是真的嗎?這就是我稱之為測試套的完整性。在前面的故事中,當沒有對自動化測試完整性給予應有的關注的時候,發生了富有喜劇性的情況。我們應該在多大程度上相信自動化化測試執行結果?自動化測試執行中的誤報告警是很大的問題。測試人員特別討厭由于測試腳本自身的問題或者是測試環境的問題導致測試執行失敗,但是,對于自動化測試誤報告警的情況,大家往往無能為力。你期望自己設計的測試對 BUG 很敏感、有效,當測試發現異常的時候,能夠報告測試執行失敗。有的測試框架支持對特殊測試結果的分類方法,分類包括 PASS , FAIL 和第三種測試結果 NOTRUN 或者 UNRESOLVED 。無論你怎么稱呼第三種測試結果,它很好的說明了由于某些測試失敗導致其他測試用例無法執行而并非執行失敗的情況。得到正確的測試結果是自動化測試完整性定義的一部分,另一部分是能夠確認執行成功的測試確確實實已經執行過了。我曾經在一個測試隊列中發現一個 BUG ,這個 BUG 引起測試隊列中部分測試用例被跳過,沒有執行。當測試隊列運行完畢后,沒有上報任何錯誤,我不得不通過走讀代碼的方式發現了這個 BUG 。如果,我沒有關注到這個 BUG ,那么可能在認識到自動化測試已經出現問題之前,還在長時間運行部分測試用例。
獨立性: 采用自動化方法不可能達到和手工測試同樣的效果。當寫手工測試執行的規程時候,通常假定測試執行將會由一個有頭腦、善于思考、具有觀察力的測試人員完成的。如果采用自動化,測試執行是由一臺不會說話的計算機完成的,你必須告訴計算機什么樣的情況下測試執行是失敗的,并且需要告訴計算機如何恢復測試場景才能保證測試套可以順利執行。自動化測試可以作為測試套的一部分或者作為獨立的測試執行。測試都需要建立自己所需要的測試執行環境,因此,保證測試執行的獨立性是唯一的好方法。手工回歸測試通常都相關的指導文檔,以便一個接著一個有序地完成測試執行,每個測試執行可以利用前一個測試執行創建的對象或數據記錄。手工測試人員可以清楚地把握整個測試過程。在自動化測試中采用上述方法是經常犯的錯誤,這個錯誤源于 “ 多米諾骨牌 ” 測試套,當一個測試執行失敗,會導致后續一系列測試失敗。更糟糕的是,所有的測試關聯緊密,無法獨立的運行。并且,這使得在自動化測試中分析合法的執行失敗結果也困難重重。當出現這種情況后,人們首先開始懷疑自動化測試的價值。自動化測試的獨立性要求在自動化測試中增加重復和冗余設計。具有獨立性的測試對發現的缺陷的分析有很好的支持。以這種方式設計自動化測試好像是一種低效率的方式,不過,重要的是在不犧牲測試的可靠性的前提下保證測試的獨立性,如果測試可以在無需人看守情況下運行,那么測試的執行效率就不是大問題了。
可重復性: 自動化測試有時能夠發現問題,有時候又無法發現問題,對這種情況實在沒有什么好的的處理辦法。因此,需要保證每次測試執行的時候,測試是以同樣的方式工作。這意味著不要采用隨機數據,在通用語言庫中構造的隨機數據經常隱藏初始化過程,使用這些數據會導致測試每次都以不同的方式執行,這樣,對測試執行的失敗結果分析是很讓人沮喪的。這里有兩個使用隨機數據發生器的的方法可以避免上述情況。一種方法是使用常量初始化隨機數據發生器。如果你打算生成不同種類的測試,需要在可預測,并且可控制的情況下建立不同類型的隨機數據發生器。另外一個辦法是提前在文件中或數據庫中建立生成隨機測試數據,然后在測試過程中使用這些數據。這樣做看起來似乎很好,但是我卻曾經看到過太多違反規則的做法。下面我來解釋到底看到了什么。當手動執行測試的時候,往往匆匆忙忙整理文件名和測試數據記錄。當對這些測試采用自動化測試方法,該做哪些工作呢?辦法之一是,可以為測試中使用的數據記錄給固定的命名。如果這些數據記錄在測試完成后還要繼續使用,那么就需要制定命名規則,避免在不同的測試中命名沖突,采用命名規則是一種很好的方法。然而,我曾經看到有些測試只是隨機的命名數據記錄,很不幸,事實證明采用這種隨機命名的方式不可避免的導致命名沖突,并且影響測試的可重復性。很顯然,自動化工程師低估了命名沖突的可能性。下面的情況我遇到過兩次,測試數據記錄的名字中包含四個隨機產生的數字,經過簡單的推算如果我們采用這種命名方式的時候,如果測試使用了 46 條記錄,會存在 10% 沖突的可能性,如果使用 118 條記錄,沖突的幾率會達到 50% 。我認為測試當中使用這種隨機命名是出于偷懶的想法 —— 避免再次測試之前寫代碼清除老的數據記錄,這樣引入了問題,損害了測試的可靠性和測試的完整性。
測試庫: 自動化測試的一個通用策略是開發可以在不同測試中應用的測試函數庫。我曾經看到過很多測試函數庫,自己也寫了一些。當要求測試不受被測試產品接口變動影響的時候,采用測試庫方法是非常有效的。不過,根據我的觀察測試庫已經使用的太多了,已經被濫用了,并且測試庫往往設計的不好,沒有相關的文檔支撐,因此,使用測試庫的測試往往很難開展。當發現問題的時候,往往不知道是測試庫自身的問題,還是測試庫的使用問題。由于測試庫往往很復雜,即便在發現測試庫存在問題,相關的維護人員也很不愿意去修改問題。通過前文中的論述,可以得出結論,在一開始就應該保證測試庫設計良好。但是,實際情況是測試自動化往往沒有花費更多的精力去保證一個優良設計的測試庫。我曾經看到有些測試庫中的功能根本不再使用了或僅僅使用一次。這與極限編程原則保持一致,即 " 你將不需要它 " 。這會導致在測試用例之間的代碼出現一些重復,我發現微小的變化可能仍然存在,很難與測試庫功能協調。你可能打算對測試用例作修改,采用源代碼的方式比采用庫的方式更容易修改。如果有幾個測試,他們有某些共同的操作,我使用剪切和粘貼的方式去復制代碼,有的人認為我采用的方法不可理喻。這允許我根據需要修改通用代碼,我不必一開始嘗試和猜測如何重用代碼。我認為我的測試是很容易讀懂的,因為閱讀者不必關心任何測試庫的語法。這種辦法的優勢是很容易理解測試,并且很方便擴展測試套。在開發軟件測試項目的時候,大多數程序員找到與他們打算實現功能類似的源代碼,并對源代碼做修改,而不是從頭開始寫代碼。同樣,在寫測試套的過程中可以采用上述方法,這也是代碼開發方式所鼓勵的方法。我比較喜歡寫一些規模比較小的測試庫,這些庫可以被反復的使用。測試庫的開發需要在概念階段充分定義,并且文檔化,從始至終都應該保持。我會對測試庫作充分的測試后,才在測試中使用這些測試庫。采用測試庫是對所有面臨的情況作權衡的。千萬不要打算寫一個大而全的測試庫,不要希望有朝一日測試人員會利用你的測試庫完成大量的測試,這一天恐怕永遠不會到來。
數據驅動測試: 把測試數據寫入到簡單表格中,這種測試技術得到了越來越廣泛的應用,這種方法被稱為表驅動( table-driven ),數據驅動 (data-driven) 或者 “ 第三代 ” 自動化測試( "third generation" automation )。這需要寫一個解析器,用來解釋表格中的數據,并執行測試。該測試架構的最主要的好處是,它允許把測試內容寫在具有一定格式的表格中,這樣方便數據設計和數據的檢視。如果測試組中有缺少編程經驗的業務專家參與測試,采用數據驅動測試方法是很合適的。數據驅動測試的解析器主要是由測試庫和上層的少量開發語言寫成的代碼組成的,所以,上面關于測試庫的說明放在這里是同樣合適的。在針對上面提到的少量代碼的設計、開發、測試的工作,還存在各種困難。代碼所采用的編程語言是不斷發展的。也許,測試人員認為他們需要把第一部分測試的輸出作為第二部分測試的輸入,這樣,加入了新的變量。接下來,也許有人需要讓測試中的某個環節運行一百次,這樣加入一個循環。你可以采用其他語言,不過,如果你預料到會面臨上述情況的時候,那么做好采用一些能夠通過公開的渠道獲取的編程語言,比如 Perl,Python 或者 TCL ,這樣比設計你自己的語言要快的多。
啟發式確認: 我曾經看到很多測試自動化沒有真正意義上的結果校驗,其原因有兩個,一個原因是做完全意義上的自動化測試結果確認從技術上講是很困難的,另外一個原因是通過測試設計規格很難找出自動化測試的預期結果。這很不幸。不過,采用手工校驗測試結果的方法是真正意義上的測試校驗。標準文件( Gold file )是另外一中校驗測試結果的方法。首先,捕獲被測試程序的輸出,并檢視程序的輸出,然后,把輸出信息文檔化,并歸檔,作為標準文件。以后,自動化測試結果與標準文件作比較,從而達到結果校驗的目的。采用標準文件的方法,也有弊端。當產品發生變化,自動化測試的環境配置發生變化,產品的輸出發生變化的時候,采用標準文方法,會上報大量的誤報告警。做好的測試結果校驗方法是,對輸出結果的特定內容作分析,并作合理的比較。有時候,很難知道正確的輸出結果是什么樣的,但是你應該知道錯誤的輸出結果是什么樣的。開展啟發式的結果校驗是很有幫助的。我猜想一些人在自動化測試中設計了大而全的測試結果校驗方法,是因為擔心如果結果校驗漏掉了任何信息,可能導致自動化測試自身出現錯誤。不過,我們在測試過程中往往采用折衷的做法,沒有采用大而全的測試結果校驗方法,這樣就不得不面對少量漏測情況的出現的風險。自動化測試不能改變這種情況的出現。如果自動化工程師不習慣采用這種折衷的方法,那么他必須找相關人員咨詢,尋找一種合適的測試結果校驗策略,這需要有很大的創造性。目前有很多技術可以保證在不產生誤報告警的情況下,找到被測試產品的缺陷。
把注意力放在通過設計保證測試的可延續性上,選擇一個合適的測試體系架構,你將進一步邁向成功的自動化測試。
步驟六:有計劃的部署
在前面的故事中,當自動化工程師沒有提供打包后的自動化測試程序給測試執行人員,會影響到測試執行,測試執行人員不得不反過來求助自動化工程師指出如何使用自動化測試程序。
作為自動化工程師,你知道如何利用自動化方法執行測試和分析執行失敗的結果。不過,測試執行人員卻未必知道如何使用自動化測試。因此,需要提供自動化測試程序的安裝文檔和使用文檔,保證自動化測試程序容易安裝和配置。當安裝的環境與安裝的要求不匹配,出現安裝錯誤的時候,能夠給出有價值的提示信息,便于定位安裝問題。
能夠把自動化測試程序和測試套作為產品對待,那真是太好了。你應該對自動化測試程序和測試套開展測試,保證它們不依賴于任何專用的庫或者是設備上的任何其他程序。
保證其他測試人員能夠隨時利用已經提供的自動化測試程序和測試套開展測試工作;保證自動化測試是符合一般測試執行人員的思維習慣的;保證測試執行人員能夠理解測試結果,并能夠正確分析失敗的測試執行結果;這需要自動化工程師提供自動動化測試相關的指導性文檔和培訓。
作為測試管理者,你希望在自動化工程師離開前,能夠識別并修改測試套中的所有問題。自動化工程師遲早會離開的,如果你沒有及時的把測試套中的問題提出來,就會面臨廢棄已有的測試套的決定。
良好的測試套有多方面的用處。良好的測試套支持對產品新版本的測試;良好的測試套在新的軟件平臺上可以很方便的驗證產品的功能;良好的測試套支持每天晚上開始的軟件每日構造過程;甚至開發人員在代碼 check in 之前,用良好的測試套驗證代碼的正確性。
測試套的共享也很重要。很難預見以后什么人會繼續使用你開發的測試套。因此,盡量讓產品開發測試團隊中的成員都很容易獲得你的測試套??梢园褱y試套放在公司的內部網絡上,這是個很好的辦法。這樣,大家就不必為了獲取一份需要的測試套而四處打聽。有些人總是感覺自己的測試套還沒有最終完工或者不夠完美,而沒有拿出來與人分享,這種做法一定要改變,共享出來的測試套不一定非常完美,共享才是關鍵。
有計劃的自動化測試部署,保證你的測試套能夠被產品相關人員獲取到,你就向成功的自動化測試又邁進了一步。并且你的自動化測試會被一次又一次的重用。
步驟七:面對成功的挑戰
當你完成了所有的事情,測試套已經文檔化了,并且文檔已經交付了。測試執行人員能夠理解要開展的測試,并知道如何完成測試執行。隨著你所負責產品的進一步開發和維護,測試被反復重用。雖然,在自動化使測試變簡單的同時,也總是使測試過程復雜化。測試人員需要學習如何診斷自動化測試執行失敗的情況,如果不這樣做,測試執行人員會認為執行失敗的情況是由自動化引起,然后,自動化工程師被叫過來幫助診斷每一個執行失敗的情況,開發人員往往也會認為執行失敗是由于自動化測試自身引起的問題,這樣,測試執行人員就不得不學習通過手工的方式,或者通過采用少量腳本的方式重現自動化測試發現的問題,以證明他們確實發現了產品當中的 BUG 。
測試套的相關工作還沒有結束,為了提高測試覆蓋率或者測試新的產品特性,需要增加更多的測試。如果已有的測試不能正常工作,那么需要對之修改;如果已有的測試是冗余的,那么需要刪除這部分測試。
隨著時間的推移,開發人員也會研究你設計的測試,改進產品的設計并且通過模擬你的測試過程對產品做初步測試,研究如何使產品在第一次測試就通過,這樣,你設計的測試很可能無法繼續發現新的問題,這種現象被稱為一種殺蟲劑悖論。這時候,會有人對你的測試有效性提出質疑,那么,你必須考慮是否應該挖掘更嚴格的測試,以便能夠發現開發人員優化之后的產品中的缺陷。
以前,我提到過一個基本上無法實現的設想,設想通過按下一個按鈕就完成了所有的測試工作。自動化測試是不是全能的,手工測試是永遠無法完全替代的。
有些測試受測試環境的影響很大,往往需要采用人工方法獲取測試結果,分析測試結果。因此,很難在預先知道設計的測試用例有多大的重用性。自動化測試還需要考慮成本問題,因此,千萬不要陷入到一切測試都采用自動化方法的錯誤觀念中。
我曾經主張保證給與測試自動化持續不斷的投入。但是,在開展自動化測試的時候,一個問題擺在面前,測試自動化應該及時的提供給測試執行人員,這個不成問題,但是如何保證需求變更后,能夠及時提供更新后的自動化測試就是個大問題了。如果自動化測試與需求變更無法同步,那么自動化測試的效果就無法保證了,測試人員就不愿意花費時間學習如何使用新的測試工具和如何診斷測試工具上報的錯誤。識別項目計劃中的軟件發布日期,然后把這個日期作為里程碑,并計劃達到這個里程碑。當達到這個里程碑后,自動化工程師應該做什么呢?如果自動化工程師關注當前產品版本的發布,他需要為測試執行人員提供幫助和咨詢,但是,一旦測試執行人員知道如何使用自動化測試,自動化測試工程師可以考慮下一個版本的測試自動化工作,包括改進測試工具和相關的庫。當開發人員開始設計產品下一個版本中的新特性的時候,如果考慮了自動化測試需求,那么自動化測試師的設計工作就很好開展了,采用這種方法,自動化測試工程師可以保持與開發周期同步,而不是與測試周期同步。如果不采用這種方式,在產品版本升級的過程中,自動化測試無法得到進一步的改進。
持續在在自動化投入,你會面臨成功的挑戰,當自動化測試成為測試過程可靠的基礎后,自動化測試的道路將會越來越平坦。
原文轉自:http://www.anti-gravitydesign.com