| Property | Value |
|---|---|
| Package | Philips.CodeAnalysis.MsTestAnalyzers |
| Diagnostic ID | PH2162 |
| Category | MsTest |
| Analyzer | TestTimeoutsClassAccessibilityAnalyzer |
| CodeFix | Yes |
| Severity | Warning |
| Enabled By Default | Yes |
Projects commonly define a TestTimeouts class that centralizes timeout constants (e.g., CiAppropriate, Integration). This analyzer enforces that any class named TestTimeouts is declared as internal and not static. Public exposure or use of static on this coordination class is discouraged.
This rule helps avoid conflicts with the MSTest analyzer that restricts all classes in a test project from being public unless they are annotated with [TestClass].
Keeping TestTimeouts internal:
- Prevents leaking test-only infrastructure into the public API surface of a library.
- Avoids external projects taking a compile-time dependency on timeout values that are intended to be adjusted freely.
- Encourages each assembly to own and tune its own timeout set without cross-assembly coupling.
- Reduces the risk that production code (outside test projects) references test timing constants.
Disallowing static (while permitting sealed) helps future flexibility (e.g., partial conditional compilation patterns) and keeps the shape consistent with existing guidance in related timeout analyzers. A sealed internal class with only const members satisfies the same usage needs without requiring static.
The diagnostic is reported for any class whose identifier is exactly TestTimeouts if either:
- It is declared
public(with or withoutsealed). - It is declared
internal static.
The class name comparison is exact and case-sensitive.
Change the declaration to be internal (optionally sealed) and remove static if present. The provided Code Fix will:
- Remove
public. - Remove
static(when paired withinternal). - Insert
internalif missing. - Preserve
sealedif it exists.
Code that triggers the diagnostic (public):
public class TestTimeouts
{
public const int CiAppropriate = 1000;
}Fix:
internal class TestTimeouts
{
public const int CiAppropriate = 1000;
}Code that triggers the diagnostic (public sealed):
public sealed class TestTimeouts
{
public const int CiAppropriate = 1000;
}Fix (Code Fix output):
internal sealed class TestTimeouts
{
public const int CiAppropriate = 1000;
}Code that triggers the diagnostic (internal static):
internal static class TestTimeouts
{
public const int CiAppropriate = 1000;
}Fix (Code Fix output):
internal class TestTimeouts
{
public const int CiAppropriate = 1000;
}Code that does NOT trigger the diagnostic:
internal class TestTimeouts
{
public const int CiAppropriate = 1000;
}
internal sealed class TestTimeouts
{
public const int CiAppropriate = 1000;
}Other class names are ignored:
public class SomeOtherClass
{
public const int CiAppropriate = 1000;
}Selecting the Code Fix on a reported diagnostic rewrites the class modifiers as described above. It does not otherwise reorder members or alter whitespace beyond necessary modifier changes.
| ID | Title |
|---|---|
| PH2012 | Test has Timeout |
| PH2015 | Test must have appropriate Test Category |
These analyzers collectively encourage consistent timeout usage patterns.
This analyzer does not currently support custom configuration keys. Standard suppression mechanisms (pragma, GlobalSuppressions.cs, or EditorConfig severity adjustments) apply, but suppression is discouraged—prefer adopting the recommended accessibility.
# Example: adjust severity (not recommended)
dotnet_diagnostic.PH2162.severity = warning