Skip to content

fix(engine): emit ECMA-335 metadata-format type names in TestMethodIdentifierProperty#6433

Merged
thomhurst merged 1 commit into
mainfrom
fix/method-identifier-metadata-type-names
Jul 16, 2026
Merged

fix(engine): emit ECMA-335 metadata-format type names in TestMethodIdentifierProperty#6433
thomhurst merged 1 commit into
mainfrom
fix/method-identifier-metadata-type-names

Conversation

@thomhurst

Copy link
Copy Markdown
Owner

Problem

Microsoft.Testing.Platform specifies that TestMethodIdentifierProperty values are ECMA-335 compliant (managed name format, vstest RFC 0017). TUnit was passing raw reflection Type.FullName for ParameterTypeFullNames and ReturnTypeFullName, which produces:

  • Assembly-qualified generic arguments: System.Collections.Generic.List1[[System.String, System.Private.CoreLib, Version=...]]`
  • null (via FullName!) for open generic method parameters (T)

Fix

New MetadataTypeNameFormatter (cached per Type) emits the spec format, matching what MSTest's ManagedNameParser produces:

  • Constructed generics: System.Collections.Generic.List1<System.String>`
  • Generic method parameters: !!0; generic type parameters: !0
  • Arrays ([], [,], jagged), byref &, pointer *
  • Nested types via +

Deliberately unchanged

TypeName keeps TUnit's class-argument decoration (MyTests(arg1, arg2)) for parameterized test classes — this keeps class-data-source instances distinguishable in Test Explorer. Nested-type + joining, namespace split, and generic backtick arity were already spec-conformant.

No internal consumers read ParameterTypeFullNames/ReturnTypeFullName (reporters only read TypeName/MethodName/Namespace), so no downstream output changes.

Tests

15 new tests in MetadataTypeNameFormatterTests covering simple types, constructed/open generics, nested generics, arrays, nullable, nested types, !!n/!n placeholders, byref.

…entifierProperty

Microsoft.Testing.Platform specifies that TestMethodIdentifierProperty values
are ECMA-335 compliant (managed name format, vstest RFC 0017). TUnit was
passing reflection Type.FullName for ParameterTypeFullNames and
ReturnTypeFullName, which yields assembly-qualified generic arguments
(List`1[[System.String, System.Private.CoreLib, ...]]) and null for open
generic method parameters.

New MetadataTypeNameFormatter emits the spec format:
- constructed generics: List`1<System.String>
- generic method/type parameters: !!0 / !0
- arrays, byref, pointer suffixes; nested types via '+'

TypeName intentionally keeps TUnit's class-argument decoration
(MyTests(arg1, arg2)) so parameterized classes stay distinguishable in
Test Explorer.
@claude

claude Bot commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

Code review

Reviewed the diff, cross-checked the new MetadataTypeNameFormatter logic against the ECMA-335/vstest RFC-0017 spec described in the PR, and had two independent passes hunt for bugs/security issues in just the introduced code. No issues found.

Notes from the review:

  • The recursive formatter correctly handles constructed generics, generic method (!!N) vs. type (!N) parameters, arrays (including jagged/multi-rank), byref (&), pointer (*), and nested types (+) — verified by tracing the logic against all 15 new test cases in MetadataTypeNameFormatterTests.cs.
  • The returnTypeFullName change correctly preserves the old System.Void fallback behavior for void returns, while fixing the previous bug where an open generic return type (T) would silently fall back to "System.Void" via the ?? operator instead of producing a spec-correct !!0.
  • ParameterTypeFullNames/ReturnTypeFullName are computed once downstream of TestDetails, which is populated uniformly by both source-gen and reflection discovery — so this satisfies the dual-mode requirement without needing separate source-gen logic.
  • Caching via ConcurrentDictionary<Type, string> + StringBuilderPool is thread-safe and consistent with the existing TypeNameFormatter pattern in TUnit.Core.Helpers.

Checked for bugs and CLAUDE.md compliance (dual-mode metadata collection, snapshot testing, AOT compatibility, performance).

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 772139f923

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

for (var i = 0; i < parameters.Length; i++)
{
array[i] = parameters[i].Type.FullName!;
array[i] = MetadataTypeNameFormatter.GetMetadataFullName(parameters[i].Type);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Use TypeInfo for source-gen generic parameters

In source-generated metadata, parameters that depend on generic arguments are stored with Type == typeof(object) and the real signature in TypeInfo (for example the generated snapshots create IEnumerable<TSource> as typeof(object) plus ConstructedGeneric). Because this new formatting path only reads parameters[i].Type, source-gen generic tests still publish System.Object instead of metadata names like !!0 or System.Collections.Generic.IEnumerable1<!!0>`, while reflection mode now publishes the correct placeholders; that leaves MTP method identity/source navigation wrong for those generic tests and violates the dual-mode requirement.

Useful? React with 👍 / 👎.

@codacy-production

Copy link
Copy Markdown

Not up to standards ⛔

🔴 Issues 3 medium · 1 minor

Alerts:
⚠ 4 issues (≤ 0 issues of at least minor severity)

Results:
4 new issues

Category Results
UnusedCode 1 minor
BestPractice 3 medium

View in Codacy

🟢 Metrics 19 complexity

Metric Results
Complexity 19

View in Codacy

NEW Get contextual insights on your PRs based on Codacy's metrics, along with PR and Jira context, without leaving GitHub. Enable AI reviewer
TIP This summary will be updated as you push new changes.

@thomhurst
thomhurst merged commit 080c62c into main Jul 16, 2026
14 of 15 checks passed
@thomhurst
thomhurst deleted the fix/method-identifier-metadata-type-names branch July 16, 2026 14:05
This was referenced Jul 16, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant