通过


在 MSTest 中测试组织和元数据

MSTest 提供用于组织测试、添加元数据并将测试链接到工作跟踪系统的属性。 这些属性可帮助你有效地在大型测试套件中筛选、排序和管理测试。

概述

元数据属性显示在测试方法的 Visual Studio 属性 窗口中。 它们可帮助你:

  • 组织测试:按类别、优先级或所有者对测试进行分组。
  • 筛选器测试运行:基于元数据运行特定的测试子集。
  • 跟踪测试覆盖率:将测试链接到工作项和要求。
  • 生成报表:在测试报表和仪表板中包含元数据。

测试分类

TestCategoryAttribute

这些 TestCategoryAttribute 将测试分组为用于筛选和组织的类别。 可以在方法、类或程序集级别应用此属性,并在多个级别应用时组合类别。

方法级类别

将类别直接应用于用于精细控制的测试方法:

[TestClass]
public class OrderTests
{
    [TestMethod]
    [TestCategory("Integration")]
    public void CreateOrder_SavesOrderToDatabase()
    {
        // Integration test
    }

    [TestMethod]
    [TestCategory("Unit")]
    public void CalculateTotal_ReturnsSumOfItems()
    {
        // Unit test
    }

    [TestMethod]
    [TestCategory("Integration")]
    [TestCategory("Slow")]
    public void ProcessLargeOrder_CompletesSuccessfully()
    {
        // Multiple categories allowed
    }
}

类级分类

将类别应用于测试类,以将该类别分配给该类中的所有测试方法:

[TestClass]
[TestCategory("Payments")]
public class PaymentServiceTests
{
    [TestMethod]
    public void ProcessPayment_ValidCard_Succeeds()
    {
        // Inherits "Payments" category from class
    }

    [TestMethod]
    [TestCategory("Slow")]
    public void ProcessBatchPayments_LargeVolume_CompletesSuccessfully()
    {
        // Has both "Payments" (from class) and "Slow" (from method) categories
    }
}

程序集级类别

在程序集级别应用类别以对整个测试程序集中的所有测试进行分类。 此方法可用于区分项目之间的测试类型:

// In AssemblyInfo.cs or any file in your test project
using Microsoft.VisualStudio.TestTools.UnitTesting;

[assembly: TestCategory("E2E")]

使用程序集级类别按测试类型组织测试项目:

项目 程序集类别 目的
MyApp.UnitTests Unit 快速隔离单元测试
MyApp.IntegrationTests Integration 使用外部依赖项进行测试
MyApp.E2ETests E2E 端到端方案测试

根据类别过滤测试

使用 dotnet test 命令按类别运行测试:

# Run only integration tests
dotnet test --filter TestCategory=Integration

# Run tests in multiple categories
dotnet test --filter "TestCategory=Integration|TestCategory=Unit"

# Exclude slow tests
dotnet test --filter TestCategory!=Slow

在 Visual Studio 测试资源管理器中,使用带有前缀的 Trait: 搜索框:

  • Trait:"TestCategory=Integration" - 显示集成测试
  • -Trait:"TestCategory=Slow" - 排除慢速测试

TestPropertyAttribute

TestPropertyAttribute 测试添加自定义键值元数据。 当内置属性不满足你的需求时,请使用此属性。

[TestClass]
public class CustomMetadataTests
{
    [TestMethod]
    [TestProperty("Feature", "Authentication")]
    [TestProperty("Sprint", "23")]
    [TestProperty("RiskLevel", "High")]
    public void Login_WithValidCredentials_Succeeds()
    {
        // Test with custom properties
    }

    [TestMethod]
    [TestProperty("Feature", "Authorization")]
    [TestProperty("RequirementId", "REQ-AUTH-001")]
    public void AccessAdminPage_RequiresAdminRole()
    {
        // Link to requirements
    }
}

属性显示在“测试特定”下的“Visual Studio 属性”窗口中。

按自定义属性进行筛选

# Filter by custom property
dotnet test --filter "Feature=Authentication"

测试所有权和优先级

OwnerAttribute

负责测试的人员是由 OwnerAttribute 标识的。

[TestClass]
public class PaymentTests
{
    [TestMethod]
    [Owner("jsmith")]
    public void ProcessPayment_ChargesCorrectAmount()
    {
        // John Smith owns this test
    }

    [TestMethod]
    [Owner("team-payments")]
    public void RefundPayment_CreditsCustomerAccount()
    {
        // Team responsibility
    }
}

按所有者筛选测试:

dotnet test --filter Owner=jsmith

PriorityAttribute

表明 PriorityAttribute 的相对测试重要性。 越小的值表示优先级越高。

[TestClass]
public class CriticalPathTests
{
    [TestMethod]
    [Priority(0)]
    public void Login_IsAlwaysAvailable()
    {
        // Highest priority - core functionality
    }

    [TestMethod]
    [Priority(1)]
    public void CreateAccount_WorksCorrectly()
    {
        // High priority
    }

