Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
MSTest provides attributes for organizing tests, adding metadata, and linking tests to work tracking systems. These attributes help you filter, sort, and manage tests effectively in large test suites.
Overview
Metadata attributes appear in the Visual Studio Properties window for test methods. They help you:
- Organize tests: Group tests by category, priority, or owner.
- Filter test runs: Run specific subsets of tests based on metadata.
- Track test coverage: Link tests to work items and requirements.
- Generate reports: Include metadata in test reports and dashboards.
Test categorization
TestCategoryAttribute
The TestCategoryAttribute groups tests into categories for filtering and organization. You can apply this attribute at the method, class, or assembly level, and categories are combined when applied at multiple levels.
Method-level categories
Apply categories directly to test methods for fine-grained control:
[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
}
}
Class-level categories
Apply a category to a test class to assign that category to all test methods within the class:
[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
}
}
Assembly-level categories
Apply a category at the assembly level to categorize all tests in the entire test assembly. This approach is useful for distinguishing test types across projects:
// In AssemblyInfo.cs or any file in your test project
using Microsoft.VisualStudio.TestTools.UnitTesting;
[assembly: TestCategory("E2E")]
Use assembly-level categories to organize your test projects by test type:
| Project | Assembly category | Purpose |
|---|---|---|
MyApp.UnitTests |
Unit |
Fast, isolated unit tests |
MyApp.IntegrationTests |
Integration |
Tests with external dependencies |
MyApp.E2ETests |
E2E |
End-to-end scenario tests |
Filter tests by category
Run tests by category using the dotnet test command:
# 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
In Visual Studio Test Explorer, use the search box with Trait: prefix:
Trait:"TestCategory=Integration"- shows integration tests-Trait:"TestCategory=Slow"- excludes slow tests
TestPropertyAttribute
The TestPropertyAttribute adds custom key-value metadata to tests. Use this attribute when built-in attributes don't meet your needs.
[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
}
}
Properties appear in the Visual Studio Properties window under Test specific.
Filter by custom properties
# Filter by custom property
dotnet test --filter "Feature=Authentication"
Test ownership and priority
OwnerAttribute
The OwnerAttribute identifies who's responsible for a test.
[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
}
}
Filter tests by owner:
dotnet test --filter Owner=jsmith
PriorityAttribute
The PriorityAttribute indicates relative test importance. Lower values indicate higher priority.
[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
}
}
Filter tests by priority:
# Run only highest priority tests
dotnet test --filter Priority=0
# Run high priority or higher
dotnet test --filter "Priority=0|Priority=1"
DescriptionAttribute
The DescriptionAttribute provides a human-readable description of what the test verifies.
Warning
Use Microsoft.VisualStudio.TestTools.UnitTesting.DescriptionAttribute, not System.ComponentModel.DescriptionAttribute. The MSTEST0031 analyzer detects incorrect usage.
[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
}
}
Work item tracking
WorkItemAttribute
The WorkItemAttribute links tests to work items in your tracking system (like 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
The GitHubWorkItemAttribute links tests to GitHub issues.
[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
}
}
Work item attributes are especially valuable when combined with Ignore:
[TestMethod]
[Ignore("Known issue, tracked in work item")]
[WorkItem(99999)]
public void KnownIssue_AwaitingFix()
{
// Provides traceability for why the test is ignored
}
Combining attributes
Combine multiple metadata attributes for comprehensive test organization:
[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
}
}
Best practices
Use consistent categories: Establish naming conventions for test categories across your project.
Set priorities strategically: Reserve
Priority(0)for critical path tests that must pass for a viable build.Link to work items: Always link tests to related work items for traceability, especially bug regression tests.
Document test purpose: Use
Descriptionfor complex tests where the method name doesn't fully explain intent.Keep metadata current: Update metadata when test scope or ownership changes.
Use categories for filtering: Design categories to support your CI/CD pipeline needs (for example, "Smoke", "Nightly", "Integration").
Filtering tests
Command-line filtering
# 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 Test Explorer
Use the search box in Test Explorer:
Trait:"TestCategory=Integration"- filter by categoryTrait:"Owner=jsmith"- filter by ownerTrait:"Priority=0"- filter by priority
For more information on test filtering, see Run selective unit tests.