Skip to content

Comments

chore: migrate from .sln to .slnx solution format#4984

Merged
thomhurst merged 1 commit intomainfrom
migrate-sln-to-slnx
Feb 23, 2026
Merged

chore: migrate from .sln to .slnx solution format#4984
thomhurst merged 1 commit intomainfrom
migrate-sln-to-slnx

Conversation

@thomhurst
Copy link
Owner

Summary

  • Replace TUnit.sln with the new TUnit.slnx XML format via dotnet sln migrate
  • Update .vscode/tasks.json references (build, publish, watch tasks)
  • Update Dockerfile example in docs to COPY *.slnx .
  • No GitHub workflow changes needed — none referenced the .sln directly

Test plan

  • Verify dotnet build TUnit.slnx succeeds
  • Verify VS Code tasks still work
  • Verify CI pipelines pass

Copy link
Contributor

@claude claude bot left a comment

Choose a reason for hiding this comment

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

Code Review: chore: migrate from .sln to .slnx solution format

Overall, this is a clean, well-executed migration. The new format is significantly more readable (125 lines vs 1,333 lines) and eliminates the GUID-heavy noise of the legacy format. The folder hierarchy is preserved, and the tooling references are consistently updated.

Observations

Positive:

  • The XML format is far easier to review in diffs and resolve merge conflicts on — this is a genuine improvement to the developer experience.
  • All IDE/tooling references (, docs) are updated consistently.
  • The PR correctly notes that no GitHub Actions workflows referenced the directly.
  • Platform configurations (, , ) carry over correctly.

Concerns

1. Unorganized root-level Mocks projects

The following projects are listed at the root of the solution in rather than in any folder:

<Project Path="TUnit.Mocks.Analyzers.Tests/TUnit.Mocks.Analyzers.Tests.csproj" />
<Project Path="TUnit.Mocks.Analyzers/TUnit.Mocks.Analyzers.csproj" />
<Project Path="TUnit.Mocks.Assertions/TUnit.Mocks.Assertions.csproj" />
<!-- ... and many more TUnit.Mocks.* -->
<Project Path="TUnit.Logging.Microsoft/TUnit.Logging.Microsoft.csproj" />
<Project Path="TUnit.SourceGenerator.Benchmarks/TUnit.SourceGenerator.Benchmarks.csproj" />

This is inconsistent with the other projects which are organized into folders (, , etc.). If these were added to the solution after the last reorganization, they should be placed in appropriate folders (e.g., into and ). This isn't a blocking issue, but it's worth tidying up.

2. IDE/tooling compatibility — worth documenting

The format requires:

  • Visual Studio: 2022 17.12+
  • JetBrains Rider: 2024.2+
  • **
    Usage: dotnet [path-to-application]
    Usage: dotnet [commands]

path-to-application:
The path to an application .dll file to execute.

commands:
-h|--help Display help.
--info Display .NET information.
--list-runtimes [--arch ] Display the installed runtimes matching the host or specified architecture. Example architectures: arm64, x64, x86.
--list-sdks [--arch ] Display the installed SDKs matching the host or specified architecture. Example architectures: arm64, x64, x86. CLI**: .NET SDK 9+

Since TUnit targets , contributors using only .NET 8 SDK tooling may not be able to open the solution. The project already requires .NET SDK 10 via , so in practice this is fine — but it's worth a note in or the README for visibility.

3. Dockerfile documentation pattern

The change in :

-COPY *.sln .
+COPY *.slnx .

This is correct for TUnit's own CI example. However, users copying this Dockerfile template for their own projects will still have files. A brief inline comment (e.g., ) would make the example more transferable. Minor, but worth considering given this is public-facing documentation.


Summary

The migration itself is correct and the code is good. The main suggestion worth acting on is organizing the root-level Mocks/Logging/Benchmarks projects into appropriate solution folders to maintain the consistency established by the folder structure. The tooling compatibility and docs comment are minor nice-to-haves.

Copy link
Contributor

@claude claude bot left a comment

Choose a reason for hiding this comment

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

Code Review: chore: migrate from .sln to .slnx solution format

Overall, this is a clean, well-executed migration. The new .slnx format is significantly more readable (125 lines vs 1,333 lines) and eliminates the GUID-heavy noise of the legacy format. The folder hierarchy is preserved, and the tooling references are consistently updated.

Observations

Positive:

  • The XML format is far easier to review in diffs and resolve merge conflicts on — this is a genuine improvement to the developer experience.
  • All IDE/tooling references (.vscode/tasks.json, docs) are updated consistently.
  • The PR correctly notes that no GitHub Actions workflows referenced the .sln directly.
  • Platform configurations (Any CPU, x64, x86) carry over correctly.

Concerns

1. Unorganized root-level Mocks projects

Several projects appear at the root of TUnit.slnx rather than in any solution folder:

  • All TUnit.Mocks.* projects (analyzers, tests, source generators, etc.)
  • TUnit.Logging.Microsoft
  • TUnit.SourceGenerator.Benchmarks
  • TUnit.Aspire, TUnit.Assertions.FSharp, TUnit.Assertions.SourceGenerator, etc.

This is inconsistent with the rest of the solution where projects are organized into named folders (/Libraries/, /Test/, /Analyzers/, etc.). These projects were likely added to the solution after the original folder structure was set up and missed being categorized. Since the .slnx format makes this trivially easy to fix, it would be worth grouping them into appropriate folders (e.g., TUnit.Mocks.* into /Libraries/ and /Test/).

2. IDE/tooling compatibility

