本教程演示如何生成包含单元测试项目和源代码项目的解决方案。 若要使用预生成解决方案遵循本教程, 请查看或下载示例代码。 有关下载说明,请参阅 示例和教程。
创建解决方案
在本部分中,将创建一个包含源和测试项目的解决方案。 已完成的解决方案具有以下目录结构:
/unit-testing-using-dotnet-test
unit-testing-using-dotnet-test.sln
/PrimeService
PrimeService.cs
PrimeService.csproj
/PrimeService.Tests
PrimeService_IsPrimeShould.cs
PrimeServiceTests.csproj
以下说明提供了创建测试解决方案的步骤。 有关在一个步骤中创建测试解决方案的说明,请参阅 命令以创建 测试解决方案。
打开 shell 窗口。
运行下面的命令:
dotnet new sln -o unit-testing-using-dotnet-test
该
dotnet new sln
命令在 unit-testing-using-dotnet-test 目录中创建新的解决方案。将目录更改为 unit-testing-using-dotnet-test 文件夹。
运行下面的命令:
dotnet new classlib -o PrimeService
该
dotnet new classlib
命令在 PrimeService 文件夹中创建新的类库项目。 新类库将包含要测试的代码。将 Class1.cs 重命名为 PrimeService.cs。
将 PrimeService.cs 中的代码替换为以下代码:
using System; namespace Prime.Services { public class PrimeService { public bool IsPrime(int candidate) { throw new NotImplementedException("Not implemented."); } } }
目前,此代码会引发一个 NotImplementedException,但稍后将在本教程中实现该方法。
在 unit-testing-using-dotnet-test 目录中,运行以下命令,将类库项目添加到解决方案:
dotnet sln add ./PrimeService/PrimeService.csproj
通过运行以下命令创建 PrimeService.Tests 项目:
dotnet new xunit -o PrimeService.Tests
上述命令在 PrimeService.Tests 目录中创建 PrimeService.Tests 项目。 测试项目使用 xUnit 作为测试库。 该命令还通过将以下
<PackageReference />
元素添加到项目文件来配置测试运行程序:Microsoft.NET.Test.Sdk
xunit
xunit.runner.visualstudio
coverlet.collector
通过运行以下命令将测试项目添加到解决方案文件:
dotnet sln add ./PrimeService.Tests/PrimeService.Tests.csproj
将
PrimeService
类库作为依赖项添加到 PrimeService.Tests 项目:dotnet add ./PrimeService.Tests/PrimeService.Tests.csproj reference ./PrimeService/PrimeService.csproj
用于创建解决方案的命令
本部分汇总了上一节中的所有命令。 如果已完成上一部分中的步骤,请跳过本部分。
以下命令在 Windows 计算机上创建测试解决方案。 对于 macOS 和 Unix,请将 ren
命令更新为 OS 版本 ren
以重命名文件:
dotnet new sln -o unit-testing-using-dotnet-test
cd unit-testing-using-dotnet-test
dotnet new classlib -o PrimeService
ren .\PrimeService\Class1.cs PrimeService.cs
dotnet sln add ./PrimeService/PrimeService.csproj
dotnet new xunit -o PrimeService.Tests
dotnet add ./PrimeService.Tests/PrimeService.Tests.csproj reference ./PrimeService/PrimeService.csproj
dotnet sln add ./PrimeService.Tests/PrimeService.Tests.csproj
按照上一部分中“将 PrimeService.cs 中的代码替换为以下代码”的说明。
创建测试
体验驱动开发(TDD)中的一种常用方法是在实现目标代码之前编写(失败)测试。 本教程使用 TDD 方法。 该方法 IsPrime
可调用,但不可实现。 对IsPrime
的测试调用失败。 使用 TDD,可以编写一个已知失败的测试。 然后更新目标代码,使测试通过。 你可以重复使用此方法,编写失败的测试,然后更新目标代码使测试通过。
更新 PrimeService.Tests 项目:
删除 PrimeService.Tests/UnitTest1.cs。
创建 PrimeService.Tests/PrimeService_IsPrimeShould.cs 文件。
将 PrimeService_IsPrimeShould.cs 中的代码替换为以下代码:
using Xunit; using Prime.Services; namespace Prime.UnitTests.Services { public class PrimeService_IsPrimeShould { [Fact] public void IsPrime_InputIs1_ReturnFalse() { var primeService = new PrimeService(); bool result = primeService.IsPrime(1); Assert.False(result, "1 should not be prime"); } } }
该 [Fact]
属性声明由测试运行程序运行的测试方法。 在 PrimeService.Tests 文件夹中,运行 dotnet test
。
dotnet 测试命令生成项目并运行测试。 xUnit 测试运行程序包含用于运行测试的程序入口点。
dotnet test
使用单元测试项目启动测试运行程序。
测试失败,因为 IsPrime
尚未实现。 使用 TDD 方法,只编写足够的代码,以便此测试通过。 使用以下代码更新 IsPrime
:
public bool IsPrime(int candidate)
{
if (candidate == 1)
{
return false;
}
throw new NotImplementedException("Not fully implemented.");
}
运行 dotnet test
。 测试通过。
添加更多测试
为 0 和 -1 添加素数测试。 可以复制在上一步中创建的测试,并将以下代码复制为测试 0 和 -1 的副本。 但不要这样做,因为有一个更好的方法。
var primeService = new PrimeService();
bool result = primeService.IsPrime(1);
Assert.False(result, "1 should not be prime");
仅当参数更改代码重复和测试膨胀中的结果时复制测试代码。 以下 xUnit 属性支持编写一套类似的测试:
-
[Theory]
表示执行相同代码但具有不同输入参数的测试套件。 -
[InlineData]
特性指定这些输入的值。
应用前面的 xUnit 属性来创建单个理论,而不是创建新的测试。 替换以下代码...
[Fact]
public void IsPrime_InputIs1_ReturnFalse()
{
var primeService = new PrimeService();
bool result = primeService.IsPrime(1);
Assert.False(result, "1 should not be prime");
}
...替换为以下代码:
[Theory]
[InlineData(-1)]
[InlineData(0)]
[InlineData(1)]
public void IsPrime_ValuesLessThan2_ReturnFalse(int value)
{
var result = _primeService.IsPrime(value);
Assert.False(result, $"{value} should not be prime");
}
在前面的代码中,[Theory]
和 [InlineData]
使得可以测试多个小于二的值。 二是最小质数。
在类声明之后和[Theory]
属性之前添加以下代码:
private readonly PrimeService _primeService;
public PrimeService_IsPrimeShould()
{
_primeService = new PrimeService();
}
运行 dotnet test
,两项测试均失败。 若要使所有测试都通过,请使用以下代码更新 IsPrime
方法:
public bool IsPrime(int candidate)
{
if (candidate < 2)
{
return false;
}
throw new NotImplementedException("Not fully implemented.");
}
遵循 TDD 方法,添加更多失败的测试,然后更新目标代码。 请参阅 测试的完成版本 和 库的完整实现。
已完成的 IsPrime
方法不是用于测试素性的有效算法。