最近開始接觸白盒測試,開發同事對OpenCover(開源C#代碼覆蓋率統計工具)、ReportGenerator(將XML報告轉換成HTML的工具)二次開發出一個代碼覆蓋率的工具。下面基於該工具,記錄對OpenCover、ReportGenerator等的理解。
未使用OpenCover時,被測程序的正常運行流程:
使用OpenCover、ReportGenerator后,被測程序的運行流程:
OpenCover中的Profiler啟動運行被測程序的程序或服務——>運行被測程序——>得到運行結果同時,也得到xml覆蓋率結果——>ReportGenerator將xml轉成HTML
——>命令行調用OpenCover.Console.exe——>使用SentrySdk收集崩潰報告——>解析命令行中傳入的參數(被測程序路徑、要打印使用說明、是否啟動服務、過濾信息等)
——>處理過濾器信息,如果命令行中未傳-filter參數,則默認匹配分析所有的類和方法——>創建性能計數器?
——>得到輸出xml報告的全路徑——>初始化封裝了注入框架依賴的容器——>創建文件句柄,后續將覆蓋率信息寫入文件中。如果已經存在覆蓋率xml文件,則合並
——>啟動覆蓋率分析進程。注冊分析器,調用OpenCover.Profiler.dll——>啟動被測程序——>
該工具使用及主要實現流程:(以測試站點程序為例)
——>配置好OpenCover、ReportGenerator、被測程序的路徑、IIS Express config的路徑
——>執行的時候就根據配置好的參數執行命令,即相當於在cmd中執行:
H:\白盒測試\Debug\Opencover\OpenCover.Console.exe -target:"C:\Program Files (x86)\IIS Express\iisexpress.exe" -targetdir:"D:\被測站點\xxx.xxx.com\bin" -targetargs:"/site:xxx_bh.xxx.com /config:\"C:\Users\ym\Documents\IISExpress\config\applicationhost.config\"" -register:ym -output:"H:\白盒測試\xml_ym\xxx_bh.xxx.com\xxx_bh.xxx.com.xml"
——>此時IIS Express已經啟動,訪問在通過IIS Express配置的站點,開始測試。
——>測試完成后,退出IIS Express,生成xml文件。
——>使用ReportGenerator生成HTML文檔,相當於在cmd中執行命令:
H:\白盒測試\Debug\ReportGenerator\ReportGenerator.exe -reports:H:\白盒測試\xml\白盒測試.xml -targetdir:H:\白盒測試\xml\html
關於OpenCover:
OpenCover是用於.NET 2.0及以上應用程序的代碼覆蓋的開源命令行工具。OpenCover使用PDB文件提供序列信息,確定哪行代碼與每行源代碼相關聯,然后檢測每個序列點以記錄命中。因此必須要有的是PDB文件以及可執行文件和程序集,應該在調試模式下構建測試中的應用程序。如果未找到PDB文件,則不會收集任何覆蓋數據。
使用COM(組件對象模型)開發,profiler部分使用c++,
OpenCover使用mono.Cecil來分析分支或IL以確定在何處檢測代碼。
OpenCover在開始時要考慮的指標是:
- 聲明范圍即已涵蓋的行數。
- 方法覆蓋范圍,即涵蓋了哪些方法。
- 分支覆蓋范圍即采取了哪些分支。這與圈復雜度有關
OpenCover基本用法(命令行參數): -target: 應用程序可執行文件或服務名稱的路徑 (我的理解:將被測程序運行起來的程序或服務。網上帖子中,大多用的NUnit。本文例子用的是IIS Express) -filter: 應用於選擇性地包括或排除coverage結果中的程序集和類的過濾器列表 (默認選擇所有的類和方法)
使用PartCover語法,在哪里(+|-)[Assembly-Filter]Type-Filter
。
例如,+[Open*]*
包括以Open開頭的程序-[*]Core.*
集中的所有類型,排除Core命名空間中的所有類型,而不管程序集如何。
如果未提供過濾器,+[*]*
則會自動應用默認的包含過濾器。 -output: 輸出XML文件的路徑,如果為空,則將在當前目錄中創建results.xml -register [:user] - 注冊和取消注冊代碼覆蓋率分析器 -targetargs: - 要傳遞給目標進程的參數(可指定被測程序的路徑) -targetdir: - 目標目錄的路徑或PDB文件的備用路徑 (如果-targetargs 已經指定了被測程序的路徑,那么這里可作為查找PDB文件的依據。本文例子則作為查找PDB文件的路徑)
用法:https://github.com/OpenCover/opencover/wiki/Usage
文檔:https://github.com/opencover/opencover/blob/master/main/OpenCover.Documentation/Usage.pdf
參考:http://www.cnblogs.com/binyao/category/477233.html
http://www.cnblogs.com/tylerzhou/p/9076386.html
http://blog.alantsai.net/posts/2017/01/devopsseries-opencover-intro
https://www.codeproject.com/Articles/677691/Getting-code-coverage-from-your-NET-testing-using
什么是IIS Express:
一個兼具Visual Studio的ASP.NET開發服務器和Windows的IIS Web服務器功能的輕量級web服務器。
具體描述:https://stackify.com/what-is-iis-express/
配置:https://blog.csdn.net/zhangjk1993/article/details/36671105
為什么用IIS Express:
文檔中有這么一段描述:
Running against IIS Normally I’d suggest running against IISEXPPRESS as I think it is easier to automate. However for those who really want to run against a full blown IIS then the following instructions (supplied by a user) will hopefully suffice. “The trick is to start OpenCover to run the w3wp.exe process in debug mode e.g. OpenCover.Console.exe -target:C:\Windows\System32\inetsrv\w3wp.exe -targetargs:-debug -targetdir:C:\Inetpub\wwwwoot\MyWebApp\bin\ -filter:+[*]* -register:user There are some prerequisites though: 1.All applications running under the site must make use of the same app pool; you'll get errors in the EventLog otherwise. 2.inetserver needs to be stopped, before starting w3wp.exe in debug mode. You can use the following command: net stop w3svc /y After testing/code coverage completion you can close the w3wp.exe process and start the inetserver again: net start w3svc This procedure was tested on a Win2008 machine with IIS7.5” You can also run multiple OpenCover instances against separate IIS sites by using the –s option when running IIS to choose the siteid e.g. OpenCover.Console.exe -target:C:\Windows\System32\inetsrv\w3wp.exe -targetargs:"-debug -s 1" -targetdir:%WebSite_Path% -filter:+[*]* -register:user -output:%CoverageResult_Path% Then you can use ReportGenerator to merge the coverage results.
大致意思就是用IIS Express更方便。
而如果要啟動完整的IIS,那就要:
1)在調試模式下運行被測程序並啟動OpenCover(將代碼構建到調試模式獲取PDB文件。或者直接獲取源代碼)
2)所有在站點下運行的應用程序都必須使用相同的應用程序池;否則,會報錯
3)在調試模式下啟動被測程序前,需要停止intserver(PS:intserver可能指的是啟動被測程序的服務吧。)
而結合實際需求,雖然也可以直接往-target傳參為IIS的啟動程序來進行監控測試情況,但是IIS還部署了其他非測試站點,會相互影響。所以實際應用還是采用IIS Express,每個測試人員部署自己的IIS Express,而不會相互影響。
關於PDB文件:
PDB是Program Data Base 的縮寫。顧名思義,它是一個存儲庫(持久性存儲,如數據庫),用於維護在調試模式下運行程序所需的信息。它包含調試代碼時所需的許多重要相關信息(在Visual Studio中),例如,在您希望調試器在Visual Studio中中斷的位置插入斷點。
這就是為什么如果*.pdb
從調試文件夾中刪除文件,Visual Studio很多次都無法達到斷點的原因。Visual Studio調試器還能夠通過文件的幫助告訴您堆棧跟蹤中發生異常的代碼文件的精確行號*.pdb
。因此,有效的pdb文件在調試程序時對開發人員來說真的很有用。
通常,建議不要排除*.pdb
文件的生成。從生產發布的角度來看,您應該做的是創建pdb文件,但不要將它們發送到產品安裝程序中的客戶站點。將所有生成的PDB文件保留在符號服務器上,以備將來可以使用/引用它。特別適用於調試進程崩潰等問題的情況。當您開始分析故障轉儲文件時,如果*.pdb
未保留在構建過程中創建的原始文件,則Visual Studio將無法確定導致崩潰的確切代碼行。
如果您仍想*.pdb
為任何版本完全禁用文件生成,請轉到項目屬性 - >構建選項卡 - >單擊Advanced按鈕 - > none
從“調試信息”下拉框中選擇 - >按OK下面的快照中所示。
https://blogs.msdn.microsoft.com/vcblog/2016/02/08/whats-inside-a-pdb-file/
https://tpodolak.com/blog/2017/10/12/net-core-calculating-code-coverage-opencover-windows/
http://www.cnblogs.com/itech/archive/2011/08/15/2136522.html
https://blog.csdn.net/feihe0755/article/details/54233714
使用ReportGenerator 將xml生成HTML報告:
ReportGenerator用於將OpenCover,PartCover,Visual Studio或NCover生成的XML報告轉換為各種格式的友好可讀報告。
使用指南可以在其主頁上找到,最有用的命令是(命令行參數):
- -reports: - 應該解析的覆蓋率報告,分號分隔,允許使用通配符
- -targetdir: - 應保存生成的報告的目錄
- -sourcedirs:[;] [;] - 包含相應源代碼的目錄,可選,分號分隔
- -classfilters:<(+ | - )filter> [; <(+ | - )filter>] [; <(+ | - )filter>] - 報表中應包含或排除的類列表,可選,通配符被允許。
如下圖,為報告部分截圖,包含語句覆蓋和分支覆蓋情況。點擊相應的頁面,會進入對應程序,可看到具體覆蓋到哪一行代碼。
代碼覆蓋詳情,綠色表示完全覆蓋,橙色表示該行代碼還有分支未覆蓋到,紅色則未覆蓋。
補充:
1、如果是測試Windows服務的覆蓋率:
1)執行如下命令啟動服務:
G:\Opencover所在路徑\OpenCover.Console.exe -service:byname -target:安裝好的服務名 -register:ym -output:H:\白盒測試保存路徑\xxx\xxx.xml
2)測試完畢后,正常關閉服務,則可收集覆蓋數據。
https://github.com/OpenCover/opencover/wiki/Service-Support
FAQ:
1)若提示
原因有三: (1)未走到相關代碼
(2)缺少對應的pdb文件
(3)未正確注冊Profiler,添加參數-register:賬號名
參考資料:https://www.cnblogs.com/tylerzhou/p/9076537.html
https://www.cnblogs.com/SivilTaram/p/vs_opencover_unit_coverage.html