应测试跨平台应用,因为它们将在现实世界中使用,以提高其质量、可靠性和性能。 应在应用上执行许多类型的测试,包括单元测试、集成测试和用户界面测试。 单元测试是最常见的形式,对于构建高质量应用至关重要。
单元测试采用应用的小单元(通常是方法),将其与代码的其余部分隔离,并验证其行为是否按预期方式。 其目标是检查每个功能单元是否按预期执行,以便错误不会在整个应用中传播。 在发生 bug 的位置检测 bug,比在次要故障点位置间接观察 bug 造成的影响更为有效。
单元测试通常应使用 arrange-act-assert 模式:
| Step | Description |
|---|---|
| Arrange | 初始化对象并设置传递给受测方法的数据的值。 |
| Act | 使用所需参数调用受测方法。 |
| Assert | 验证所测试方法的作是否按预期方式运行。 |
此模式可确保单元测试可读、自描述和一致。
单元测试是软件开发工作流不可或缺的一部分时,对代码质量的影响最大。 单元测试可以充当应用的设计文档和功能规范。 一旦编写了方法,就应该编写单元测试来验证该方法响应标准、边界和不正确输入数据情况的行为,并检查代码做出的任何显式或隐式假设。 或者,如果使用测试驱动开发,则会在代码之前编写单元测试。
Important
单元测试对回归非常有效。 也就是说,功能曾经正常工作,但被错误的更新所干扰。
对于 .NET MAUI 应用,建议使用 xUnit 测试框架。
将 xUnit 测试添加到 .NET MAUI 解决方案
若要将 xUnit 测试添加到 .NET MAUI 解决方案,请执行以下作之一:
使用 Visual Studio 向解决方案添加新 的 xUnit 测试项目 。
OR
使用 .NET CLI 创建新的 xUnit 测试项目并将其添加到解决方案。 有关详细信息,请参阅 使用 dotnet 测试和 xUnit 在 .NET 中对 C# 进行单元测试。
xUnit 测试项目的项目文件 (.csproj) 将类似于以下示例:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<IsPackable>false</IsPackable>
<IsTestProject>true</IsTestProject>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="coverlet.collector" Version="6.0.2" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.12.0" />
<PackageReference Include="xunit" Version="2.9.2" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.8.2" />
</ItemGroup>
<ItemGroup>
<Using Include="Xunit" />
</ItemGroup>
</Project>
生成 $(TargetFramework) 属性指定测试项目的目标框架。 这是计算机上安装的最新版本的 .NET。
该 xunit 包包含测试框架本身的子包,以及检测单元测试常见问题的 Roslyn 分析器。
xunit.runner.visualstudio在 Visual Studio 和dotnet test命令中运行单元测试需要和Microsoft.NET.Test.Sdk包。 包 coverlet.collector 允许收集代码覆盖率。 如果不打算收集代码覆盖率,可以删除此包引用。 有关单元测试的代码覆盖率的详细信息,请参阅 使用代码覆盖率进行单元测试。
有两种用于构建应用进行单元测试的主要方法:
- 单元测试的代码位于 .NET MAUI 类库项目中。
- 单元测试的代码位于 .NET MAUI 应用项目中。
每个方法都需要特定的配置。
配置用于单元测试的 .NET MAUI 类库项目
使用此方法时,要进行单元测试的代码位于 .NET MAUI 类库项目中,该项目由 .NET MAUI 应用项目使用。 若要针对 .NET MAUI 类库编写单元测试,需要更新项目使用的目标框架。 这可以通过将 xUnit 测试项目文件 (.csproj) 中的生成属性的值$(TargetFramework)添加到 $(TargetFrameworks) .NET MAUI 类库项目文件中的生成属性来实现:
<TargetFrameworks>net9.0;net9.0-android;net9.0-ios;net9.0-maccatalyst</TargetFrameworks>
在此示例中,已将值 net9.0 添加到 $(TargetFrameworks) .NET MAUI 类库项目文件中的生成属性。
然后,必须从 xUnit 测试项目添加对 .NET MAUI 类库项目的引用。
配置用于单元测试的 .NET MAUI 应用项目
使用此方法时,要进行单元测试的代码位于 .NET MAUI 应用项目中。 若要针对 .NET MAUI 应用项目编写单元测试,需要更新项目使用的目标框架。 这可以通过将 xUnit 测试项目文件 (.csproj) 中的生成属性的值$(TargetFramework)添加到 $(TargetFrameworks) .NET MAUI 应用项目文件中的生成属性来实现:
<TargetFrameworks>net9.0;net9.0-android;net9.0-ios;net9.0-maccatalyst</TargetFrameworks>
在此示例中,已将值 net9.0 添加到 $(TargetFrameworks) .NET MAUI 应用项目文件中的生成属性。
还需要修改 .NET MAUI 应用项目,以便它不会为 xUnit 测试项目使用的目标框架输出可执行文件。 这可以通过将条件添加到 $(OutputType) .NET MAUI 应用项目文件中的生成属性来实现:
<OutputType Condition="'$(TargetFramework)' != 'net9.0'">Exe</OutputType>
在此示例中,.NET MAUI 应用项目仅在目标框架不是 net9.0时生成可执行文件。
然后,必须从 xUnit 测试项目添加对 .NET MAUI 应用项目的引用。
编写单元测试
xUnit 支持两种类型的单元测试:
| Testing type | Attribute | Description |
|---|---|---|
| Facts | Fact |
始终为 true 的测试,用于测试固定条件。 |
| Theories | Theory |
只对特定数据集成立的测试。 |
单元测试应放置在 xUnit 测试项目中,并使用或[Theory]属性进行[Fact]修饰。 以下示例演示使用该属性的 [Fact] 单元测试:
namespace MyUnitTests
{
public class MyTests
{
[Fact]
public void PassingTest()
{
Assert.AreEqual(4, 2+2);
}
[Fact]
public void FailingTest()
{
Assert.AreEqual(5, 2+2);
}
}
}
在此示例中,测试表示有意通过和失败的测试。
以下示例演示使用该属性的 [Theory] 单元测试:
namespace MyUnitTests
{
public class MyTests
{
[Theory]
[InlineData(3)]
[InlineData(4)]
[InlineData(5)]
public void MyTheoryTest(int value)
{
Assert.True(value % 2 == 1);
}
}
}
在此示例中,尽管只有一个测试方法,但实际上有三个测试,因为理论将针对每个数据项运行一次。
Tip
使用每个单元测试测试一个作。 随着测试复杂性的扩大,测试的验证变得更加困难。 通过将单元测试限制为单个问题,可以确保测试可重复、隔离且执行时间较短。 有关详细信息,请参阅 单元测试最佳做法。
运行单元测试
单元测试可以在 Visual Studio 的测试资源管理器中运行,也可以使用命令运行 dotnet test 。 有关测试资源管理器的信息,请参阅 使用测试资源管理器运行单元测试。 有关命令的信息dotnet test,请参阅使用 dotnet test 和 xUnit 和 dotnet 测试在 .NET 中的单元测试 C# 。
使用设备运行程序运行单元测试
还可以使用设备运行程序在设备上运行单元测试。 设备运行程序是一个测试运行程序应用,它提供可视化运行程序 shell 和一些挂钩,以使用 XHarness 从 CLI 运行。 有关详细信息,请参阅 测试设备运行程序 Wiki 中的文档。