隨著測試成為一門“專業”,所涉及到的范疇比較多,中培偉業《軟件自動化測試與持續集成實踐》培訓專家張老師在這里就軟件測試的一些重點問題進行了介紹。
1. 單元測試
單元測試在軟件工程中隸屬開發過程域,開發團隊在完成一部分代碼(一個類、一個方法、函數)時設計對應的單元測試用例來進行驗證這部分代碼是否按預期進行執行的行為。
實際上單元測試提了若干年,但這若干年里鮮有公司能將單元測試的覆蓋率提升到50%以上,60%的公司從不做單元測試。
為什么出現這個結果呢?
一方面,開發人員認為完成功能是首要任務,總覺得來不及也沒有職責做單元測試。修復后期別人發現的一大堆bug認為是想當然自己的工作,為了預防和減少這些bug認真的做一把單元“測試”卻不是自己職責所在了?很有意思的習慣性思維。想起多年前剛參加工作時,公司貼在座位旁邊的的一句話“你的下游就是上帝”。我們在交付下游(測試團隊/客戶)我們的東西時,我們應該做到什么程度?
另一方面,開發團隊對單元測試的重要性認知不夠。為什么認知不夠呢,因為缺乏對bug/故障的總結與分析。這屬于典型的做項目的一次性交付思維,項目/新需求交付即表示完成。事實上這個總結分析非常重要。大家可以嘗試著從重大故障庫里翻閱一下歷史上的重大故障,有些很低級的,比如結構體初始化錯誤、數組越界、變量類型錯誤、邏輯缺失、甚至select忘記了where條件都有。其實這些錯誤,在自己編碼階段完成可以通過單元測試/同行評審/代碼掃描檢查等方式發現,何必出現重大故障時扼腕嘆息?Boris Beizer:軟件歷史上最臭名昭著的錯誤都是單元測試可以發現的錯誤。
再談談單元測試的執行方法。結合性價比及開發團隊現狀,建議單元測試:
1) 先從核心代碼/核心模塊入手做;核心代碼/模塊的單元測試行覆蓋率要達到60%,方法/函數覆蓋率達到90%;
2) 單元測試用例先從基本邏輯路徑覆蓋、出錯處理、接口、邊界條件四個方面設計;
3) 結合單元測試工具框架Xunit及Xmock(打樁用)來執行;
4) 結合同行評審/自動自動靜態代碼掃描(findbugs/PMD/Cppcheck等)來執行;
5) 結合持續集成來執行,隨時看到全景視圖;
2. 功能測試
功能測試(含軟件工程中的集成和系統測試)經過多年的項目實踐,相對來說控制過程已經相對較為成熟。重點把握住幾點:
1) 波次需求-波次開發-波次測試-波次發布;
2) 開發、測試、編譯、生產環境相對獨立且權限受控;
3) 測試人員對業務的深入理解+測試用例的整理及測試要點;
4) Bug系統及bug跟蹤、Bug度量;
5) 適當頻率的回歸測試應對增量開發;
6) 實際使用人員的參與測試很重要,比如工單補錄、模擬測試;
7) 先從端到端核心流程的穿越測試入手再擴大范圍測試;
8) 重大專項的測試把握顆粒度,從最易出錯處考慮;
9) 最好版本管理+持續集成工具框架。
3. 自動化測試
很多年來一直有一個誤區,認為自動化測試能替代手工測試。事實上,目前沒有一家公司完全通過自動化測試來替代手工測試的。拿一個需求簡單對比執行時間:手工測試的時間=用例編寫(文檔)+用例執行;自動化測試的時間=用例編寫(文檔)+自動化用例設計調試+自動化用例執行。所以從普遍功能測試上看,自動化測試不會比你單純的手工測試執行更快。
但我們還是要去持續推動自動化測試呢?因為我們面對的是迭代增量迭代開發模式(敏捷也是高度迭代),我們已經測試的功能在新的功能增量上來后還好用不好用,受不受影響?從工程實踐的統計來看,經過多次版本增量迭代后,在上線前約30%的已經測試過的功能受增量代碼交叉影響而又出現bug。所以我們要對已經測試的功能做出自動化用例,當新增/迭代的版本/功能上來后,我們可以手工測試新增的版本/功能,同時啟動已經測試過的功能的自動化用例執行。這樣就能發現已測試過的功能是否受到后來功能版本的影響而導致的bug,又省略全部功能測試一遍的煩惱。因為一個項目過程中有多次迭代和增量,那么這個規模效應就越發顯現。在新需求開發過程中更為重要:將核心功能做成自動化腳本,每次上線的時候自動化執行那些核心功能的自動化腳本+手工執行本次上線需求的測試。
自動化測試腳本還應用在一次傳入多個測試數據的場合。
自動化測試的應用場景分析清楚后,我們再談談為何自動化測試即便用在回歸測試這種場合及它的作用和效果,業界公司為何仍然很少能規模、例行的做起來呢?
1)受限于自動化測試框架。目前業界的主流自動化測試框架,例如QTP、selenium、watin、watir等全部都是基于界面的自動化工具,基本原理都是捕獲界面組件(按鈕/下拉菜單/彈出框等)的動作,重新執行一遍這個動作來完成驗證。這里面涉及到界面組件的任何變化,比如位置、比如內容、比如觸發方式、比如執行環境等都需要修改和調試自動化腳本,帶來較大的維護工作量。常常地,執行一遍自動化測試腳本報出若干個各種類型的錯誤,真正定位是bug的又少,越來越失去信心,最終放棄。
2)前期的測試人員投入和堅持。我們上面分析了自動化測試的特點,所以要自動化測試例行落地,必需前期有一定的人員投入(最好測試人員分一部分精力來做),隨著腳本維護的數量和腳本的數量積累,才能有一定的規模效應出現,最終體驗到自動化測試的樂趣和價值。自動化測試還要有所堅持,因為根據上面分析的自動化測試特點,有時候很多次自動化用例執行不一定能發現關聯錯誤,關聯影響的錯誤畢竟要大幅度少于新增功能測試的錯誤。不能因為發現的bug少就認為價值小最后失望告終。
在自動化測試的落地實施上,我們建議:
1)范圍:新需求開發過程/長周期界面不易變化的項目建議做自動化測試實施;短周期項目不做自動化測試,界面易變化的項目不做自動化測試;
2)工具。互聯網類可嘗試python+webdriver+robotfromwork的自動化測試框架,這個框架之所以成為互聯網近期關注的熱門。主要還是python腳本語言的簡單好寫跨平臺的特點,再結合robotfromwork的用例管理及表格化編寫用例帶來方便性。但是正如我前面的分析,目前這類工具都是界面型工具,有天然界面變化引起維護的這個弊端。所以我們還是要強烈推薦我們自有研發的自動化測試工具Sitechtester,這個工具主要是拋開界面,將界面訪問邏輯的過程封裝,只需調服務和傳測試數據,因為在腳本制作上和腳本執行上都比較快。目前自有工具的主要弱點是C主體開發,在跨平臺使用和編寫用例上要求更具程序基礎,對于測試人員的使用有一定技術局限。
3)資源。雖然我們寄希望長期降低成本。但是不得不面對,我們在自動化初期的人員投入腳本編寫和腳本維護及自動化環境搭建等過程,建議可先從核心功能做出自動化用例,先現有人員分離部分職能來做自動化測試。
4. 測試用例
測試用例的重要性、設計方法在這兒不再闡述,我主要想表達下測試用例的積累和復用。我們知道,如果一個項目/產品的代碼重新開發的比例超過30%,這個產品/項目基本上來說是比較失敗的。測試用例亦如此。同樣產品/項目的測試用例應盡量復用或者在復用基礎上進一步修改使用,總比全部重新來寫的好。
所以要強化測試用例收集和復用的工作。收集后就是復用的問題了,先有地可尋,再強化復用。
測試用例的復用要遵循:對于項目還是建立按照產品樹-構件-測試用例,轉到項目樹的產品構件下的測試用例對應即為復用/修改屬性帶過去。對于新需求,每個產品要建立最小回歸用例集,需求上線時確保該部分用例覆蓋測試到,包括測試場景及測試數據等。
5. 敏捷開發與敏捷測試
敏捷開發和敏捷測試我們這兒不去談論它的好壞。依據我們的了解,國內真正做起敏捷開發/敏捷測試的公司也屈指可數,而且多數變了形。
敏捷真的好的事物,關鍵是我們怎么用它。
在測試方面,關鍵的是我們對敏捷測試的態度是不要照貓畫虎,應該更多的學習和借鑒它的一些方法和思想:
1)劃分波次的思想,先劃分系統的主干功能,一個波次一個波次的整理需求、設計開發、集中測試、波次交付。這樣最大限度的避免了原來我們領到任務后,黑箱操作幾個月到半年再一次性集成發布,結果要花費巨大的時間來解決集成和缺陷。波次思想的核心就是通過一次次端到端的潛在集成替代了原有的黑箱操作完畢一次性集成發布。
2)測試人員和開發人員的溝通應該是以bug為中心隨時、無障礙、互相坦誠相見,而不是傳統意義上的“相互對立”,因為目標是統一的。敏捷中的站會、總結評審會就解決了這些矛盾。
3)測試計劃應該詳細做最近一個波次的,更遠波次的測試計劃只做總體計劃。這個有好處的,其實我們都深刻有體會,計劃跟不上變化。能把握的是最近的事和人。
4)敏捷中測試用例突破原有的標準文檔模式,可以通過示意圖、測試要點(站會時隨時記錄)等方式來呈現,核心是你是否真的理解和掌握了你所測的東西。但不管何時方式呈現,都要積累下來,以備復用。
5)敏捷始終強調質量內建,也就是說測試不是保障質量的唯一環節,質量更應該是越早解決越好,體現在規劃階段的FDD、開發設計階段的極限編程(靜態代碼檢查、同行評審、單元測試、結對編程、持續集成等)、項目管理過程的scrum(共同分享信息,關注總結)等;
6)工具。不管我們是否采用敏捷,伴隨著敏捷,一大批開源工具可以被我們使用和掌握。比如持續集成的相關工具(jenkins/maven/ant等)、測試驅動開發的工具(fitnesse等)、代碼檢查的工具(findbugs等)、自動化測試工具selenium工具等。
5性能與安全測試
性能測試本身不再多說。我這兒想要說的產品/項目的性能不要單單放在性能測試的時候才去關注,到那時候產品的性能bug修復代價太大了,開發測試團隊日常中就要關注產品性能。
對于設計團隊來講,比如批量與數據庫交互設計、充分利用緩存和存儲層推前、多進程與集群設計、分表與分庫等都會對系統性能造成重大影響;對于開發團隊來講,你代碼中申請的內存不要忘記回收(malloc/free,new/delete)以免造成內存泄漏、你get的線程使用完畢要close掉、你的報文傳輸壓縮、CSS置前JS放后、請求合并處理、減少硬解析、正確使用索引等等都是避免后期性能的簡單而有效的方法,你編碼的時候考慮到了就好了。
安全測試隨著近年來重大安全事件的暴露而變得熱門。安全測試本身的技術和方法并不復雜,你用appscan、zap等工具,一會兒跑出大片安全漏洞就ok了。當然測試團隊也要理解安全漏洞的原理和攻擊方法。
本質還是開發團隊要有針對性的避免和減少安全問題。因為一旦工具跑出一堆安全問題,要不要修改?修改的代價有多大?我認為還是比較大的一個量的估算,比如數據字段加密,你是加了密了,加密后傳給對方是否要解密還是對方解密等等涉及的面很多。必需要有取舍。否則根本按期完不成功能交付。建議:
1) 對于面向互聯網普通大眾的系統,從根本上要控制認證和授權、數據加密保護和傳輸這兩個主要切入點。關鍵動作必須重新認證(不要信任session)。關鍵數據必須加密保存和傳輸,注意提醒那些還沉浸在MD5加密的人們,這個早就被破解了,更不要用自己的加密函數。面向互聯網普通大眾的系統還要重點考慮網絡攻擊(比如Ddos攻擊,這時候防火墻是解決不了的)。
2) 對于傳統渠道產品,比如支撐系統、經分系統等,因運營商有4A等類似單點登錄的統一認證系統,認證和授權可以適當充分信任4A等系統。更多的是從合法用戶的非法行為入手考慮,比如合法IP的刷機行為、合法用戶的盜權行為、合法用戶的信息泄漏行為(強化數據加密)。
先寫這些,感覺要寫的很多。后面再推出個(2)吧,重點談談持續集成、國內外優秀工具測試的實踐及分析我們的差距。……