Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
The diff you're trying to view is too large. We only load the first 3000 changed files.
1 change: 1 addition & 0 deletions .claude/.sourcyignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

6 changes: 3 additions & 3 deletions .claude/docs/mandatory-rules.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@ TUnit supports two execution modes that MUST produce identical behavior:
## Rule 2: Snapshot Testing

Run snapshot tests when changing:
- Source generator output → `dotnet test TUnit.Core.SourceGenerator.Tests`
- Public APIs → `dotnet test TUnit.PublicAPI`
- Source generator output → `dotnet test tests/TUnit.Core.SourceGenerator.Tests`
- Public APIs → `dotnet test tests/TUnit.PublicAPI`

See `CLAUDE.md` for the quick fix workflow.

Expand Down Expand Up @@ -95,6 +95,6 @@ public void InvokeTest(MethodInfo method) { }
### Verification

```bash
cd TUnit.TestProject
cd tests/TUnit.TestProject
dotnet publish -c Release -p:PublishAot=true --use-current-runtime
```
16 changes: 15 additions & 1 deletion .claude/docs/project-structure.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,20 @@

---

## Repository Layout

| Directory | Contents |
|-----------|----------|
| `src/` | Product libraries, analyzers, source generators, integrations, templates, and packaged tools |
| `tests/` | Unit, integration, snapshot, fixture, and test-application projects |
| `benchmarks/` | Performance benchmarks and profiling workloads |
| `examples/` | Sample applications and test projects |
| `tools/` | CI pipeline and developer utilities |
| `eng/` | Shared MSBuild imports, signing key, and engineering assets |
| `scripts/` | Local test and profiling scripts |

Project names below are relative to their category directory. Production projects live under `src/`, test projects under `tests/`, and benchmark projects under `benchmarks/` unless noted.

## Core Projects

| Project | Purpose |
Expand All @@ -23,7 +37,7 @@
| `TUnit.PropertyTesting` | Property-based testing |
| `TUnit.FsCheck` | F#-based property testing integration |
| `TUnit.Playwright` | Browser testing integration |
| `TUnit.Pipeline` | CI/CD pipeline orchestration |
| `tools/TUnit.Pipeline` | CI/CD pipeline orchestration |
| `TUnit.Templates` | `dotnet new` project templates |

## Test Projects
Expand Down
2 changes: 1 addition & 1 deletion .claude/docs/troubleshooting.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ See `mandatory-rules.md` for annotation patterns.

**Diagnose**:
```bash
cd TUnit.Performance.Tests
cd benchmarks/TUnit.Performance.Tests
dotnet run -c Release
```

Expand Down
10 changes: 5 additions & 5 deletions .claude/docs/workflows.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ dotnet build TUnit.slnx --no-restore -graphBuild:True
dotnet test

# Snapshot tests
dotnet test TUnit.Core.SourceGenerator.Tests
dotnet test TUnit.PublicAPI
dotnet test tests/TUnit.Core.SourceGenerator.Tests
dotnet test tests/TUnit.PublicAPI

