开发应用程序时,Live Unit Testing 会自动在后台运行任何受影响的单元测试,并实时显示结果和代码覆盖率。 修改代码时,Live Unit Testing 提供有关更改如何影响现有测试以及你添加的新代码是否由一个或多个现有测试涵盖的反馈。 此反馈提醒你在进行 bug 修复或添加新功能时编写单元测试。
对测试使用 Live Unit Testing 时,它会保留有关测试状态的数据。 使用持久化数据,Live Unit Testing 可以在动态运行测试以响应代码更改时提供卓越的性能。
Live Unit Testing 仅适用于面向 .NET Core 或 .NET Framework 的项目的 Visual Studio 企业版。
支持的测试框架
Live Unit Testing 适用于下表中列出的三种常用单元测试框架。 还显示了其适配器和框架的最低支持版本。 单元测试框架可从 NuGet.org 获取。
| 测试框架 | Visual Studio 适配器最低版本 | 框架最低版本 |
|---|---|---|
| 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 |
如果具有引用 Microsoft.VisualStudio.QualityTools.UnitTestFramework 的较旧的基于 MSTest 的测试项目,并且不想移动到较新的 MSTest NuGet 包,请升级到 Visual Studio 2019 或 Visual Studio 2017。
在某些情况下,可能需要显式还原项目引用的 NuGet 包,以便 Live Unit Testing 正常工作。 可以使用两个选项:
- 通过执行解决方案的显式生成进行还原。 在顶级 Visual Studio 菜单上选择“生成>重新生成解决方案”。
- 还原解决方案中的包。 右键单击解决方案,然后选择“ 还原 NuGet 包”。
Configure
首次启动解决方案的 Live Unit Testing 时,设置向导允许你配置 Live Unit Testing 应生成和运行测试的方式。
在停止实时单元测试后,还可以通过转到“测试>实时单元测试>为解决方案配置实时单元测试”来打开设置向导。
运行 Live Unit Testing 时,它会创建一个工作区,该工作区是原始存储库的副本。 然后,Live Unit Testing 会将 Visual Studio 中所做的任何未保存的更改应用到工作区、执行生成、执行测试运行以及报告最新的代码覆盖率。
应使用向导配置的第一件事是应从何处复制文件,以及应将其复制到何处。
存储库根目录
存储库根指定将复制以创建 Live Unit Testing 工作区的文件夹。 它应该是存储库的根文件夹,即它应包含所有源、二进制文件和工具。 如果解决方案文件不在存储库根目录下,可能需要更改存储库根目录。
工作区根目录
工作区根目录指定了用于保留 Live Unit Testing 存储库克隆的文件夹。 注意是否有提示路径过长的异常。 默认情况下,根在主文件夹下创建。 但是,例如,如果通常需要在驱动器 C 下创建存储库,则可以将工作区根目录调整为 C:\lut\Repo 等内容。
指定排除的文件
并非所有文件都应复制到 Live Unit Testing 工作区。 生成过程中生成的任何构件都应从复制中排除,以便常规构建不会干扰 Live Unit Testing 测试构建。 此外,常规 nuget restore 命令不应干扰 Live Unit Testing nuget restore 命令。
默认情况下,Live Unit Testing 排除以下两种文件模式之一:
- 对于 Git 存储库, gitignore 文件中指定的文件不会复制到 Live Unit Testing 工作区。
- 对于非 Git 存储库,不会将文件夹(如 bin/ 和 obj/)的基本列表复制到 Live Unit Testing 工作区。
对于更复杂的存储库,可能需要指定自己的忽略文件。 从向导中选择“<自定义>”选项。 选择 “下一步”后,将显示 Live Unit Testing 在完成向导后创建的自定义忽略文件的内容。 这是 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 Testing 不会在生成过程中生成 PDB。 这些符号文件可以帮助您在测试失败时查找堆栈跟踪。
- 使用多个 CPU 核心进行生成:默认情况下,Live Unit Testing 使用多个 CPU 核心执行生成,从而提高生成时间。 如果计算机速度变慢,或者解决方案无法使用多个处理器生成,请不要选择此选项。
测试运行选项
向导配置页的最后一部分是设置测试运行选项的位置:
- 测试用例超时:某些测试可能需要很长时间才能运行。 设置此字段后,如果任何测试超过特定时间持续时间,将自动中止运行。 可以自动取消测试。
- 使用多个处理器:默认情况下,Live Unit Testing 会尝试使用多个处理器来加快运行性能。 如果计算机速度变慢,或者解决方案无法并行运行测试,请不要选择此选项。 例如,如果多个测试尝试从同一文件路径写入/读取,则可能会出现这些情况。
更多配置
通过在顶级 Visual Studio 菜单栏上选择 “工具>选项 ”来配置 Live Unit Testing。
在 “选项 ”窗格中,展开“ 所有设置>测试>Live Unit Testing ”部分。
在 “选项 ”对话框中,展开“ Live Unit Testing>常规 ”部分。
启用 Live Unit Testing 后(请参阅 “开始”、“暂停”和“停止 Live Unit Testing”),可以通过选择“ 测试>Live Unit Testing>选项”再次打开选项。
可配置的选项包括:
生成和调试解决方案时 Live Unit Testing 是否暂停。
当系统的电池电量低于指定阈值时,Live Unit Testing 是否暂停。
能够删除所有持久化数据。 当 Live Unit Testing 以不可预知或意外的方式进行时,此功能非常有用,这表明持久化的数据已损坏。
Live Unit Testing 进程可以使用的最大内存量。
写入到“实时单元测试 输出 ”窗口的信息级别。
选项包括不记录(无)、仅错误消息(错误)、错误和信息性消息(信息,默认值)或所有详细信息(详细)。
还可以通过将值 1 分配给名为 “用户级环境变量” 来在 Live Unit Testing 输出窗口中显示详细
VS_UTE_DIAGNOSTICS。 然后重启 Visual Studio。若要捕获文件中 Live Unit Testing 的详细 MSBuild 日志消息,请将
LiveUnitTesting_BuildLog用户级环境变量设置为文件的名称以包含日志。
自定义 Live Unit Testing 的构建
对于更复杂的解决方案,可能需要进一步自定义构建。 例如,在测试运行期间,可能不需要生成翻译文件。 若要加快生成速度,可以使用 Live Unit Testing 禁用翻译文件生成。 可以通过操作项目文件来实现该操作。
添加 Live Unit Testing 替代
如果您的解决方案需要为检测(实时单元测试)构建特定的自定义步骤,而这些步骤在“常规”非检测构建中不需要,您可以将代码添加到项目或 .targets 文件中,用于检查 BuildingForLiveUnitTesting 属性,并执行自定义预/后生成步骤。
例如,可以编写以下示例来添加仅针对 Live Unit Testing 执行的另一个目标:
<Target Name="GenerateNuGetPackages" BeforeTargets="AfterBuild" Condition="'$(BuildingForLiveUnitTesting)' == 'true'">
<Exec Command='"$(MSBuildThisFileDirectory)..\tools\GenPac" '/>
</Target>
可以使用该 BuildingForLiveUnitTesting 属性来禁用某些不应为测试生成执行的任务。 例如,Live Unit Testing 设置为 <RunAnalyzers>false</RunAnalyzers> 禁用测试分析器。
Live Unit Testing 测试依赖项
可能并非所有运行测试所需的文件都已被复制。 Live Unit Testing 创建一个单独的文件夹,用于运行测试。 这种排列允许在测试运行时进行生成,但生成文件夹中的所有文件都不会复制到测试文件夹。
通常,出于以下两个原因之一添加测试依赖项:
- 你的测试依赖于源代码树中的文件。 例如,测试会检查 resx 文件的内容,或者可能读取一些配置文件。
- 你的测试依赖于所引用的某些库。 例如,测试运行作为依赖项生成的可执行文件。
注释
测试依赖项必须存在于安装向导中指定为 存储库根 目录的目录中。
在这两种情况下,默认情况下,Live Unit Testing 不会复制这些文件,目的是最大程度地减少必须复制以运行测试的文件数。 如果需要测试运行,则需要使用 LiveUnitTestingTestDependency 属性显式指定这些文件。 例如,假设我们具有以下布局:
SRC/
CONSOLE_UTILITY/
TEST_PROJECT/
ARTIFACTS/
CONSOLE_UTILITY/NET472/DEBUG/
TEST_PROJECT/NET472/DEBUG/
默认情况下,使用 Live Unit Testing 生成这些项目时,它仅复制到 Artifacts/Test_Project 测试文件夹。 若要将源或console_utility添加到测试文件夹,请将以下示例添加到 test_project.csproj:
<LiveUnitTestingTestDependency Include=”$(RepoRoot)/Src/ConsoleUtility” />
<LiveUnitTestingTestDependency Include=”$(RepoRoot)/Artifacts/ConsoleUtility/net472/$(Configuration)/</LiveUnitTestingTestDependency” />
启动、暂停和停止
若要启用 Live Unit Testing,请在顶级 Visual Studio 菜单上选择“ 测试>实时单元测试>开始 ”。 启用 Live Unit Testing 后,Live Unit Testing 菜单上可用的选项将从单个项“ 开始”更改为 “暂停 ”和 “停止”:
暂停 暂时暂停 Live Unit Testing。
暂停实时单元测试时,覆盖率可视化效果不会显示在编辑器中,但收集的所有数据都会保留。 若要恢复 Live Unit Testing,请在“Live Unit Testing”菜单上选择“继续”。 Live Unit Testing 执行必要的工作,以赶上暂停期间所做的所有编辑,并相应地更新标记。
停止 完全停止 Live Unit Testing。 Live Unit Testing 会丢弃它收集的数据。
如果在不包含单元测试项目的解决方案中启动 Live Unit Testing,“ 暂停 ”和 “停止 ”选项会显示在 Live Unit Testing 菜单上,但 Live Unit Testing 不会启动。 “ 输出 ”窗口显示一条开始的消息,“此解决方案未引用任何受支持的测试适配器...”。
随时可以暂时暂停或完全停止 Live Unit Testing。 例如,如果你正在进行重构,并且知道测试会在一段时间内中断,这时你可能需要采取这些措施。
包括和排除测试项目和测试方法
启动 Live Unit Testing 时,将显示“Live Unit Testing”工具窗口,并提示你选择要通过 Live Unit Testing 测试的测试集。
对于单元测试运行时间很少的较小解决方案,请选择 “包括所有测试”,使 Live Unit Testing 运行所有测试。
对于包含许多测试项目的较大解决方案,可以通过编辑播放列表来控制项目中哪些项目和单个方法参与 Live Unit Testing。 例如,如果你有一个包含数百个测试项目的解决方案,则可以选择一组有针对性的测试项目来参与 Live Unit Testing。
通过编辑实时单元测试播放列表(这个功能与测试资源管理器中的播放列表类似)来选择应该运行的实时单元测试。
可通过多种方式编辑 Live Unit Testing 播放列表:
- Live Unit Testing 工具窗口
- 代码编辑器窗口
- 解决方案资源管理器
- 以编程方式在测试代码中
Live Unit Testing 将 include/exclude 状态保存为用户设置,并在解决方案关闭并重新打开时记住它。
Live Unit Testing 工具窗口
可以使用 Live Unit Testing 选项卡的播放列表编辑器来包括或排除执行中的项目、命名空间或类。 在工具窗口中选择 “编辑播放列表 ”。
可以选择或清除树视图元素以包括或排除测试。 例如,如果检查单个测试,Live Unit Testing 会在更改时运行它。 如果选择类,该类中的所有测试都会运行,并且添加到该类的所有新测试也会运行。
代码编辑器窗口
可以使用代码编辑器窗口来包括或排除单个测试方法。 在代码编辑器窗口中右键单击测试方法的签名或正文,然后选择以下选项之一:
- Live Unit Testing>包括 <所选方法>
- Live Unit Testing>排除 <所选方法>
- Live Unit Testing>排除除所选方法外 <的所有方法>
解决方案资源管理器
若要在单元测试中选择单个项目,请在启动 Live Unit Testing 后执行以下步骤:
- 右键单击 解决方案资源管理器 中的解决方案,然后选择“ Live Unit Testing>Exclude ”以排除整个解决方案。
- 右键单击要包含在测试中的每个测试项目,然后选择 “Live Unit Testing>Include”。
在测试代码中通过编程实现
可以应用特性 ExcludeFromCodeCoverageAttribute 以编程方式排除那些不在 Live Unit Testing 中报告其覆盖范围的方法、类或结构。
使用以下属性从 Live Unit Testing 中排除各个方法:
-
xUnit:
[Trait("Category", "SkipWhenLiveUnitTesting")] -
NUnit:
[Category("SkipWhenLiveUnitTesting")] -
MSTest:
[TestCategory("SkipWhenLiveUnitTesting")]
使用以下属性从 Live Unit Testing 中排除整个测试程序集:
-
xUnit:
[assembly: AssemblyTrait("Category", "SkipWhenLiveUnitTesting")] -
NUnit:
[assembly: Category("SkipWhenLiveUnitTesting")] -
MSTest:
[assembly: TestCategory("SkipWhenLiveUnitTesting")]
查看覆盖范围可视化效果
启用 Live Unit Testing 后,它会更新 Visual Studio 编辑器中的每一行代码,以显示你编写的代码是否由单元测试涵盖,以及覆盖它的测试是否通过。
下图显示了通过和失败测试的代码行,以及测试未涵盖的代码行。 通过测试的行显示为绿色“√”。 带有红色“x”的行由一个或多个失败的测试覆盖。 未被任何测试涵盖的行显示蓝色“➖”符号。
在代码编辑器中修改代码时,实时单元测试覆盖率可视化效果会立即更新。 在处理编辑过程中,可视化效果将更改,以指示数据未更新至最新,如下图所示:在通过、失败和未覆盖的符号下添加一个圆形计时器图像。
获取有关测试状态的信息
将鼠标悬停在代码窗口中通过或失败的符号上,可以看到有多少测试覆盖了该行。 若要查看各个测试的状态,请选择符号。
除了提供测试的名称和结果之外,工具提示还允许你重新运行或调试测试集。 如果在工具提示中选择一个或多个测试,则还可以仅运行或调试这些测试。 此作允许你调试测试,而无需离开代码窗口。
调试时,除了观察可能已设置的任何断点之外,当调试器执行 Assert 返回意外结果的方法时,程序执行会暂停。
将鼠标悬停在工具提示中的失败测试上时,它会展开以提供有关失败的详细信息,如下图所示。 若要直接转到失败的测试,请在工具提示中双击它。
转到失败的测试时,Live Unit Testing 在方法签名中直观地指示具有以下测试:
- 通过(由半满的烧杯和绿色“✓”指示)。
- 失败(由半满的烧杯和红色“🞩”指示)。
- 不参与实时单元测试(由半满的烧瓶和蓝色“➖”表示)。
未用符号标识的方法不是测试方法。 下图说明了所有四种类型的方法。
诊断并更正测试失败
从失败的测试中,可以轻松调试代码示例、进行编辑并继续开发应用程序。 由于 Live Unit Testing 在后台运行,因此无需在调试、编辑和继续周期期间停止和重启 Live Unit Testing。
例如,上图中显示的测试失败是由于测试方法中的一个错误假设引起的,即在将非字母字符传递给该方法时,它会返回true。 更正测试方法后,所有测试都应通过。 无需暂停或停止 Live Unit Testing。
实时单元测试窗口
Live Unit Testing(类似于 测试资源管理器)提供了一个界面,可用于运行和调试测试和分析测试结果。 启用 Live Unit Testing 后, 测试资源管理器 中的单元测试状态将立即更新。 无需显式运行单元测试。
如果未启用或停止 Live Unit Testing,Live Unit Testing 将在上次运行测试时显示单元测试的状态。 重启 Live Unit Testing 后,需要更改源代码才能重新运行测试。
可以通过在顶级 Visual Studio 菜单上选择“测试>实时单元测试开始”来启动>。 您还可以通过视图>菜单中的其他窗口打开实时单元测试窗口。
你可能会注意到,在 “Live Unit Testing ”窗口中,某些测试已淡出。例如,当你停止和重启 Live Unit Testing 时, Live Unit Testing 窗口会淡出所有测试,如下图所示。
淡出测试结果表示测试不是最新 Live Unit Test 运行的一部分。 仅当检测到对测试的更改或测试的依赖项时,才会运行测试。 如果没有更改,则避免不必要的运行测试。 在这种情况下,灰显测试结果仍为“最新”,尽管这不是最新运行的一部分。
可以通过更改代码来重新运行显示为淡化的任何测试。
Live Unit Testing 自动运行和更新测试结果以及从 测试资源管理器显式运行测试之间存在一些差异。 这些差异包括:
- 从 “测试资源管理器” 窗口运行或调试测试会运行常规二进制文件。 Live Unit Testing 运行检测的二进制文件。
- Live Unit Testing 不会创建新的应用程序域来运行测试。 而是从默认域运行测试。 从 “测试资源管理器” 窗口运行的测试会创建新的应用程序域。
- Live Unit Testing 按顺序在每个测试程序集中运行测试。 在 “测试资源管理器” 窗口中,可以选择并行运行多个测试。
取消 Live Unit Testing 测试运行
每当进行任何代码更改时,Live Unit Testing 将持续运行测试。 如果在运行中并且您进行更多代码更改,Live Unit Testing 会在等待第一次运行完成时排队另一个运行。
每当保存文件时,Live Unit Testing 都会取消第一次运行,并立即计划排队的运行。 此过程可帮助完成首次运行需要很长时间才能完成的方案。