NoTests
The NoTestsAttribute specifies the default status for a parameterized test method or test fixture when it contains no
executable child tests. This is useful when test cases are generated dynamically and may sometimes produce an empty
set.
By default, NUnit treats a Theory with no test cases as a failure. For other parameterized tests, the behavior may
vary. The NoTestsAttribute allows you to explicitly control what status should be reported when no test cases are
available.
Note
This attribute was introduced in NUnit 4.6.
Usage
The attribute accepts a TestStatus value that determines how the test should be reported when no child tests exist:
TestStatus.Skipped- The test is marked as skippedTestStatus.Inconclusive- The test is marked as inconclusiveTestStatus.Passed- The test is marked as passed (use with caution)TestStatus.Failed- The test is marked as failed (default for Theory)
Test Fixture Syntax
Apply to a fixture to affect all parameterized tests within it:
[TestFixture]
[NoTests(TestStatus.Skipped)]
public class DynamicTestsFixture
{
// When no test cases are generated, the test will be marked as Skipped
// instead of Failed (which is the default for Theory) or Passed
[TestCaseSource(nameof(GetTestCases))]
public void DynamicTest(int value)
{
Assert.That(value, Is.GreaterThan(0));
}
private static IEnumerable<int> GetTestCases()
{
// In real scenarios, this might query a database or external source
// that could return empty results
yield break; // No test cases
}
}
Test Method Syntax
Apply directly to a test method:
[TestFixture]
public class MethodLevelNoTestsFixture
{
[NoTests(TestStatus.Skipped)]
[TestCaseSource(nameof(EmptySource))]
public void TestWithPossiblyEmptySource(int value)
{
Assert.That(value, Is.Positive);
}
private static IEnumerable<int> EmptySource()
{
yield break;
}
}
Inconclusive Status
Use TestStatus.Inconclusive when empty test cases indicate an indeterminate state rather than a skip:
[TestFixture]
[NoTests(TestStatus.Inconclusive)]
public class ConditionalTestsFixture
{
[TestCaseSource(nameof(GetConditionalCases))]
public void ConditionalTest(string input)
{
Assert.That(input, Is.Not.Empty);
}
private static IEnumerable<string> GetConditionalCases()
{
// Returns empty when certain conditions aren't met
if (Environment.GetEnvironmentVariable("RUN_CONDITIONAL_TESTS") == "true")
{
yield return "test1";
yield return "test2";
}
// Otherwise yields nothing - test will be Inconclusive
}
}
Common Scenarios
Dynamic Test Data
When test cases come from external sources (databases, APIs, configuration files) that might be empty:
[TestFixture]
[NoTests(TestStatus.Skipped)]
public class DataDrivenTests
{
[TestCaseSource(typeof(ExternalDataSource))]
public void ProcessData(DataRecord record)
{
// Test implementation
}
}
Conditional Test Execution
When test cases are only available under certain conditions:
[NoTests(TestStatus.Inconclusive)]
[TestCaseSource(nameof(GetPlatformSpecificCases))]
public void PlatformSpecificTest(string testCase)
{
// Test only runs when platform-specific cases are available
}
Feature Flag Testing
When tests depend on feature flags that may not be enabled:
[TestFixture]
[NoTests(TestStatus.Skipped)]
public class FeatureFlagTests
{
[TestCaseSource(nameof(GetEnabledFeatures))]
public void TestFeature(string featureName)
{
// Tests features that are currently enabled
}
}
Inheritance
The NoTestsAttribute can be applied at the assembly, class, or method level:
- Assembly level: Affects all parameterized tests in the assembly
- Class level: Affects all parameterized tests in the fixture
- Method level: Affects only the specific test method
When multiple levels specify the attribute, the most specific level (method) takes precedence.