The .slnx format requires Visual Studio 2022 17.12+, JetBrains Rider 2024.2+, and .NET SDK 9+. The project's global.json already enforces .NET SDK 10+, so this is fine in practice. However, a brief note in CONTRIBUTING.md or the README callling out that .slnx requires modern tooling would help contributors who hit IDE issues.

3. Dockerfile docs pattern

The update to docs/docs/examples/tunit-ci-pipeline.md correctly reflects the new format for TUnit's own pipeline. Since this is public-facing example documentation that users copy for their own projects, consider adding a comment like # Use *.sln for projects still on the legacy format so the intent is clear to users who haven't migrated.


Summary

The migration is correct and well done. The main actionable suggestion is organizing the root-level projects (especially all the TUnit.Mocks.* entries) into appropriate solution folders to match the folder structure already established for the rest of the solution. The other two points are minor.

Replace TUnit.sln with the new TUnit.slnx XML format via
`dotnet sln migrate`, then reorganize all 86 projects into logical
folders for a better IDE experience:

- /Core/ — TUnit, TUnit.Core, TUnit.Engine, TUnit.Assertions
- /Libraries/ — Aspire, AspNetCore, FsCheck, Playwright, Logging, Mocks
- /Analyzers/ — all Roslyn analyzers and code fixers
- /SourceGenerators/ — all source generators and Roslyn variants
- /Tests/ — all test projects
- /Benchmarks/ — source generator benchmarks
- /Build/ — TUnit.Pipeline
- /Examples/ — playground and example projects
- /Templates/ — project templates (unchanged)

No projects were at the solution root previously without a folder;
now zero remain orphaned. Update .vscode/tasks.json and docs
Dockerfile example references.
Copy link
Contributor

@claude claude bot left a comment

Choose a reason for hiding this comment

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

Code Review: chore: migrate from .sln to .slnx solution format

Follow-up on Previous Review Comments

The two previous reviews raised a concern about root-level Mocks projects lacking folder organization. Checking the current PR HEAD (e35e99d): this has been addressed. All TUnit.Mocks.* projects are now correctly organized into appropriate folders (/Libraries/, /Analyzers/, /SourceGenerators/, /Tests/). The concern is resolved.


Current State Assessment

This is a clean, well-structured migration. The .slnx format cuts the solution file from 1,333 lines to ~125, eliminates GUID noise, and makes folder organization human-readable and diff-friendly. All tooling references (.vscode/tasks.json, docs Dockerfile example) are consistently updated.

All previous review concerns are now addressed.


Remaining Minor Observations

1. TUnit.Profile placement

TUnit.Profile is placed in the /Tests/ folder alongside test projects, but a /Benchmarks/ folder already exists (containing TUnit.SourceGenerator.Benchmarks). TUnit.Profile is a profiling project, not a test project. It would be more consistent to move it to /Benchmarks/:

<Folder Name="/Benchmarks/">
  <Project Path="TUnit.Profile/TUnit.Profile.csproj" />
  <Project Path="TUnit.SourceGenerator.Benchmarks/TUnit.SourceGenerator.Benchmarks.csproj" />
</Folder>

This keeps the categorization semantically accurate. Very minor, not blocking.

2. Dockerfile docs snippet

The change from COPY *.sln . to COPY *.slnx . is correct for TUnit's own pipeline. Since this is public-facing example docs that contributors copy for their own projects, a small inline comment would improve clarity for users who haven't migrated yet:

# Use *.sln if your project hasn't migrated to .slnx format yet
COPY *.slnx .

Not blocking, but this is a commonly copied snippet.


Summary

The migration is correct and the folder structure is well organized. The only actionable suggestion worth considering is moving TUnit.Profile from /Tests/ to /Benchmarks/ for consistency. Both remaining points are non-blocking. This is ready to merge.

Copy link
Contributor

@claude claude bot left a comment

Choose a reason for hiding this comment

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

Code Review: chore: migrate from .sln to .slnx solution format

Follow-up on Previous Review Comments

The two previous reviews raised a concern about root-level Mocks projects lacking folder organization. Checking the current PR HEAD (e35e99d): this has been addressed. All TUnit.Mocks.* projects are now correctly organized into appropriate folders (/Libraries/, /Analyzers/, /SourceGenerators/, /Tests/). The concern is resolved.


Current State Assessment

This is a clean, well-structured migration. The .slnx format cuts the solution file from 1,333 lines to ~125, eliminates GUID noise, and makes folder organization human-readable and diff-friendly. All tooling references (.vscode/tasks.json, docs Dockerfile example) are consistently updated.

All previous review concerns are now addressed.


Remaining Minor Observations

1. TUnit.Profile placement

TUnit.Profile sits in /Tests/ alongside test projects, but a /Benchmarks/ folder already exists (containing TUnit.SourceGenerator.Benchmarks). TUnit.Profile is a profiling project, not a test project. Moving it to /Benchmarks/ would keep the categorization semantically accurate:

<Folder Name="/Benchmarks/">
  <Project Path="TUnit.Profile/TUnit.Profile.csproj" />
  <Project Path="TUnit.SourceGenerator.Benchmarks/TUnit.SourceGenerator.Benchmarks.csproj" />
</Folder>

Very minor — the .slnx format makes this trivial to change.

2. Dockerfile docs snippet

The change from COPY *.sln . to COPY *.slnx . is correct for TUnit's own pipeline. Since this is public-facing example docs that users copy for their own projects, a small inline comment would improve clarity for those who haven't migrated yet:

# Use *.sln if your project hasn't migrated to .slnx format yet
COPY *.slnx .

Not blocking.


Summary

The migration is correct and all previous concerns are resolved. The only actionable suggestion is moving TUnit.Profile from /Tests/ to /Benchmarks/ for consistency. Both points above are non-blocking. This is ready to merge.

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