Skip to content

Commit ef66da3

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 4cf7f4b commit ef66da3

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
@@ -107,26 +107,41 @@ private static void AnalyzeSymbol(SymbolAnalysisContext context)
107107

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

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

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)