在開發應用程式時,Live 單元測試會自動在背景執行受影響的單元測試,並即時呈現結果與程式碼覆蓋範圍。 當你修改程式碼時,即時單元測試會回饋你的變更如何影響現有測試,以及你新增的程式碼是否被一個或多個現有測試覆蓋。 這些回饋提醒你在修正錯誤或新增功能時,要撰寫單元測試。
當你使用即時單元測試來進行測試時,它會持續保存關於測試狀態的資料。 使用持久化資料讓即時單元測試能在動態執行測試時,因應程式碼變更提供卓越的效能。
Live 單元測試僅在 Visual Studio 企業版中提供,適用於針對 .NET Core 或 .NET Framework 的專案。
支援的測試框架
即時單元測試可搭配下表中三個熱門單元測試框架運作。 同時也展示了他們支援的最低版本的介面卡與框架。 單元測試框架皆可從 NuGet.org 取得。
| 測試架構 | Visual Studio 適配器最低版本 | Framework 最小版本 |
|---|---|---|
| xUnit.net | xunit.runner.visualstudio 版本 2.2.0-beta3-build1187 | xunit 1.9.2 |
| NUnit | NUnit3TestAdapter 版本 3.5.1 | NUnit 版本 3.5.0 |
| MSTest | MSTest.TestAdapter 1.1.4-preview | MSTest.TestFramework 1.0.5-preview |
如果你有較舊的基於 MSTest 的測試專案,參考 了 Microsoft.VisualStudio.QualityTools.UnitTestFramework,且不想換成較新的 MSTest NuGet 套件,建議升級到 Visual Studio 2019 或 Visual Studio 2017。
在某些情況下,你可能需要明確地還原專案參考的 NuGet 套件,即時單元測試才能運作。 您有兩個選擇:
- 透過明確建置解決方案來還原。 在 Visual Studio 頂層選單中選擇 「建置>重建解決方案 」。
- 在解決方案中還原套件。 右鍵點選解決方案,選擇 還原 NuGet 套件。
Configure
當你第一次啟動解決方案的即時單元測試時,設定精靈會讓你設定即時單元測試應該如何建置和執行測試。
當即時單元測試停止時,你也可以透過「 測試>即時單元測試>配置即時單元測試以求解決方案」來開啟設定精靈。
當 Live 單元測試執行時,會建立一個工作區,該工作區是原始儲存庫的副本。 Live 單元測試接著會將你在 Visual Studio 中未儲存的變更套用到工作區,執行建置、測試跑,並回報最新的程式碼覆蓋情況。
你首先應該透過精靈設定檔案的複製來源和複製地點。
儲存庫根
儲存庫根會指定將被複製的資料夾,以建立 Live Unit Test 工作區。 它應該是儲存庫的根目錄,也就是說,應該包含所有原始碼、二進位檔和工具。 若解決方案檔案不在儲存庫根目錄下,可能需要更改儲存庫根目錄。
工作區根
工作區根會指定 Live Unit Testing 存放該倉庫複製品的資料夾。 請注意顯示路徑過長的例外情況。 預設情況下,根節點會建立在你的主資料夾下。 不過舉例來說,如果你通常需要在 C 磁碟建立儲存庫,工作區根目錄可以調整成像 C:\lut\Repo。
指定排除的檔案
並非所有檔案都應該複製到 Live Unit Test 工作區。 在建置過程中產生的任何產物都應該被排除在複製之外,這樣一般建置就不會干擾 Live Unit Test 建置。 另外,一般 nuget restore 指令不應該干擾 Live Unit Testing nuget restore 指令。
預設情況下,Live 單元測試會排除以下兩種檔案模式之一:
- 對於 Git 倉庫, gitignore 檔案中指定的檔案不會被複製到 Live 單元測試工作區。
- 對於非 Git 軟體庫,基本的資料夾清單,如 bin/ 和 obj/,不會被複製到 Live Unit Testing 工作區。
對於較複雜的儲存庫,你可能需要指定自己的忽略檔案。 從精靈中選擇「<自訂>」選項。 選擇 「下一步」後,Live 單元測試在你完成精靈後建立的自訂忽略檔案內容就會出現。 是 lutignore 檔案。
備註
有些 Git 倉庫需要自訂的 lutignore 檔案,這是因為可以將即使被 gitignore 檔案忽略的文件也簽入 Git 倉庫。 如果沒有自訂 的 lutignore 檔案,Live Unit Testing 就無法複製這些檔案,這可能會導致建置失敗。
Lutignore 檔案結構
lutignore 檔案使用與 gitignore 檔案相同的格式。 它應該包含與建置過程中產生的資料夾或檔案相符的規則,避免被複製到工作區。 對於大多數預設專案範本,以下忽略檔案即可:
[Bb]in
[Oo]bj
# WILL NOT COPY ANY BIN AND OBJ FOLDERS TO THE LIVE UNIT TESTING WORKSPACE
如果你的倉庫只有一個建置資料夾,忽略檔案應該會列出該資料夾:
[Aa]rtifacts/
# WILL NOT COPY THE ARTIFACTS FOLDER TO THE LIVE UNIT TESTING WORKSPACE
如果你的資料庫在建構資料夾中包含其他工具,這些工具應該被排除在相符模式集合中:
[Aa]rtifacts/
![Aa]rtifacts/tools/
# WILL NOT COPY THE ARTIFACTS FOLDER TO THE LIVE UNIT TESTING WORKSPACE
# HOWEVER IT WILL COPY THE TOOLS SUBFOLDER THAT MIGHT CONTAIN TOOLS AND UTILITIES
建造選項
精靈設定頁面的第二部分是你設定建置選項的地方:
- 產生 PDB:為了加快建置速度,Live Unit Test 不會在建置時產生 PDB。 這些符號檔案使您能夠在測試失敗時檢視堆疊追蹤資訊。
- 使用多個 CPU 核心建置:預設情況下,Live 單元測試會使用多個 CPU 核心來執行建置,從而提升建置時間。 如果你的機器變慢,或是用多處理器無法建立解決方案,就不要選擇這個選項。
測試運行選項
精靈設定頁面的最後部分是設定測試執行選項的地方:
- 測試案例逾時:有些測試可能需要很長時間才能執行。 設定此欄位時,若任何測試超過特定時間,則自動中止執行。 考試可以自動取消。
- 使用多個處理器:預設情況下,即時單元測試會嘗試使用多個處理器來加速執行效能。 如果你的機器變慢或解決方案無法平行執行測試,就不要選擇這個選項。 例如,當多個測試嘗試從相同的檔案路徑寫入/讀取時,可能會發生這種情況。
更多配置
透過在 Visual Studio 頂層選單列選擇 工具>選項 來設定即時單元測試。
在 選項 面板中,展開 「所有設定>測試>即時單元測試 」區塊。
在 選項 對話框中,展開 「即時單元測試>通用 」區塊。
啟用即時單元測試(參見 啟動、暫停及停止即時單元測試)後,您可以選擇「 測試>即時單元測試>選項」再次開啟選項。
可配置選項包括:
當解決方案建置並除錯時,Live 單元測試是否會暫停。
當系統電池電量低於指定門檻時,Live 單元測試是否會暫停。
能夠刪除所有持久化的資料。 當即時單元測試表現不可預測或意外,暗示持久化資料損壞時,此功能非常有用。
即時單元測試程序能佔用的最大記憶體量。
寫入即時單元測試 輸出 視窗的資訊層級。
選項包括無日誌記錄(無日誌)、僅錯誤訊息(錯誤)、錯誤與資訊訊息(資訊,預設),或全細節(冗長)。
你也可以透過在即時單元測試輸出視窗中,將一個使用者層級環境變數設為1 來顯示詳細輸出。 然後重新啟動 Visual Studio。
若要將 Live Unit Testing 的詳細 MSBuild 日誌訊息擷取到檔案中,請將使用者層級的環境變數設定
LiveUnitTesting_BuildLog為包含該日誌的檔案名稱。
自訂你的建置版本以支援即時單元測試
對於更複雜的解決方案,可能需要進一步客製化配置。 例如,測試時可能不需要建立翻譯檔案。 為了加快建置速度,你可以用 Live Unit Test 停用轉譯檔建置。 你可以透過操作專案檔案來達成這個目標。
新增即時單元測試覆寫
如果你的解決方案需要自訂步驟來建置儀表(即時單元測試),而這些步驟在「一般」非儀表化建置中並非必需,你可以在專案或 .targets 檔案中加入程式碼,檢查 BuildingForLiveUnitTesting 屬性並執行建置前後的自訂步驟。
例如,你可以寫以下範例,新增另一個僅用於即時單元測試的目標:
<Target Name="GenerateNuGetPackages" BeforeTargets="AfterBuild" Condition="'$(BuildingForLiveUnitTesting)' == 'true'">
<Exec Command='"$(MSBuildThisFileDirectory)..\tools\GenPac" '/>
</Target>
你可以用這個 BuildingForLiveUnitTesting 屬性來停用一些不該執行的測試建置任務。 例如,即時單元測試會設定 <RunAnalyzers>false</RunAnalyzers> 停用測試分析器。
即時單元測試相依關係
有可能並非所有執行測試所需的檔案都被複製。 Live Unit Testing 會建立一個獨立的資料夾來執行測試。 這種安排允許在測試執行時進行建置,但並非所有建置資料夾的檔案都會複製到測試資料夾。
通常,您會基於以下兩個原因之一來新增測試相依性:
- 你的測試依賴於來源樹下的檔案。 例如,測試會檢查 resx 檔案的內容,或是讀取一些設定檔。
- 你的測試依賴於其所引用的某些函式庫。 舉例來說,一個測試執行了一個作為依賴項的可執行檔。
備註
測試相依必須存在於設定精靈中指定的 Repository Root 目錄中。
在這兩種情況下,Live 單元測試預設不會複製這些檔案,目的是為了減少執行測試時需要複製的檔案數量。 如果測試需要這些檔案,就必須用屬性 LiveUnitTestingTestDependency 明確指定。 舉例來說,假設我們有以下的佈局:
SRC/
CONSOLE_UTILITY/
TEST_PROJECT/
ARTIFACTS/
CONSOLE_UTILITY/NET472/DEBUG/
TEST_PROJECT/NET472/DEBUG/
預設情況下,當你用 Live Unit Test 建置這些專案時,它只會複製 Artifacts/Test_Project 到 test 資料夾。 若要將來源或console_utility加入測試資料夾,請將以下範例加入 test_project.csproj:
<LiveUnitTestingTestDependency Include=”$(RepoRoot)/Src/ConsoleUtility” />
<LiveUnitTestingTestDependency Include=”$(RepoRoot)/Artifacts/ConsoleUtility/net472/$(Configuration)/</LiveUnitTestingTestDependency” />
開始、暫停、停止
要啟用即時單元測試,請在 Visual Studio 頂層選單中選擇「 測試>即時單元測試>開始 」。 啟用即時單元測試時,即時 單元測試 選單上的選項會從單一項目「 開始」變成 「暫停 」和 「停止」:
暫停 會暫時暫停即時單元測試。
當即時單元測試暫停時,編輯器中不會顯示覆蓋率視覺化,但所有收集的資料都會被保留。 要繼續即時單元測試,請在即時單元測試選單中選擇繼續。 即時單元測試會完成必要的工作,追蹤暫停期間所做的所有編輯,並適當更新字形。
停止 會完全停止即時單元測試。 即時單元測試會丟棄所有收集到的資料。
如果你在不包含單元測試專案的解決方案中啟動即時單元測試,暫停與停止選項會出現在即時單元測試選單中,但即時單元測試並未啟動。 輸出視窗顯示一則訊息,開頭寫著:「本解決方案不參考任何支援的測試介面卡......」。
你隨時都可以暫時暫停或完全停止即時單元測試。 例如,如果你正在重構中,且知道測試會有一段時間無法正常運作,你可能會考慮採取此類措施。
包含與排除測試專案與測試方法
當你開始 Live Unit Testing 時,會出現 Live Unit Test 工具視窗,並提示你選擇想由 Live Unit Test 測試的測試集合。
對於較小的解決方案,單元測試執行時間非常短,選擇 「包含所有測試」,讓即時單元測試執行所有測試。
對於擁有多個測試專案的大型解決方案,你可以透過編輯播放清單來控制哪些專案和專案中的個別方法參與 Live 單元測試。 例如,如果你的解決方案包含數百個測試專案,你可以選擇一組目標測試專案參與即時單元測試。
你可以透過編輯即時單元測試播放清單來選擇 Live 單元測試應該執行什麼,這個功能就像 測試檔案總管裡的播放清單一樣。
有多種方式可以編輯 Live Unit Test 播放清單:
- 即時單元測試工具視窗
- 程式碼編輯器視窗
- 方案總管
- 在測試程式碼中以程式化方式
Live 單元測試會將包含/排除狀態儲存為使用者設定,並在解決方案關閉與重新開啟時記住。
即時單元測試工具視窗
你可以使用即時單元測試標籤的播放清單編輯器,將專案、命名空間或類別納入或排除執行。 在工具視窗中選擇 編輯播放清單 。
你可以選擇或清除樹狀檢視元素,以包含或排除測試。 舉例來說,如果你檢查單一測試,當有變更時,Live Unit Testing 會執行該測試。 如果你選擇一個類別,該類別中的所有測試都會執行,並且新增到該類別的測試也會執行。
程式碼編輯器視窗
你可以使用程式碼編輯器視窗來包含或排除個別測試方法。 在程式碼編輯器視窗中右鍵點擊測試方法的簽名或主體,並選擇以下選項之一:
- 即時單元測試>包含 <選定方法>
- 即時單元測試>排除 <選定方法>
- 即時單元測試>排除所有但<選定的方法>
方案總管
要選擇單元測試中的個別專案,啟動即時單元測試後,請依照以下步驟操作:
- 在 解決方案總管 中右鍵點擊該解決方案,選擇 「即時單元測試>排除 」以排除整個解決方案。
- 右鍵點擊你想包含在測試中的每個測試專案,並選擇 「即時單元測試>包含」。
在測試程式碼中以程式化方式
你可以套用這個 ExcludeFromCodeCoverageAttribute 屬性,程式化地排除方法、類別或結構,避免在即時單元測試中回報其覆蓋範圍。
請使用以下屬性排除個別方法,以將它們從 Live Unit Testing 中排除:
-
x單元:
[Trait("Category", "SkipWhenLiveUnitTesting")] -
NUnit:
[Category("SkipWhenLiveUnitTesting")] -
MSTest:
[TestCategory("SkipWhenLiveUnitTesting")]
使用以下屬性來排除整個測試組合,從即時單元測試中剔除:
-
x單元:
[assembly: AssemblyTrait("Category", "SkipWhenLiveUnitTesting")] -
NUnit:
[assembly: Category("SkipWhenLiveUnitTesting")] -
MSTest:
[assembly: TestCategory("SkipWhenLiveUnitTesting")]
檢視覆蓋範圍視覺化
啟用即時單元測試後,它會在 Visual Studio 編輯器中更新每一行程式碼,告訴你你所寫的程式碼是否被單元測試覆蓋,以及涵蓋它的測試是否通過。
下圖顯示了包含通過與失敗測試的程式碼行,以及未被測試涵蓋的程式碼行數。 帶有綠色「✓」的項目僅通過測試。 帶有紅色「x」的線條會被一個或多個未通過的測試覆蓋。 帶有藍色「➖」的線條不會被任何考試涵蓋。
當你修改程式碼編輯器中的程式碼時,即時單元測試覆蓋率視覺化會立即更新。 在處理編輯過程中,視覺化會改變,透過在通過、失敗及未覆蓋符號下方加入圓整計時器影像,以顯示資料非最新,如下圖所示。
獲取測試狀態資訊
將游標懸停在程式碼視窗中代表通過或失敗的符號上,您可以查看有多少測試命中該行。 要查看各測試的狀態,請選擇符號。
除了提供測試名稱和結果外,工具提示還能讓你重跑或除錯測試集合。 如果你在工具提示中選擇一個或多個測試,也可以只執行或除錯這些測試。 這個動作讓你能在不離開程式碼視窗的情況下除錯測試。
除錯時,除了觀察你可能已設定的斷點外,當除錯器執行 Assert 的方法回傳意外結果時,程式執行會暫停。
當你將滑鼠移到提示中失敗的測試上時,它會展開以提供更多失敗的資訊,如下圖所示。 要直接進入失敗測試,請在工具提示中按兩下。
當你進入失敗測試時,Live 單元測試會在方法簽名中視覺化標示出具備以下條件的測試:
- 通過 (以半滿的燒杯和綠色的「✓」表示)。
- 失敗 (以半滿的燒杯和紅色「🞩」表示)。
- 未參與即時單元測試(用半滿的燒杯和藍色「➖」表示)。
非測試方法不會用符號來識別。 下圖展示了所有四種方法類型。
診斷並修正測試失敗
從失敗的測試中,你可以輕鬆除錯產品程式碼、編輯,然後繼續開發你的應用程式。 因為即時單元測試是在背景執行,你不需要在除錯、編輯和繼續的循環中停止和重啟即時單元測試。
例如,前一張圖片中顯示的測試失敗,是因為測試方法錯誤地假設當非字母字元傳入System.Char.IsLower方法時,會返回true。 修正測試方法後,所有測試都應該通過。 你不必暫停或停止即時單元測試。
即時單元測試視窗
即時單元測試類似 於測試檔案總管,提供一個介面,讓你能執行、除錯測試並分析測試結果。 啟用即時單元測試時, 測試檔案總管 中單元測試的狀態會立即更新。 你不需要明確執行單元測試。
當未啟用或停止即時單元測試時, 即時單元測試 會顯示上次執行測試時的單元測試狀態。 重新啟動即時單元測試後,必須修改原始碼才能重新執行測試。
你可以在 Visual Studio 頂層選單中選擇「Test>Live Unit Test Start>」來啟動即時單元測試。 您也可以使用「視圖」>其他視窗>中的「即時單元測試視窗」來開啟即時單元測試視窗。
你可能會注意到在 即時單元測試 視窗中,有些測試會淡出。例如,當你停止並重新啟動 Live Unit Testing 時,Live Unit Test 視窗會淡出所有測試,如下圖所示。
模糊的測試結果顯示該測試並非最新的 Live Unit 測試的一部分。 只有在偵測到測試變更或其相依關係時,測試才會執行。 如果沒有變化,就能避免不必要的測試。 在這個案例中,灰色的測試結果仍然是「最新的」,雖然它並非最新一次測試的一部分。
你可以透過修改程式碼來重跑任何看起來已經消失的測試。
即時單元測試自動執行並更新測試結果,與明確從 測試檔案總管執行測試之間存在一些差異。 這些差異包括:
- 從 測試總管 視窗執行或除錯測試時,會執行一般的二進位檔。 即時單元測試執行已帶儀器的二進位檔。
- 即時單元測試不會建立新的應用程式域來執行測試。 取而代之的是,它會從預設網域執行測試。 從 測試檔案總管 視窗執行的測試確實會建立一個新的應用程式域。
- 即時單元測試會在每個測試組件中依序執行測試。 在 測試檔案總管 視窗中,你可以選擇同時執行多個測試。
取消即時單元測試的執行
Live 單元測試會在你修改程式碼時持續執行測試。 如果執行進行中且你做了更多程式碼變更,Live 單元測試會在等待第一次執行完成時排隊再執行一次。
每次儲存檔案時,Live Unit Testing 會取消正在執行的第一個測試,並立即排程等待中的測試。 這個流程有助於處理第一次跑很久才完成的情況。