Skip to content

Commit b2fe63a

Browse files
Use namespace-based test detection for more flexible test framework support
Co-authored-by: BenjaminMichaelis <22186029+BenjaminMichaelis@users.noreply.github.com>
1 parent 792cbe2 commit b2fe63a

2 files changed

Lines changed: 31 additions & 16 deletions

File tree

IntelliTect.Analyzer/IntelliTect.Analyzer/Analyzers/NamingMethodPascal.cs

Lines changed: 30 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -108,26 +108,41 @@ private static void AnalyzeSymbol(SymbolAnalysisContext context)
108108

109109
private static bool IsTestMethod(IMethodSymbol methodSymbol)
110110
{
111-
// Common test framework attributes
112-
string[] testAttributeNames =
111+
// Test framework namespaces - checking namespace is more flexible than specific attribute names
112+
string[] testFrameworkNamespaces =
113113
[
114-
"TestMethod", // MSTest
115-
"TestMethodAttribute",
116-
"Fact", // xUnit
117-
"FactAttribute",
118-
"Theory", // xUnit
119-
"TheoryAttribute",
120-
"Test", // NUnit
121-
"TestAttribute",
122-
"TestCase", // NUnit
123-
"TestCaseAttribute",
124-
"TestCaseSource", // NUnit
125-
"TestCaseSourceAttribute"
114+
"Xunit", // xUnit
115+
"NUnit.Framework", // NUnit
116+
"Microsoft.VisualStudio.TestTools.UnitTesting", // MSTest
117+
"TUnit.Core" // TUnit
126118
];
127119

128120
ImmutableArray<AttributeData> attributes = methodSymbol.GetAttributes();
129121
return attributes.Any(attribute =>
130-
attribute.AttributeClass?.Name is string name && testAttributeNames.Contains(name));
122+
{
123+
if (attribute.AttributeClass == null)
124+
{
125+
return false;
126+
}
127+
128+
// Check namespace first (more robust for production code)
129+
string containingNamespace = attribute.AttributeClass.ContainingNamespace?.ToDisplayString();
130+
if (containingNamespace != null &&
131+
testFrameworkNamespaces.Any(ns => containingNamespace.StartsWith(ns, StringComparison.Ordinal)))
132+
{
133+
return true;
134+
}
135+
136+
// Fallback: check attribute name for common test attributes
137+
// This helps in test environments where namespace metadata may be incomplete
138+
string attributeName = attribute.AttributeClass.Name;
139+
return attributeName == "TestMethod" || attributeName == "TestMethodAttribute" ||
140+
attributeName == "Fact" || attributeName == "FactAttribute" ||
141+
attributeName == "Theory" || attributeName == "TheoryAttribute" ||
142+
attributeName == "Test" || attributeName == "TestAttribute" ||
143+
attributeName == "TestCase" || attributeName == "TestCaseAttribute" ||
144+
attributeName == "TestCaseSource" || attributeName == "TestCaseSourceAttribute";
145+
});
131146
}
132147
}
133148
}

docs/analyzers/00XX.Naming.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ class SomeClass
4949

5050
Methods, including local functions, should be PascalCase
5151

52-
**Note:** Test methods decorated with test framework attributes (e.g., `[TestMethod]`, `[Fact]`, `[Theory]`, `[Test]`) are exempt from this rule, as they commonly use underscores for readability (e.g., `Method_Scenario_ExpectedResult`).
52+
**Note:** Test methods decorated with test framework attributes from xUnit, NUnit, MSTest, or TUnit are exempt from this rule, as they commonly use underscores for readability (e.g., `Method_Scenario_ExpectedResult`). Any attribute from these framework namespaces will be recognized automatically.
5353

5454
**Allowed**
5555
```c#

0 commit comments

Comments
 (0)