自動化測試—想說愛你不容易
正如許多事情都有其兩面性一樣,測試方法也是這樣。要保證測試方法正確,最簡單、最直觀地想法就是多寫些測試用例,從更多地角度去測試,但這必然增加我們的測試成本。小步快跑要求我們頻繁進行測試,假如我們重構的周期是20分鐘,但測試卻要花掉10分鐘,那么這樣的成本就實在太大了。假如這種測試還是開發人員手工測試,每天都有對同樣的測試反復執行數十遍,那么開發人員估計就要瘋掉了。
你可能立即就想到自動化測試了。是的,在許多重構的書籍中,大師們都建議我們在重構開始前,首先建立自動化測試機制。但遺憾的是,我經過多年的實踐總結出來的經驗是,這幾乎不可能實現。每次重構,我們面臨的都是一個個遺留系統。大多數遺留系統都有一些共同的特征:代碼凌亂,沒有清晰的接口;代碼間耦合度高,相互依賴嚴重;web層、業務層、數據訪問層往往沒有清晰的界限,代碼相互參雜其中。在這樣的情況下,編寫自動化測試代碼是幾乎不可完成的任務。當然,這里所說的自動化測試代碼,是指那些基于JUnit編寫的自動化測試程序
舉一個簡單的例子:假如你現在要測試一個開票類,想編寫它的測試代碼。本來這個開票類并不復雜,業務也很清晰。但是在函數傳遞參數時,其中一個參數是Web容器中的Request、Response或Session。這下麻煩了,為了測試一個簡單的函數,我們必須啟動整個Web應用,這是我們不可接受的。
隨后你可能會說了,我們為什么非要傳遞一個真正地Request、Response或Session呢?我們Mock一個假的嘛!想法不錯,但你真正去嘗試Mock時你會發現這也是一個不可完成的任務。Request、Response或Session有許多的狀態,屬性變量中又有對象,又有屬性變量。除此還有大量集合變量,集合變量里都有什么對象,天才知道。因此,即使你費盡千辛萬苦Mock出來,也可能因某些屬性不對而使得測試失敗。
另一個寫自動化測試程序比較忌諱的就是訪問數據庫。比如你這次執行的插入操作成功了,并不意味著下次執行就可以成功。下次執行會報“主鍵沖突”錯誤,出現這個錯誤并不是被測程序錯了,而是測試程序錯了。上次執行一個查詢產生的結果集,不一定就是下一次執行同樣一個查詢產生的結果。查詢結果變了,并不意味著被測程序錯了,而是測試程序不對。自動化測試程序之所以能夠自動化執行,必須要保證測試過程是可以反復執行的,并且不論什么時候執行都有一個確定的結果。
總之,自動化測試不是銀彈,并不是所有代碼都適合自動化測試。與Web容器或其它設備驅動相關的代碼是不適合自動化測試的,因為我們在測試的時候不希望去啟動Web容器或其它設備。因此,我們在做自動化測試程序前,首先應當確保要測試的程序已經與Web容器或其它設備驅動相關的代碼充分解耦。一個比較好的辦法就是分離出Web層與BUS層,Web層負責從Web容器中獲取數據,并打包傳遞給BUS層,而BUS層則完成真正需要測試的業務邏輯。
另一個不適合自動化測試的就是要訪問數據庫的程序,因為它們執行的結果總是與數據庫狀態有關,無法獲得穩定而可以不斷復現的結果。所以,我們解決它的最好辦法就是將訪問數據庫的部分Mock掉。如何Mock呢?你不能Mock一個JDBC,也不能Mock一個Hibernate,因為那都過于復雜了,你唯一可以做的就是將DAO層Mock掉。這就要求我們對系統重構的時候,要將數據庫訪問的代碼從業務代碼中脫離出來,寫入到DAO層。最后,被Mock的DAO層代碼并不真正去訪問數據庫。每當客戶程序傳入一個參數時,它首先作為測試程序去驗證這個參數是否與預期一致,然后返回一個確定的結果。
posted on 2014-09-15 09:32 順其自然EVO 閱讀(330) 評論(0) 編輯 收藏 所屬分類: 測試學習專欄 、selenium and watir webdrivers 自動化測試學習