FrameworkKind.java
package org.egothor.methodatlas.discovery.dotnet.internal;
import java.util.List;
import java.util.Set;
/**
* C# test framework detected from {@code using} directives in a source file.
*/
public enum FrameworkKind {
XUNIT, NUNIT, MSTEST, UNKNOWN;
private static final Set<String> ALL_DEFAULT_MARKERS = Set.of(
"Fact", "Theory",
"Test", "TestCase", "TestCaseSource",
"TestMethod", "DataTestMethod");
/**
* Detects the framework from a list of using-directive namespace strings
* (e.g. {@code "NUnit.Framework"}, {@code "Xunit"}).
*/
public static FrameworkKind detect(List<String> usingDirectives) {
for (String u : usingDirectives) {
if ("Xunit".equals(u) || u.startsWith("Xunit.")) { return XUNIT; }
if ("NUnit.Framework".equals(u) || u.startsWith("NUnit.")) { return NUNIT; }
if (u.contains("VisualStudio.TestTools")) { return MSTEST; }
}
return UNKNOWN;
}
/** Default test-attribute names for this framework. */
public Set<String> defaultTestMarkers() {
return switch (this) {
case XUNIT -> Set.of("Fact", "Theory");
case NUNIT -> Set.of("Test", "TestCase", "TestCaseSource");
case MSTEST -> Set.of("TestMethod", "DataTestMethod");
case UNKNOWN -> ALL_DEFAULT_MARKERS;
};
}
/** Attribute simple-names that carry tag / category values on test methods. */
public Set<String> tagAttributeNames() {
return switch (this) {
case XUNIT -> Set.of("Trait");
case NUNIT -> Set.of("Category");
case MSTEST -> Set.of("TestCategory");
case UNKNOWN -> Set.of("Category", "Trait", "TestCategory");
};
}
/**
* Builds a single-line attribute text (without surrounding whitespace) for
* the given tag value, e.g. {@code [Category("security")]}.
*/
public String buildTagAttribute(String tagValue) {
String escaped = tagValue.replace("\\", "\\\\").replace("\"", "\\\"");
return switch (this) {
case XUNIT -> "[Trait(\"Tag\", \"" + escaped + "\")]";
case NUNIT, UNKNOWN -> "[Category(\"" + escaped + "\")]";
case MSTEST -> "[TestCategory(\"" + escaped + "\")]";
};
}
/**
* Returns {@code true} when the attribute carries a display-name that
* MethodAtlas can read and write for this framework.
* Only xUnit embeds {@code DisplayName} as a named parameter of
* {@code [Fact]} / {@code [Theory]}.
*/
public boolean supportsDisplayName() {
return this == XUNIT;
}
}