TestContext 类提供了有用的信息和工具来帮助管理测试执行。 它允许你访问有关测试运行的详细信息并调整测试环境。 此类是 Microsoft.VisualStudio.TestTools.UnitTesting 命名空间的一部分。
访问 TestContext 对象
TestContext 对象在以下上下文中可用:
- 作为 AssemblyInitialize 的参数,ClassInitialize 方法。 在此上下文中,与测试运行相关的属性不可用。
- 从 3.6 开始,(可选)作为 AssemblyCleanup 的参数,ClassCleanup 方法。 在此上下文中,与测试运行相关的属性不可用。
- 作为测试类的属性。 在此上下文中,与测试运行相关的属性可用。
- 作为测试类的构造器参数(从 v3.6 开始)。 建议使用这种方式,而不是使用属性,因为这样可以在构造函数中访问对象。 而该属性仅在构造函数运行后可用。 这种方式还有助于确保对象的不可变性,并允许编译器强制对象不为 null。
using Microsoft.VisualStudio.TestTools.UnitTesting;
[TestClass]
public class MyTestClassTestContext
{
public TestContext TestContext { get; set; }
[AssemblyInitialize]
public static void AssemblyInitialize(TestContext context)
{
// Access TestContext properties and methods here. The properties related to the test run are not available.
}
[ClassInitialize]
public static void ClassInitialize(TestContext context)
{
// Access TestContext properties and methods here. The properties related to the test run are not available.
}
[TestMethod]
public void MyTestMethod()
{
// Access TestContext properties and methods here
}
}
或者可以使用 MSTest 3.6+:
using Microsoft.VisualStudio.TestTools.UnitTesting;
[TestClass]
public class MyTestClassTestContextThroughCtor
{
private readonly TestContext _testContext;
public MyTestClassTestContextThroughCtor(TestContext testContext)
{
_testContext = testContext;
}
[AssemblyInitialize]
public static void AssemblyInitialize(TestContext context)
{
// Access TestContext properties and methods here. The properties related to the test run are not available.
}
[ClassInitialize]
public static void ClassInitialize(TestContext context)
{
// Access TestContext properties and methods here. The properties related to the test run are not available.
}
[TestMethod]
public void MyTestMethod()
{
// Access TestContext properties and methods here
}
}
TestContext成员。
TestContext 类提供有关测试运行的属性以及用于操作测试环境的方法。 本部分介绍最常用的属性和方法。
测试运行信息
TestContext 提供测试运行的相关信息,如:
- TestContext.TestName – 当前正在执行的测试的名称。
- TestContext.CurrentTestOutcome - 当前测试的结果。
- TestContext.FullyQualifiedTestClassName - 测试类的全名。
- TestContext.TestRunDirectory - 执行测试运行的目录。
-
TestContext.DeploymentDirectory - 部署项所在的目录。 若要填充此目录,请使用
DeploymentItemAttribute。 - TestContext.ResultsDirectory - 存储测试结果的目录。 通常为 TestContext.TestRunDirectory的子目录。
- TestContext.TestRunResultsDirectory - 存储测试结果的目录。 通常为 TestContext.ResultsDirectory的子目录。
- TestContext.TestResultsDirectory - 存储测试结果的目录。 通常为 TestContext.ResultsDirectory的子目录。
- 从 MSTest 3.9 开始,TestContext.TestRunCount - 当前测试已运行的次数,从 1 开始计数。 当重试
[Retry]测试时,该值大于 1。
每个测试的临时目录
Important
TestContext.TestTempDirectory 计划在 MSTest 4.4 中推出,并且在 MSTest 4.4.0 发布之前仅可在预览版中使用。
将 TestContext.TestTempDirectory 用作测试的私有暂存空间。 MSTest 仅在首次访问该属性时创建目录,并且每个测试执行都会收到唯一目录。 每个数据行也会接收其自己的目录,因此并行测试不会共享路径。
string path = Path.Combine(TestContext.TestTempDirectory!, "output.json");
File.WriteAllText(path, json);
MSTest 会在可能的情况下在 TestResultsDirectory 下创建目录;如果结果路径不可用、过长或为只读,则改用系统临时目录。 MSTest 在通过测试后删除该目录,并在任何未通过结果后保留该目录。 将 MSTEST_TEST_TEMP_DIRECTORY_RETAIN 环境变量设置为 1 或 true,以便在所有结果情况下都保留目录。
当测试通过并使用 AddResultFile 从该目录注册文件时,MSTest 会保留该目录,直到宿主进程收集该附件。 清理是尽力而为,不会更改测试结果。
TestTempDirectory可用于.NET和.NET框架目标,但不适用于 UWP 或 WinUI 目标。 该属性不会更改进程当前目录。
在 MSTest 3.7 及更高版本中,TestContext 类还提供对 TestInitialize 和 TestCleanup 方法有用的新属性:
-
TestContext.TestData - 将提供给参数化测试方法的数据,或者如果未参数化测试,则
null。 - TestContext.TestDisplayName - 测试方法的显示名称。
-
TestContext.TestException - 测试方法或测试初始化引发的异常,或者
null(如果测试方法没有引发异常)。
数据驱动的测试
在 MSTest 3.7 及更高版本中,属性 TestContext.TestData 可用于在 TestInitialize 和 TestCleanup 方法期间访问当前测试的数据。
在面向 .NET Framework 时,TestContext 允许你使用 DataRow 和 DataConnection 属性来检索和设置数据驱动测试中每次迭代的数据(适用于基于 DataSource的测试)。
请考虑以下 CSV 文件 TestData.csv:
Number,Name
1,TestValue1
2,TestValue2
3,TestValue3
可以使用 DataSource 属性从 CSV 文件读取数据:
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
namespace YourNamespace
{
[TestClass]
public class CsvDataDrivenTest
{
public TestContext TestContext { get; set; }
[TestMethod]
[DataSource(
"Microsoft.VisualStudio.TestTools.DataSource.CSV",
"|DataDirectory|\\TestData.csv",
"TestData#csv",
DataAccessMethod.Sequential)]
public void TestWithCsvDataSource()
{
// Access data from the current row
int number = Convert.ToInt32(TestContext.DataRow["Number"]);
string name = TestContext.DataRow["Name"].ToString();
Console.WriteLine($"Number: {number}, Name: {name}");
// Example assertions or logic
Assert.IsTrue(number > 0);
Assert.IsFalse(string.IsNullOrEmpty(name));
}
}
}
存储和检索运行时数据
可以使用 TestContext.Properties 来存储可在同一测试会话中跨不同方法访问的自定义键值对。
从 MSTest 4.4 预览版开始,索引器在自定义键不存在时一致返回 null 。
TestContext.Properties["MyKey"] = "MyValue";
string value = TestContext.Properties["MyKey"]?.ToString();
注意
从 MSTest 4.2 开始,测试类别 [TestCategory] 包含在 TestContext.Properties内。
从 MSTest 4.3 开始,在 TestContext.Properties 中添加到 [AssemblyInitialize] 的自定义属性会传递到程序集中的每个类和测试,而在 [ClassInitialize] 中添加的属性会传递到该类中的每个测试。 这使装置可以发布测试方法可以读取的共享上下文。
从 MSTest 4.3.3 开始,[TestProperty] 值、测试类别、主机提供的属性以及测试添加的属性仍然仅限于该测试,不会传播到同级测试。
从当前调用堆栈进行访问TestContext
从 MSTest 4.2 开始,在测试方法执行期间, TestContext.Current 从调用堆栈中的任意位置返回当前 TestContext 测试。 此 API 是实验性的,使用 [Experimental] 属性,并可能在将来的 MSTest 版本中更改。
将数据关联到测试
TestContext.AddResultFile(String) 方法允许向测试结果添加文件,使其在测试输出中可供查看。 这在您希望将测试期间生成的文件(例如日志文件、屏幕截图或数据文件)附加到测试结果时,非常有用。
using Microsoft.VisualStudio.TestTools.UnitTesting;
[TestClass]
public class TestClassResultFile
{
public TestContext TestContext { get; set; }
[TestMethod]
public void TestMethodWithResultFile()
{
// Simulate creating a log file for this test
string logFilePath = Path.Combine(TestContext.TestRunDirectory, "TestLog.txt");
File.WriteAllText(logFilePath, "This is a sample log entry for the test.");
// Add the log file to the test result
TestContext.AddResultFile(logFilePath);
// Perform some assertions (example only)
Assert.IsTrue(File.Exists(logFilePath), "The log file was not created.");
Assert.IsTrue(new FileInfo(logFilePath).Length > 0, "The log file is empty.");
}
}
还可以使用 TestContext.Write 或 TestContext.WriteLine 方法将自定义消息直接写入测试输出。 从 MSTest 4.4 开始,Live 输出捕获模式会在测试运行期间回显这些消息,同时仍会将这些消息附加到最终测试结果中。 有关详细信息,请参阅 配置 MSTest 输出。
取消令牌
当测试超时或测试运行中止时,TestContext 会发出一个 CancellationToken 属性信号。 你应将此令牌传递给异步操作,以便它们可以协作响应取消。 使用 Timeout 属性时,这一点尤其重要。
当TestContext作为属性访问时:
using Microsoft.VisualStudio.TestTools.UnitTesting;
[TestClass]
public class TestClassCancellationToken
{
// MSTest automatically sets the TestContext property before each test runs.
// MSTest.Analyzers includes a diagnostic suppressor that removes CS8618
// (non-nullable property uninitialized) for this property.
public TestContext TestContext { get; set; }
[TestMethod]
[Timeout(5000, CooperativeCancellation = true)]
public async Task MyAsyncTest()
{
using var client = new HttpClient();
var response = await client.GetAsync(
"https://example.com", TestContext.CancellationToken);
Assert.IsTrue(response.IsSuccessStatusCode);
}
}
当通过构造函数注入TestContext时(MSTest 3.6+)
using Microsoft.VisualStudio.TestTools.UnitTesting;
[TestClass]
public class TestClassCancellationTokenCtor
{
private readonly TestContext _testContext;
public TestClassCancellationTokenCtor(TestContext testContext)
{
_testContext = testContext;
}
[TestMethod]
[Timeout(5000, CooperativeCancellation = true)]
public async Task MyAsyncTest()
{
using var client = new HttpClient();
var response = await client.GetAsync(
"https://example.com", _testContext.CancellationToken);
Assert.IsTrue(response.IsSuccessStatusCode);
}
}
小窍门
MSTest 分析器规则 MSTEST0049 有助于识别应传递的 TestContext.CancellationToken 异步调用。 它还提供代码修复程序来自动应用更改。
相关分析器
以下分析器有助于确保正确使用 TestContext 类:
- MSTEST0005 - TestContext 属性应具有有效的布局。
- MSTEST0024 - 不要将 TestContext 存储在静态成员中。
- MSTEST0033 - 为 TestContext 属性抑制 CS8618。
- MSTEST0048 - 避免固定装置方法中的 TestContext 属性。
- MSTEST0049 - 传递 TestContext CancellationToken。
- MSTEST0054 - 使用 CancellationToken 属性。