自動化測試最佳實踐 連載二
0.2 技術因素
在我們看來,最重要的技術因素是測試件架構以及多個層次上的抽象。測試件(testware)是所有創建的用于測試的事物,包括腳本、數據、文檔、文件、環境信息等。測試件架構就是這些事物是如何組織的,以及它們彼此之間是如何依賴的——例如,高層次的腳本使用了低層次的腳本用來與被測軟件進行交互。
0.2.1 抽象、抽象、再抽象:測試件架構
在最初得到了一個測試執行工具后,通常會期望測試人員開始使用這個工具。當這名測試人員不是開發人員時會發生什么?現在突然需要他們成為程序員,去學習工具的腳本語言。如果他們沒有編程背景,他們就不知道如何構建堅固的(自動化)代碼,于是當對被測軟件進行改動,同時這項改動也需要在自動化代碼中進行時,維護他所寫的代碼可能就要付出很大的代價。通常,公司放棄一個測試執行工具是因為測試腳本維護費用很高!
對于成功的自動化測試執行來說,(至少)有兩個主要的抽象層次:將工具和工具特定細節與結構化的測試件分離開來;將測試(即測試人員所從事的工作)與結構化的測試件分離開來。這些內容會在0.2.1.1節和0.2.1.2節中進行更詳細的描述。
自動化測試人員負責實現這些層次的抽象;如果這些層次實現得不好,那么自動化維護起來就會很昂貴而且很難使用。圖0-1展示的是我們認為好的測試件架構,其中還包含了為了達到這些層次的抽象自動化測試人員所扮演的角色。
圖0-1 抽象的層次
0.2.1.1 將測試執行工具與測試件分離開來
一個好的測試件架構能夠讓測試自動化發揮真正的力量。自動化測試架構師負責設計測試件的架構:腳本、數據文件和實用工具等,這些都是自動化測試所需要的。其他的自動化測試人員在之后必須對其進行補充和完善。這里需要好的編程實踐:良好的結構,遵守一些合理標準的模塊化代碼,這些標準鼓勵代碼的簡易性和復用性。當軟件的一些方面有所改變時,也許測試件需要進行改動,但是一個好的架構會讓這些變動最小。
可以通過框架來實現測試件架構,框架可能是測試執行工具的一部分,也可能和測試執行工具分開;或者也可以通過分開的測試控制程序或者測試解釋器來實現測試件架構。
有時人們在用戶界面(UI)對象(如按鈕和編輯框)周圍使用包裝器(wrapper)。包裝器是個好的開始而且對于好的自動化測式來說也很有必要(但是并不足夠)。為GUI對象的名字使用對象映射(object map)也是另一個用來實現合適層次抽象的例子。
另外一個重要的方面是較高級的測試件不應該直接與任何特定的工具或者工具語言綁定在一起。當然,在工具接口上,腳本必須是以選擇的工具語言所編寫,但是這僅僅是對于最底層而言;結構化的腳本應該以與工具無關的方式編寫。你也許會認為,當前使用的工具很完美,為什么還要這么做?但是隨著時間的推移工具會發生變化,應用程序也已意料之外的方式發生改變,系統可能要遷移到其他環境或者平臺上,于是3年前看起來完美的工具現在看起來并不那么合適。如果測試件和工具緊緊地綁定到一起,那么很有可能你最終會不得不拋棄測試件的很多部分。如果達到了這個層次的抽象,那么就可以保留結構化的測試件的大部分,僅僅需要改動最底層的那些與工具相關的腳本。
這個層次的抽象能讓自動化測試有著更長的生命周期。通過使用正確層次的抽象,無論是在應用程序上進行了改動,還是在當前使用的工具發生了變動,依然可以使得自動化測試繼續進行下去。在本書提到的所有成功案例研究中都在一定程度上實現了這一層次的抽象。
0.2.1.2 將測試與測試件分離開來
頂層(高層)的抽象是將測試的基本想法(即對什么進行測試)與測試的實現(如何構建自動化測試)分離。測試人員使用對他們有意義的高級(領域相關的)關鍵字編寫測試,以描述他們想要運行的測試。
這一級別的抽象對于那些沒有編程技能的測試人員是最重要的。他們的專業技能可能是有關業務或者應用程序的。如果是程序員在開發測試,他們會更加理解這些測試技術是如何實現的,于是這層的抽象對他們來說就沒有那么重要;這些對于開發人員最合適的高級關鍵字可能對那些業務用戶來說過于技術性。但是不要忽略這一點,即對于那些編寫和維護測試的人員來說,易于使用這些測試是很重要的,而不管他們是不是程序員。
測試人員的工作是測試(見0.1.5節中關于技能的部分)。在關注如何最好地對一些事物進行測試時,不應該考慮過多的實現細節。他們應該能夠使用對他們來說有意義的語言來編寫測試,而不是使用只對工具有意義的編程語言。他們關于測試的想法與他們的領域有關(即他們測試的應用程序),于是他們的測試也應該與這個領域有關。
例如,一個擁有保險業務知識的測試人員可能會關注保險索賠和續保。一名專注移動設備的測試人員可能會想對網絡連接、會議電話等進行測試。對于不同行業部門的人來說,這些高層次關鍵字可能非常不同,即使一些低層次的關鍵詞可能會相同。這就是為什么我們喜歡這個詞目——“領域相關的測試語言”(Domain-Specific Test Language, DSTC),這點Martin Gijsen曾也提到(www.deanalist.nl)。
如果沒有任何編程經驗的測試人員既能編寫也能運行自動化測試,那么自動化測試就能對業務領域有巨大的幫助,而且更有可能廣泛地應用,進一步增加ROI。
專門地討論這個層次抽象的案例研究包含在第2、11、12、14、15、20、21、27和29章。
0.2.2 自動化測試標準
如果人們僅僅關注自己的事情,他們將會以只對他們有意義的方式創建自動化測試和測試件,然而他們創建的東西彼此之間都不相同。如果想要很多人使用自動化測試,那么定義自動化的標準并去遵守這一標準是很重要的。標準的命名約定,存儲測試件條目的統一的地方,創建測試的標準方式,歸檔測試的標準例子,對象、腳本和數據文件的標準名稱;每個腳本的標準文件頭——需要達成一致并且普遍使用的事情遠比你能想到的還要多。之外,使用自動化測試的人越多,遵循標準就越重要,并能帶來更大的收益。
對這些自動化測試標準的定義最好在試點項目中開始,在試點項目中可以嘗試各種方法并且達成一致。之后必須將大家都同意的標準告知所有將要使用自動化測試的人員——無論使用領域相關的測試語言定義自動化測試的人員,還是開發可復用腳本的人員。我們還建議將一些標準構建到支持測試的工具中,以便更容易地創建更多的腳本,而且還能避免很多人為錯誤。
然而這些標準也不應該一成不變。隨著自動化測試變得成熟,保證標準可以變更以及遵循新的(改進的)方法進行更新是個很好的主意。另外很重要的是,允許標準中出現例外情況,當然,要對這些例外進行驗證。隨著自動化測試規模變大,將標準進行集中管理并且就其與所有人員進行溝通就變得更加重要。關于標準的討論參見第6、9、12、15、21和29章。
0.2.3 可復用性、文檔和靈活性
雖然有時構建一些“可以丟棄的腳本”(disposable script,參見第19章)是很有用的,然而大部分自動化測試中,單個腳本都有很長的生命周期,并且需要以多種方式復用。如果腳本使用多次,那么就值得花費時間去保證它構建良好,如其中包含良好的錯誤處理方法,并且保證對其進行過測試和審閱。去找尋那些可以復用的模塊,而不是一切都從頭編寫。
為了使得測試自動化人員能夠找到并且使用可復用的模塊,這些模塊必須有良好的文檔。應該可以很容易地訪問這些測試件條目的信息,而且這些信息應該以標準的格式呈現出來。例如,在每個腳本頭,寫出這個腳本的目的、如何使用這個腳本(它期望接收的數據以及返回的數據),以及一些前置條件和后置條件。一些額外的信息也很有用,如在一些可能的錯誤條件下會發生什么。這些信息應該可以很容易地搜索到。事實上,將這些信息收集起來就可以作為測試件的文檔,而且通常可以很直接地將這些信息收集起來,并將其分類到單獨的文檔或者集中進行管理。
在運行測試時,靈活性是很重要的。例如,如果一個腳本正在處理從電子表格中得到的數據,而且并不需要電子表格中所有項都填滿,那么一個更加靈活的腳本應該允許跳過那些沒有值的字段,這可使測試人員很容易創建各種不同的測試。
為每個測試標注上該測試屬于哪一類也是很有用的,例如,可以標記其為冒煙測試、修復bug的測試或者對函數X進行的測試。使用這種“測試選擇器”可以很快地選擇在給定時間運行測試的不同子集。
這些主題在第3、5、11、14、21和29章中討論。
0.2.4 測試結果和報告
評估測試的結果是測試所做的最基本的事情:如果不關心結果是什么,那么它就不是一個測試!然而對自動化測試的結果進行檢查并不是一件顯而易見的事情,尤其是當檢查結果是以屏幕截圖的位圖存儲時(要盡可能避免),對結果進行自動化檢查就更加困難。
工具不會告訴你一個測試通過還是失敗;它僅僅能告訴你測試結果和你期望的結果是否匹配。如果期望結果就是錯誤的,那么工具可能很“高興地”認為所有的測試都通過,即使它正在做錯誤的事情!
有時,自動化測試可能愚弄你,讓你認為它們正在檢查一些東西,而實際上沒有——通過的測試通常不會有人進行檢查,然而這有時會帶來嚴重的問題,正如第15、19和29章所討論的(第15章稱這些測試為“僵尸測試”)。
對于測試結果的報告應該讓收到報告的人能夠理解這些測試;為此可能需要做一些額外的工作來過濾以及解釋原始的測試結果,但是這些工作很值得,因為這能讓各類人員對這些測試有著更好的交流。這些主題在第3、5、13和20章中討論。
有時通過使用部分的預言(oracle),自動化測試僅僅能夠檢查測試結果的一部分而不是所有。例如,探索性的自動化測試(第28章和第29章)、猴子測試(第24章)和可靠性測試(第13章),可能會檢查系統是否還在運行而不是檢查系統的結果是否正確。當能夠自動地生成大量測試時,僅僅檢查系統是否能存活下來也是很有價值的。
更多的關于測試結果和報告的討論見第3、5、10、13、14、17、19、20和29章。
0.2.5 對測試進行測試:審閱、靜態分析、對測試件進行測試
自動化代碼(包括腳本)也是軟件,正如所有的軟件一樣,它們也會有bug,并且必須對其進行測試。對自動化測試件進行審閱,甚至檢查,也能幫助找到在測試件本身中的bug和問題,并且保證自動化測試與它的目標是一致的。這還能夠有助于團隊內溝通知識,讓團隊人員更好地了解測試件的細節。不需要審閱所有的事情——選擇一個具有代表性的測試方案,并且與利益相關者對其進行審閱是一種很有效的方式,有助于確定正在進行的工作是否正常。
正如第15章所述,另一個來自軟件開發的技術,是對測試腳本的靜態分析。靜態分析工具能夠發現代碼(包括自動化代碼)中的bug,這些bug在評審過程中以及測試中可能發現不到。雖然靜態分析不能找到所有的bug,但其發現bug的速度很快而且成本很低。
這些主題在第1、5、7、10、15、17、21和29章中討論。
0.2.6 對哪些測試進行自動化
第2章和第12章證明了對那些沒有價值的測試進行自動化是沒有意義的——首先,保證將進行自動化的測試是值得自動化的;其次僅僅自動化那些重復使用的測試。
首先應該對哪些測試進行自動化?那些對測試人員來說執行起來很無聊的、那些普通的并且重復的、或者那些非常復雜的測試,都是開始自動化的最佳候選測試,但是也要根據當前最需要解決的問題來進行選擇,總的來說,要對那些能夠為測試帶來價值的測試進行自動化。
第25章給出了一個用于決定是否對某個測試進行自動化的檢查列表。知道不要對什么進行自動化以及應該對什么進行自動化是很重要的。過多地進行自動化也會影響自動化的結果,因為這可能使你難于獲得一些“快速的回報”(quick win),雖然這些回報能更有效地證明自動化的價值。
這些主題在第2、8、19、20、22、25和29章中討論。
0.2.7 自動化測試不僅僅是執行測試
大多數人認為測試執行工具僅僅是用來執行測試的工具。然而,要達到好的自動化,僅僅對一項活動有著工具支持是遠遠不夠的。書中很多案例研究都講到,創造性地思考通過工具能支持自動化過程中的哪些活動——不論是通過使用傳統商業工具還有內部實用工具、腳本、宏等,都能給項目帶來驚人的收益。第19章主要關注這個主題,除此之外,第3、4、5、14、21、22、24、25和29章還包含了一些有用的小竅門和主意。
在自動化測試過程中經常被忽略的一個領域就是,將手動測試引入到自動化過程中是很有用的。第21章講述的例子很有趣,它在改進自動化的同時也加入了對手動測試的支持,在第1、8、12和19章也討論了這個主題。
另一個常被忽略的領域是對于預處理和后續處理任務的自動化。如果不能對這些任務進行自動化,那么自動化測試就不得不加入手動過程——這在很大程度上違背了自動化的目標!關于這個主題的更多討論請參見第2、10、11、18和22章。
0.2.8 失敗分析
當測試失敗時分析原因可能會花費大量時間,對自動化測試失敗的分析所花的時間要多于手動測試所花的時間。例如,手動測試時,在發現bug前你都知道做了些什么,所以在發現bug時就掌握了bug的上下文信息。然而,當自動化測試失敗時,你可能僅僅知道測試的ID,而并不清楚這個測試到底是做什么、它所處的位置,以及發生了哪些其他的事情。在寫bug的報告前需要重建bug的上下文信息,這需要一些時間。考慮到這種情況,自動化測試應該記錄一些日志,這些額外的信息對需要檢查測試失敗的人是很有用的。失敗分析在第20、23、27和29章中討論。
0.2.9 自動化測試是否用來發現bug
0.1.1節提到過,發現bug對于測試來說是一個好的目標,然而對于自動化的回歸測試來說,找到bug卻不是一個好目標。然而,在一些示例中自動化確實可以發現新的bug。如果自動化能夠允許運行一些測試,而這些測試不能通過其他手段運行(因為手動運行它們需要大量的時間而且不實用),那么自動化就能增加被測軟件的測試覆蓋率,而且還能發現那些其他方法找不到的bug。
基于模型的測試(model-based testing,參見第9、14、24、28和29章)不僅能夠在執行測試時發現bug,還能在模型的開發過程中發現bug。
當自動化測試能夠運行那些依靠手動幾乎不可能執行的長序列的測試時,如猴子測試、可靠性測試和探索性自動化測試,就可以發現手動測試發現不了的bug。
如果想要記錄哪些bug是通過自動化測試發現的,而不是通過其他方式發現的,第11章對bug跟蹤系統提出了一些建議用來找到這些bug。第27章有一些有趣的統計數據,比較了自動化測試發現的bug數量(<10%)與手動腳本測試和探索性測試發現的數量。
0.2.10 工具和技術方面
0.1.9節從管理的角度討論了工具,同時也必須考慮到這些工具的技術方面。如果要開發自己的工具,就可以用這些工具做你想要做的事情;理想情況下,你將會得到適用于需求的最好的工具。然而,開發工具需要進行大量的工作(通常比預計的更多),于是通常需要在期望得到的功能和可以利用的資源之間做出折中。
可以嘗試的是使用多個工具來達成某個目標,而這個目標無法用單獨的工具來完成。在采用這些工具時,要充分挖掘它們的用途。
那些和當前測試領域密切相關的工具能保證正確使用這些領域知識,而且使用起來更容易,也更少出錯。
如果你在考慮測試件該使用什么編程語言,那么就挑選那些開發人員已經熟知的并且受歡迎的編程語言。這樣就能更好地得到開發人員的幫助來解決測試件中出現的問題。
你也需要仔細注意測試的環境;測試發現的失敗應該是真正發生的問題,而不是因為在環境中忘記了加入一些因素。很多環境因素的設置也能自動化地進行,這也有效地減少了人為錯誤。
還需要關注測試和軟件的同步,尤其是當被測系統并沒有限定只能使用標準的GUI控件時。雖然有很多工具對于同步提供很好的支持,并不是在所有的情況下工具都能很好地解決問題。而且有時無法充分地解決所有同步問題。這也就意味著軟件中有些部分是不能應用自動化測試的,至少目前不行(或許未來會出現新的技術手段來解決這些問題)。
第7、8、14、17、18、19、24、26、27和29章討論了這些問題。
0.3 總結
自動化測試不再是件奢侈品而成為系統的必需品;隨著應用程序和系統變得越來越大、越來越復雜,僅僅依賴手動測試已經無法全面地測試系統。隨著技術的進步,測試也必須進行調整——而且要快。
本書描述的自動化測試的實踐包含了在21世紀第二個十年開始時測試自動化的情況。這些故事中既有痛楚也有榮耀,既有失敗也有成功,既有卓越的想法也有難以置信的決定。傾聽這些故事并且注意這些作者學習到了什么,這樣你自己的測試自動化的實踐便更有可能取得成功!
(未完待續...)
相關鏈接:
posted on 2013-04-22 09:49 順其自然EVO 閱讀(316) 評論(0) 編輯 收藏 所屬分類: selenium and watir webdrivers 自動化測試學習