diff --git a/TUnit.Core.SourceGenerator/CodeGenerators/Writers/FailedTestInitializationWriter.cs b/TUnit.Core.SourceGenerator/CodeGenerators/Writers/FailedTestInitializationWriter.cs
index cd18e57587..69471a7923 100644
--- a/TUnit.Core.SourceGenerator/CodeGenerators/Writers/FailedTestInitializationWriter.cs
+++ b/TUnit.Core.SourceGenerator/CodeGenerators/Writers/FailedTestInitializationWriter.cs
@@ -8,7 +8,8 @@ public static class FailedTestInitializationWriter
public static void GenerateFailedTestCode(ICodeWriter sourceBuilder,
DynamicTestSourceDataModel testSourceDataModel)
{
- var testId = $"{testSourceDataModel.Class.ContainingNamespace}.{testSourceDataModel.Class.Name}.{testSourceDataModel.Method.Name}_InitializationFailure";
+ var className = testSourceDataModel.Class.GetNestedClassName();
+ var testId = $"{testSourceDataModel.Class.ContainingNamespace}.{className}.{testSourceDataModel.Method.Name}_InitializationFailure";
sourceBuilder.Append("return");
sourceBuilder.Append("[");
@@ -16,7 +17,7 @@ public static void GenerateFailedTestCode(ICodeWriter sourceBuilder,
sourceBuilder.Append("{");
sourceBuilder.Append($"TestId = \"{testId}\",");
sourceBuilder.Append($"MethodName = $\"{testSourceDataModel.Method.Name}\",");
- sourceBuilder.Append($"Exception = new global::TUnit.Core.Exceptions.TestFailedInitializationException(\"{testSourceDataModel.Class.Name}.{testSourceDataModel.Method.Name} failed to initialize\", exception),");
+ sourceBuilder.Append($"Exception = new global::TUnit.Core.Exceptions.TestFailedInitializationException(\"{className}.{testSourceDataModel.Method.Name} failed to initialize\", exception),");
sourceBuilder.Append($"TestFilePath = @\"{testSourceDataModel.FilePath}\",");
sourceBuilder.Append($"TestLineNumber = {testSourceDataModel.LineNumber},");
sourceBuilder.Append("}");
diff --git a/TUnit.Core.SourceGenerator/Extensions/TypeExtensions.cs b/TUnit.Core.SourceGenerator/Extensions/TypeExtensions.cs
index d4b2266807..726185ffa0 100644
--- a/TUnit.Core.SourceGenerator/Extensions/TypeExtensions.cs
+++ b/TUnit.Core.SourceGenerator/Extensions/TypeExtensions.cs
@@ -348,4 +348,27 @@ public static bool IsCollectionType(this ITypeSymbol typeSymbol, Compilation com
innerType = null;
return false;
}
+
+ ///
+ /// Gets the nested class name with '+' separator (matching .NET Type.FullName convention).
+ /// For example: OuterClass+InnerClass
+ ///
+ public static string GetNestedClassName(this INamedTypeSymbol typeSymbol)
+ {
+ var typeHierarchy = new List();
+ var currentType = typeSymbol;
+
+ // Walk up the containing type chain
+ while (currentType != null)
+ {
+ typeHierarchy.Add(currentType.Name);
+ currentType = currentType.ContainingType;
+ }
+
+ // Reverse to get outer-to-inner order
+ typeHierarchy.Reverse();
+
+ // Join with '+' separator (matching .NET Type.FullName convention for nested types)
+ return string.Join("+", typeHierarchy);
+ }
}
diff --git a/TUnit.Engine/Services/TestIdentifierService.cs b/TUnit.Engine/Services/TestIdentifierService.cs
index 5456917368..8a8504fad5 100644
--- a/TUnit.Engine/Services/TestIdentifierService.cs
+++ b/TUnit.Engine/Services/TestIdentifierService.cs
@@ -199,12 +199,12 @@ private static string GetTypeNameWithGenerics(Type type)
// Reverse to get outer-to-inner order
typeHierarchy.Reverse();
- // Append all types with dot separator
+ // Append all types with + separator (matching .NET Type.FullName convention for nested types)
for (var i = 0; i < typeHierarchy.Count; i++)
{
if (i > 0)
{
- sb.Append('.');
+ sb.Append('+');
}
sb.Append(typeHierarchy[i]);
}