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]); }