    [TestMethod]
    [Priority(2)]
    public void CustomizeProfile_SavesPreferences()
    {
        // Medium priority
    }
}

按优先级筛选测试:

# Run only highest priority tests
dotnet test --filter Priority=0

# Run high priority or higher
dotnet test --filter "Priority=0|Priority=1"

DescriptionAttribute

提供一个关于 DescriptionAttribute 所验证内容的用户可读说明。

警告

使用 Microsoft.VisualStudio.TestTools.UnitTesting.DescriptionAttribute,而不是 System.ComponentModel.DescriptionAttributeMSTEST0031分析器检测到不正确的使用情况。

[TestClass]
public class DocumentedTests
{
    [TestMethod]
    [Description("Verifies that orders over $100 receive a 10% discount")]
    public void ApplyDiscount_LargeOrder_Gets10PercentOff()
    {
        // Test implementation
    }

    [TestMethod]
    [Description("Ensures email validation rejects malformed addresses")]
    public void ValidateEmail_InvalidFormat_ReturnsFalse()
    {
        // Test implementation
    }
}

工作项跟踪

WorkItemAttribute

WorkItemAttribute 将测试与您的跟踪系统(如 Azure DevOps)中的工作项链接起来。

[TestClass]
public class BugFixTests
{
    [TestMethod]
    [WorkItem(12345)]
    [Description("Regression test for bug #12345")]
    public void DatePicker_LeapYear_HandlesFebruary29()
    {
        // Test that verifies the bug fix
    }

    [TestMethod]
    [WorkItem(67890)]
    [WorkItem(67891)]  // Can link multiple work items
    public void Export_LargeDataset_CompletesWithinTimeout()
    {
        // Test related to multiple work items
    }
}

GitHubWorkItemAttribute

链接 GitHubWorkItemAttribute 将测试与 GitHub 问题关联起来。

[TestClass]
public class GitHubLinkedTests
{
    [TestMethod]
    [GitHubWorkItem("https://github.com/myorg/myrepo/issues/42")]
    public void FeatureX_WorksAsExpected()
    {
        // Test linked to GitHub issue #42
    }

    [TestMethod]
    [GitHubWorkItem("https://github.com/myorg/myrepo/issues/100")]
    [Ignore("Waiting for upstream fix")]
    public void DependentFeature_RequiresUpdate()
    {
        // Ignored test linked to tracking issue
    }
}

与以下项结合使用 Ignore时,工作项属性特别有用:

[TestMethod]
[Ignore("Known issue, tracked in work item")]
[WorkItem(99999)]
public void KnownIssue_AwaitingFix()
{
    // Provides traceability for why the test is ignored
}

组合属性

将多个元数据属性结合起来,以实现全面的测试组织:

[TestClass]
public class FullyDocumentedTests
{
    [TestMethod]
    [TestCategory("Integration")]
    [TestCategory("API")]
    [Owner("payment-team")]
    [Priority(1)]
    [Description("Verifies that the payment API returns correct error codes for invalid requests")]
    [WorkItem(54321)]
    [TestProperty("Sprint", "24")]
    [TestProperty("Feature", "ErrorHandling")]
    public void PaymentAPI_InvalidRequest_ReturnsAppropriateErrorCode()
    {
        // Well-documented test with full traceability
    }
}

最佳做法

  1. 使用一致的类别:为项目中的测试类别建立命名约定。

  2. 从战略上设置优先级:为必须通过的关键路径测试保留 Priority(0),以确保构建的可行性。

  3. 链接到工作项:始终将测试链接到相关工作项,以实现可追踪性,尤其是缺陷回归测试。

  4. 文档测试目的:在 Description 方法名称无法完全解释意图的情况下进行复杂测试。

  5. 使元数据保持最新状态:在测试范围或所有权更改时更新元数据。

  6. 使用类别进行筛选:设计类别以支持 CI/CD 管道需求(例如“冒烟”、“夜间”、“集成”)。

筛选测试

命令行筛选

# Filter by category
dotnet test --filter TestCategory=Unit

# Filter by owner
dotnet test --filter Owner=jsmith

# Filter by priority
dotnet test --filter Priority=0

# Combine filters (AND)
dotnet test --filter "TestCategory=Integration&Priority=0"

# Combine filters (OR)
dotnet test --filter "TestCategory=Smoke|TestCategory=Critical"

# Exclude by filter
dotnet test --filter TestCategory!=Slow

# Filter by custom property
dotnet test --filter "Feature=Payments"

Visual Studio 测试资源管理器

在测试资源管理器中使用搜索框:

  • Trait:"TestCategory=Integration" - 按类别进行筛选
  • Trait:"Owner=jsmith" - 按所有者进行筛选
  • Trait:"Priority=0" - 按优先级进行筛选

有关测试筛选的详细信息,请参阅 “运行选择性单元测试”。

另请参阅