# Run specific test
dotnet test --treenode-filter "/*/*/ClassName/*"
Expand All @@ -41,15 +41,15 @@ Run benchmarks when changing hot paths (test discovery, execution, data generati

```bash
# Core performance benchmarks (BenchmarkDotNet)
cd TUnit.Performance.Tests
cd benchmarks/TUnit.Performance.Tests
dotnet run -c Release

# Source generator benchmarks
cd TUnit.SourceGenerator.Benchmarks
cd benchmarks/TUnit.SourceGenerator.Benchmarks
dotnet run -c Release

# Large-scale performance validation
cd TUnit.PerformanceBenchmarks
cd benchmarks/TUnit.PerformanceBenchmarks
dotnet run -c Release
```

Expand Down
6 changes: 3 additions & 3 deletions .github/CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -146,14 +146,14 @@ When contributing code to TUnit, please keep these important requirements in min

TUnit supports both source-generated and reflection-based test discovery. **All changes that affect test discovery or execution must work identically in both modes:**

- Source Generator path: `TUnit.Core.SourceGenerator`
- Reflection path: `TUnit.Engine`
- Source Generator path: `src/TUnit.Core.SourceGenerator`
- Reflection path: `src/TUnit.Engine`

#### Snapshot Testing

If your changes affect the source generator output or public APIs:

1. Run the relevant tests: `dotnet test TUnit.Core.SourceGenerator.Tests` or `dotnet test TUnit.PublicAPI`
1. Run the relevant tests: `dotnet test tests/TUnit.Core.SourceGenerator.Tests` or `dotnet test tests/TUnit.PublicAPI`
2. Review any `.received.txt` files generated
3. If the changes are intentional, rename them to `.verified.txt`
4. Commit the `.verified.txt` files with your changes
Expand Down
2 changes: 1 addition & 1 deletion .github/actions/execute-pipeline/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ runs:
- name: Run Pipeline
shell: bash
run: dotnet run -c Release --no-build --categories ${{ inputs.categories }}
working-directory: "TUnit.Pipeline"
working-directory: "tools/TUnit.Pipeline"
env:
ADMIN_TOKEN: ${{ inputs.admin-token }}
GITHUB_TOKEN: ${{ github.token }}
Expand Down
40 changes: 20 additions & 20 deletions .github/copilot-instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,14 @@
2. **SNAPSHOT TESTS ARE NON-NEGOTIABLE**
- After ANY change to source generator output:
```bash
dotnet test TUnit.Core.SourceGenerator.Tests
dotnet test tests/TUnit.Core.SourceGenerator.Tests
# Review .received.txt files, then:
for f in *.received.txt; do mv "$f" "${f%.received.txt}.verified.txt"; done # Linux/macOS
for %f in (*.received.txt) do move /Y "%f" "%~nf.verified.txt" # Windows
```
- After ANY public API change (TUnit.Core, TUnit.Engine, TUnit.Assertions):
```bash
dotnet test TUnit.PublicAPI
dotnet test tests/TUnit.PublicAPI
# Review and accept snapshots as above
```
- Commit ALL `.verified.txt` files. These are the source of truth.
Expand Down Expand Up @@ -67,17 +67,17 @@

```bash
# ❌ WRONG - Will show many "failures" (this is expected behavior)
cd TUnit.TestProject && dotnet run
cd TUnit.TestProject && dotnet test
cd tests/TUnit.TestProject && dotnet run
cd tests/TUnit.TestProject && dotnet test

# ✅ CORRECT - Always use targeted filters when testing TUnit.TestProject
cd TUnit.TestProject && dotnet test --treenode-filter "/*/*/SpecificClass/*"
cd TUnit.TestProject && dotnet test --treenode-filter "/*/*/*/*[Category!=Performance]"
cd tests/TUnit.TestProject && dotnet test --treenode-filter "/*/*/SpecificClass/*"
cd tests/TUnit.TestProject && dotnet test --treenode-filter "/*/*/*/*[Category!=Performance]"

# ✅ CORRECT - Test other test projects normally (they don't have intentional failures)
dotnet test TUnit.Engine.Tests
dotnet test TUnit.Assertions.Tests
dotnet test TUnit.Core.SourceGenerator.Tests
dotnet test tests/TUnit.Engine.Tests
dotnet test tests/TUnit.Assertions.Tests
dotnet test tests/TUnit.Core.SourceGenerator.Tests
```

**Why TUnit.TestProject is special:**
Expand All @@ -98,11 +98,11 @@ dotnet test TUnit.Core.SourceGenerator.Tests
dotnet test

# Test source generator + accept snapshots
dotnet test TUnit.Core.SourceGenerator.Tests
dotnet test tests/TUnit.Core.SourceGenerator.Tests
for f in *.received.txt; do mv "$f" "${f%.received.txt}.verified.txt"; done

# Test public API + accept snapshots
dotnet test TUnit.PublicAPI
dotnet test tests/TUnit.PublicAPI
for f in *.received.txt; do mv "$f" "${f%.received.txt}.verified.txt"; done

# Run specific test by tree node filter
Expand Down Expand Up @@ -270,13 +270,13 @@ TUnit has two execution paths that **MUST** behave identically:
dotnet test

# If source generator changed, accept snapshots
cd TUnit.Core.SourceGenerator.Tests
cd tests/TUnit.Core.SourceGenerator.Tests
dotnet test
# Review .received.txt files
for f in *.received.txt; do mv "$f" "${f%.received.txt}.verified.txt"; done

# If public API changed, accept snapshots
cd TUnit.PublicAPI
cd tests/TUnit.PublicAPI
dotnet test
# Review .received.txt files
for f in *.received.txt; do mv "$f" "${f%.received.txt}.verified.txt"; done
Expand All @@ -285,13 +285,13 @@ TUnit has two execution paths that **MUST** behave identically:
4. **Performance Check**
```bash
# Run benchmarks (if touching hot paths)
cd TUnit.Performance.Tests
cd benchmarks/TUnit.Performance.Tests
dotnet run -c Release --framework net9.0
```

5. **AOT Verification** (if touching reflection)
```bash
cd TUnit.TestProject
cd tests/TUnit.TestProject
dotnet publish -c Release -p:PublishAot=true --use-current-runtime
```

Expand Down Expand Up @@ -647,7 +647,7 @@ public Task GeneratesCorrectCode_ForSimpleTest()
**Accepting Snapshots:**
```bash
# After verifying .received.txt files are correct:
cd TUnit.Core.SourceGenerator.Tests
cd tests/TUnit.Core.SourceGenerator.Tests
for f in *.received.txt; do mv "$f" "${f%.received.txt}.verified.txt"; done

# Commit the .verified.txt files
Expand Down Expand Up @@ -785,7 +785,7 @@ public async Task BeforeAllTestsHook_ExecutesOnce(ExecutionMode mode)
### Adding Analyzer Rules

```csharp
// TUnit.Analyzers/Rules/TestMethodMustBePublic.cs
// src/TUnit.Analyzers/Rules/TestMethodMustBePublic.cs

[DiagnosticAnalyzer(LanguageNames.CSharp)]
public class TestMethodMustBePublicAnalyzer : DiagnosticAnalyzer
Expand Down Expand Up @@ -826,7 +826,7 @@ public class TestMethodMustBePublicAnalyzer : DiagnosticAnalyzer
### Adding Assertions

```csharp
// TUnit.Assertions/Extensions/NumericAssertions.cs
// src/TUnit.Assertions/Extensions/NumericAssertions.cs

public static class NumericAssertions
{
Expand Down Expand Up @@ -863,7 +863,7 @@ await Assert.That(value).IsPositive();
**Solution**:
```bash
# 1. Review the .received.txt files to see what changed
cd TUnit.Core.SourceGenerator.Tests # or TUnit.PublicAPI
cd tests/TUnit.Core.SourceGenerator.Tests # or tests/TUnit.PublicAPI
ls *.received.txt

# 2. If changes are intentional (you modified the generator or public API):
Expand Down Expand Up @@ -955,7 +955,7 @@ public void InvokeTestMethod(MethodInfo method) { }
**Diagnostic**:
```bash
# Run performance benchmarks
cd TUnit.Performance.Tests
cd benchmarks/TUnit.Performance.Tests
dotnet run -c Release --framework net9.0

# Profile with dotnet-trace
Expand Down
2 changes: 1 addition & 1 deletion .github/scripts/process-mock-benchmarks.js
Original file line number Diff line number Diff line change
Expand Up @@ -416,7 +416,7 @@ This makes TUnit.Mocks compatible with **Native AOT** and **IL trimming**, while
### Source Code
All benchmark source code is available in the [\`TUnit.Mocks.Benchmarks\`](https://github.com/thomhurst/TUnit/tree/main/TUnit.Mocks.Benchmarks) directory.
All benchmark source code is available in the [\`TUnit.Mocks.Benchmarks\`](https://github.com/thomhurst/TUnit/tree/main/benchmarks/TUnit.Mocks.Benchmarks) directory.
---
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/dotnet-build-different-locale.yml
Original file line number Diff line number Diff line change
Expand Up @@ -53,4 +53,4 @@ jobs:
- name: Build
run: dotnet build -c Release
working-directory: TUnit.TestProject
working-directory: tests/TUnit.TestProject
2 changes: 1 addition & 1 deletion .github/workflows/dotnet.yml
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ jobs:
- name: Publish AOT
shell: bash
run: >-
dotnet publish TUnit.TestProject/TUnit.TestProject.csproj -c Release
dotnet publish tests/TUnit.TestProject/TUnit.TestProject.csproj -c Release
--use-current-runtime -p:Aot=true -o TESTPROJECT_AOT --framework net10.0
"-p:Version=${{ steps.gitversion.outputs.semVer }}"
"-p:AssemblyVersion=${{ steps.gitversion.outputs.assemblySemVer }}"
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/mock-benchmarks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ jobs:

- name: Run Benchmark
run: dotnet run -c Release -f net10.0 -- --filter "*${{ matrix.benchmark }}*" --exporters json github
working-directory: "TUnit.Mocks.Benchmarks"
working-directory: "benchmarks/TUnit.Mocks.Benchmarks"

- name: Upload Results
uses: actions/upload-artifact@v7
Expand Down
4 changes: 2 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -416,8 +416,8 @@ requirements/
**/SourceGeneratedViewer/

# TUnit test output files
TUnit.TestProject/TestDiscovery*.txt
TUnit.TestProject/TestSession*.txt
tests/TUnit.TestProject/TestDiscovery*.txt
tests/TUnit.TestProject/TestSession*.txt

.mcp.json
requirements
Expand Down
6 changes: 3 additions & 3 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@
"request": "launch",
"preLaunchTask": "build",
// If you have changed target frameworks, make sure to update the program path.
"program": "${workspaceFolder}/TUnit.TestProject/bin/Debug/net8.0/TUnit.TestProject.dll",
"program": "${workspaceFolder}/tests/TUnit.TestProject/bin/Debug/net8.0/TUnit.TestProject.dll",
"args": [],
"cwd": "${workspaceFolder}/TUnit.TestProject",
"cwd": "${workspaceFolder}/tests/TUnit.TestProject",
// For more information about the 'console' field, see https://aka.ms/VSCode-CS-LaunchJson-Console
"console": "internalConsole",
"stopAtEntry": false
Expand All @@ -23,4 +23,4 @@
"request": "attach"
}
]
}
}
4 changes: 2 additions & 2 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ See `.claude/docs/mandatory-rules.md` for full details.

**NEVER run `TUnit.TestProject` without filters.** Many tests are designed to fail.
```bash
cd TUnit.TestProject
cd tests/TUnit.TestProject
dotnet test --treenode-filter "/*/*/SpecificClass/*"
```
See `.claude/docs/workflows.md` for filter syntax and details.
Expand All @@ -31,7 +31,7 @@ See `.claude/docs/workflows.md` for filter syntax and details.

```bash
# Review changes, then accept if intentional:
# (Run from test project directory, e.g., TUnit.Core.SourceGenerator.Tests)
# (Run from test project directory, e.g., tests/TUnit.Core.SourceGenerator.Tests)

# Linux/macOS:
for f in *.received.txt; do mv "$f" "${f%.received.txt}.verified.txt"; done
Expand Down
12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -331,6 +331,18 @@ TUnit runs F# and VB.NET test projects too, and `TUnit.Assertions.FSharp` provid

The syntax will feel familiar. For example, xUnit's `[Fact]` becomes `[Test]`, and `[Theory]` + `[InlineData]` becomes `[Test]` + `[Arguments]`. See the migration guides for full details: [xUnit](https://tunit.dev/docs/migration/xunit) · [NUnit](https://tunit.dev/docs/migration/nunit) · [MSTest](https://tunit.dev/docs/migration/mstest).

## Repository layout

- `src/` — product libraries, analyzers, source generators, integrations, templates, and tools shipped as packages
- `tests/` — unit, integration, snapshot, fixture, and cross-language test projects
- `benchmarks/` — BenchmarkDotNet and profiling workloads
- `examples/` — sample applications and test projects
- `tools/` — repository automation and development utilities
- `eng/` — shared MSBuild imports, signing key, and engineering assets
- `scripts/` — local build, test, and profiling entry points

Solutions and repository-wide SDK, package, and build configuration remain at root.

## Community

- [Documentation](https://tunit.dev) — guides, tutorials, and API reference
Expand Down
5 changes: 0 additions & 5 deletions TUnit.Analyzers.Roslyn414/TUnit.Analyzers.Roslyn414.csproj

This file was deleted.

5 changes: 0 additions & 5 deletions TUnit.Analyzers.Roslyn44/TUnit.Analyzers.Roslyn44.csproj

This file was deleted.

5 changes: 0 additions & 5 deletions TUnit.Analyzers.Roslyn47/TUnit.Analyzers.Roslyn47.csproj

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

Loading
Loading