如果一個軟件模塊必須要通過圖形界面才能夠觸發它的應用邏輯時,那么要對這個軟件模塊進行測試時就必須要使用圖形界面。但是圖形界面又是很難測試的?雌饋砗孟窈茈y辦。讓我們換一個角度考慮一下,其實我們真正想要測試的是軟件模塊本身的應用邏輯,而不是圖形界面的觸發邏輯。如果我們在設計時能夠把被測試的軟件模塊本身進行很好的封裝,定義良好的服務提供接口,那么我們就完全可以通過軟件模塊本身提供的接口進行測試。這樣就可以繞過難以測試的圖形界面。造成上述軟件模塊很難測試的原因正是由于在設計時把軟件模塊本身的應用邏輯和圖形界面這兩個無關的邏輯耦合在了一起。把這兩個邏輯分離,不僅可以對該軟件模塊進行更容易、更有效的測試,而且也使得該軟件模塊具有了很好的可重用性和可移植性。
那么對于不好測試的圖形界面,我們該怎么辦呢?原則很簡單,如果某種東西不好測試,那么就讓它做肯定不會出錯的事情,而把可能會出錯的邏輯剝離出來,放到一個可以測試的模塊中。對于圖形界面來說,就是僅僅保持一個很薄的圖形界面邏輯,它的工作就是把用戶的請求簡單的轉發給真正處理該請求的軟件模塊(一般稱之為Application Facade)。轉發邏輯足夠簡單以至于它肯定不會出錯,所以我們也無需對它進行測試。關于這方面更多的信息,請參見參考文獻[5]。
如果在進行軟件開發時能夠首先編寫測試代碼,那么就會迫使你從易使用性,易測試性的角度開考慮問題,從而你就會專注于軟件模塊的高層抽象和職責。這樣就會定義出清晰的、明確反映意圖的模塊接口來,另外,為了使得測試能夠進行,你就會主動把那些導致不好測試的耦合去掉。這樣的結果不僅僅是獲得了可測試性,并且也產生了更好的設計和系統架構。
但是確實存在一些不好測試的東西并且很難只讓它執行一些非常簡單的邏輯,比如嵌入式系統中的BSP(板級支持包)。開發它們所使用的語言、環境以及它們本身的特性等決定了它們是很難測試的。這里說的難測試其實是一個測試代價問題,具體的說就是要付出更多的時間和努力。這就需要你在付出的代價和測試帶來的收益之間進行平衡。如果付出的代價所帶來的收益(更少的調試、維護、發布成本)是巨大的,那么付出的代價就是非常值得的。
誤區之三:測試代碼可以隨意寫
大家肯定知道測試代碼是不能隨意編寫的,并且在編寫測試代碼時也不是抱著一種隨意的態度,但是你編寫出來的測試代碼以及測試代碼運行的情況卻表現出了一種隨意性和無序性。因為你可能并沒有弄清楚測試的真正意圖所在。
本人曾經看到過有關驗收測試的這樣一個案例,驗收測試者使用昂貴的商用測試工具對一個具有圖形界面的軟件進行測試。測試的方法是通過編寫測試腳本驅動鼠標在圖形界面上隨機的點擊(當然每一次的點擊,都點到了圖形界面上可以接收事件的區域),然后等待著被測試軟件的崩潰。當然這種測試方法可以作為驗收測試的一個方面,但是決不是唯一的一個方面。還有更重要的內容被忽視了。
測試的目的是用來檢驗軟件系統是否滿足了需求。所以,你的測試代碼一定要明確的表達出這一點來。就那上面的案例來說,如果測試者真正從用戶的需求出發,那么他寫出來的測試腳本肯定不會是那樣的,而應該是每一個測試用例都清晰的刻畫了一項用戶的需求,然后檢驗系統是否實現了用戶期望的功能。這樣的測試才是有明確目的,才是最有效的測試。和把界面邏輯和應用邏輯隔離,采用明確表現用戶需求測試用例進行測試相比,上面的測試方法不能不說是隨意了一點。
在針對類進行的單元測試中,也經常會看到一些錯誤的測試方法。很多的測試者往往針對類中的每個特定的實現細節進行測試。類中的特定的實現細節是很容易變化的,在快速的迭代式開發中更是如此。一旦你測試的類中的某個實現細節發生了變化,你原先的測試代碼就要進行相應的更改,否則就失去了意義。這種頻繁更改的代價是巨大的。類是一種抽象,它反映了更高層面的內聚性,它應該有明確的職責和定義良好的服務接口,它的職責和對外的接口相對于內部的實現細節來說要穩定的多,并且我們要驗證的正是這個類是否具備了它的職責。因此,在對類進測試時,我們應該針對類的接口來驗證類是否實現了它的職責而不是其他。這樣寫出來的測試代碼要穩定的多,也有效的多。
細想一下,造成容易陷入針對實現細節測試的原因主要是由于先實現了類,然后才去進行測試。如果先實現了類的功能,然后在去對類進行測試,潛意識中就會不由自主的想去驗證已經完成的類的某種實現細節。如果能夠在編寫實際類前,首先編寫針對該類的測試代碼,情況就會有很大的不同,因為這會迫使你從類的使用者的角度去考慮問題。結果就是會把關注點放在類的易用性上,放在類的職責上面,放在類提供服務的接口上面,而不是某種實現細節。
文章來源于領測軟件測試網 http://www.kjueaiud.com/