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, behavior may
vary. NoTestsAttribute chooses the TestStatus reported when no executable child tests are produced.
Note
Introduced in NUnit 4.6.
Constructor
NoTestsAttribute(TestStatus defaultStatus)
| Parameter | Type | Description |
|---|---|---|
defaultStatus |
TestStatus |
Result when no child tests exist (Skipped, Inconclusive, Passed, or Failed). |
Applies To
| Test Methods | Test Fixtures (Classes) | Assembly |
|---|---|---|
| ✅ | ✅ | ✅ |
Most specific scope (method) wins over fixture and assembly.
TestStatus Values
Typical uses:
| Value | Meaning |
|---|---|
TestStatus.Skipped |
Marked skipped when no cases |
TestStatus.Inconclusive |
Indeterminate empty data |
TestStatus.Passed |
Passed with no cases (use carefully) |
TestStatus.Failed |
Default for Theory with no cases |
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
Typical when test cases come from a source that can legitimately be empty (a database, API, config file, or similar).
[TestFixture]
[NoTests(TestStatus.Skipped)]
public class DataDrivenTests
{
[TestCaseSource(typeof(ExternalDataSource))]
public void ProcessData(int recordId)
{
Assert.That(recordId, Is.GreaterThan(0));
}
}
public sealed class ExternalDataSource : IEnumerable
{
public IEnumerator GetEnumerator()
{
yield break;
}
}
Conditional Execution
Typical when cases are only produced for some platforms, environments, or other prerequisites.
[NoTests(TestStatus.Inconclusive)]
[TestCaseSource(nameof(GetPlatformSpecificCases))]
public void PlatformSpecificTest(string testCase)
{
Assert.That(testCase, Is.Not.Empty);
}
private static IEnumerable<string> GetPlatformSpecificCases()
{
yield break;
}
Feature Flags
Typical when data-driven cases depend on feature flags or rollout state and may sometimes yield none.
[TestFixture]
[NoTests(TestStatus.Skipped)]
public class FeatureFlagTests
{
[TestCaseSource(nameof(GetEnabledFeatures))]
public void TestFeature(string featureName)
{
Assert.That(featureName, Is.Not.Empty);
}
private static IEnumerable<string> GetEnabledFeatures()
{
yield break;
}
}
Scope Precedence
- Assembly — parameterized tests across the assembly
- Fixture (class) — parameterized tests in that fixture
- Method — that method only
The most specific level wins when multiple attributes apply.