From 58338f6771cf6ede03f4c6f8f93bf13d5b55a295 Mon Sep 17 00:00:00 2001 From: Tom Longhurst <30480171+thomhurst@users.noreply.github.com> Date: Thu, 15 May 2025 08:42:05 +0100 Subject: [PATCH 1/4] chore(deps): update aspire to 9.2.1 (#2236) Co-authored-by: Renovate Bot --- .../ExampleNamespace.AppHost.csproj | 6 +++--- .../ExampleNamespace.TestProject.csproj | 2 +- .../ExampleNamespace.WebApp/ExampleNamespace.WebApp.csproj | 2 +- .../content/TUnit.Aspire.Test/ExampleNamespace.csproj | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/TUnit.Templates/content/TUnit.Aspire.Starter/ExampleNamespace.AppHost/ExampleNamespace.AppHost.csproj b/TUnit.Templates/content/TUnit.Aspire.Starter/ExampleNamespace.AppHost/ExampleNamespace.AppHost.csproj index 07e052c965..5b7ad83116 100644 --- a/TUnit.Templates/content/TUnit.Aspire.Starter/ExampleNamespace.AppHost/ExampleNamespace.AppHost.csproj +++ b/TUnit.Templates/content/TUnit.Aspire.Starter/ExampleNamespace.AppHost/ExampleNamespace.AppHost.csproj @@ -1,6 +1,6 @@  - + Exe @@ -12,8 +12,8 @@ - - + + diff --git a/TUnit.Templates/content/TUnit.Aspire.Starter/ExampleNamespace.TestProject/ExampleNamespace.TestProject.csproj b/TUnit.Templates/content/TUnit.Aspire.Starter/ExampleNamespace.TestProject/ExampleNamespace.TestProject.csproj index 03ba0b34c4..5eda00a26b 100644 --- a/TUnit.Templates/content/TUnit.Aspire.Starter/ExampleNamespace.TestProject/ExampleNamespace.TestProject.csproj +++ b/TUnit.Templates/content/TUnit.Aspire.Starter/ExampleNamespace.TestProject/ExampleNamespace.TestProject.csproj @@ -10,7 +10,7 @@ - + diff --git a/TUnit.Templates/content/TUnit.Aspire.Starter/ExampleNamespace.WebApp/ExampleNamespace.WebApp.csproj b/TUnit.Templates/content/TUnit.Aspire.Starter/ExampleNamespace.WebApp/ExampleNamespace.WebApp.csproj index 9f36b86edc..1db611f967 100644 --- a/TUnit.Templates/content/TUnit.Aspire.Starter/ExampleNamespace.WebApp/ExampleNamespace.WebApp.csproj +++ b/TUnit.Templates/content/TUnit.Aspire.Starter/ExampleNamespace.WebApp/ExampleNamespace.WebApp.csproj @@ -7,7 +7,7 @@ - + diff --git a/TUnit.Templates/content/TUnit.Aspire.Test/ExampleNamespace.csproj b/TUnit.Templates/content/TUnit.Aspire.Test/ExampleNamespace.csproj index 6ce3e95f5f..7e4f6a9eeb 100644 --- a/TUnit.Templates/content/TUnit.Aspire.Test/ExampleNamespace.csproj +++ b/TUnit.Templates/content/TUnit.Aspire.Test/ExampleNamespace.csproj @@ -9,7 +9,7 @@ - + From e67d2db6df5a4e81d40931a64afeeade357c1f9e Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 16 May 2025 07:11:01 +0100 Subject: [PATCH 2/4] Update README.md (#2387) Co-authored-by: thomhurst <30480171_thomhurst@users.noreply.github.com> --- README.md | 96 +++++++++++++++++++++++++++---------------------------- 1 file changed, 48 insertions(+), 48 deletions(-) diff --git a/README.md b/README.md index ef394c32c3..ea32e1d81f 100644 --- a/README.md +++ b/README.md @@ -289,12 +289,12 @@ Apple M1 (Virtual), 1 CPU, 3 logical and 3 physical cores Job=.NET 9.0 Runtime=.NET 9.0 ``` -| Method | Mean | Error | StdDev | -|------------- |--------:|---------:|---------:| -| Build_TUnit | 1.874 s | 0.0958 s | 0.2795 s | -| Build_NUnit | 1.287 s | 0.0412 s | 0.1210 s | -| Build_xUnit | 1.308 s | 0.0404 s | 0.1173 s | -| Build_MSTest | 1.406 s | 0.0426 s | 0.1250 s | +| Method | Mean | Error | StdDev | Median | +|------------- |-----------:|---------:|----------:|-----------:| +| Build_TUnit | 1,196.3 ms | 87.14 ms | 255.57 ms | 1,108.9 ms | +| Build_NUnit | 976.1 ms | 21.23 ms | 61.60 ms | 969.0 ms | +| Build_xUnit | 1,033.8 ms | 30.35 ms | 87.07 ms | 1,012.0 ms | +| Build_MSTest | 1,064.2 ms | 80.16 ms | 236.34 ms | 1,016.7 ms | @@ -313,10 +313,10 @@ Job=.NET 9.0 Runtime=.NET 9.0 ``` | Method | Mean | Error | StdDev | |------------- |--------:|---------:|---------:| -| Build_TUnit | 1.861 s | 0.0231 s | 0.0204 s | -| Build_NUnit | 1.424 s | 0.0117 s | 0.0109 s | -| Build_xUnit | 1.438 s | 0.0142 s | 0.0126 s | -| Build_MSTest | 1.454 s | 0.0120 s | 0.0112 s | +| Build_TUnit | 1.880 s | 0.0299 s | 0.0249 s | +| Build_NUnit | 1.459 s | 0.0116 s | 0.0103 s | +| Build_xUnit | 1.445 s | 0.0105 s | 0.0093 s | +| Build_MSTest | 1.467 s | 0.0141 s | 0.0132 s | @@ -335,10 +335,10 @@ Job=.NET 9.0 Runtime=.NET 9.0 ``` | Method | Mean | Error | StdDev | |------------- |--------:|---------:|---------:| -| Build_TUnit | 1.883 s | 0.0356 s | 0.0366 s | -| Build_NUnit | 1.457 s | 0.0106 s | 0.0088 s | -| Build_xUnit | 1.473 s | 0.0270 s | 0.0225 s | -| Build_MSTest | 1.500 s | 0.0141 s | 0.0131 s | +| Build_TUnit | 1.928 s | 0.0372 s | 0.0330 s | +| Build_NUnit | 1.504 s | 0.0167 s | 0.0140 s | +| Build_xUnit | 1.498 s | 0.0279 s | 0.0233 s | +| Build_MSTest | 1.527 s | 0.0233 s | 0.0218 s | ### Scenario: A single test that completes instantly (including spawning a new process and initialising the test framework) @@ -356,13 +356,13 @@ Apple M1 (Virtual), 1 CPU, 3 logical and 3 physical cores Job=.NET 9.0 Runtime=.NET 9.0 ``` -| Method | Mean | Error | StdDev | -|---------- |----------:|----------:|----------:| -| TUnit_AOT | 66.19 ms | 0.391 ms | 0.346 ms | -| TUnit | 501.76 ms | 10.005 ms | 15.576 ms | -| NUnit | 700.61 ms | 4.639 ms | 4.112 ms | -| xUnit | 715.20 ms | 5.205 ms | 4.614 ms | -| MSTest | 617.98 ms | 3.197 ms | 2.670 ms | +| Method | Mean | Error | StdDev | Median | +|---------- |----------:|----------:|-----------:|----------:| +| TUnit_AOT | 79.11 ms | 1.554 ms | 1.454 ms | 78.67 ms | +| TUnit | 576.59 ms | 36.021 ms | 106.209 ms | 542.81 ms | +| NUnit | 748.01 ms | 14.432 ms | 26.024 ms | 746.05 ms | +| xUnit | 720.94 ms | 6.845 ms | 6.403 ms | 720.02 ms | +| MSTest | 628.81 ms | 8.047 ms | 6.282 ms | 630.57 ms | @@ -381,11 +381,11 @@ Job=.NET 9.0 Runtime=.NET 9.0 ``` | Method | Mean | Error | StdDev | |---------- |------------:|----------:|----------:| -| TUnit_AOT | 24.78 ms | 0.562 ms | 1.647 ms | -| TUnit | 810.22 ms | 15.765 ms | 17.522 ms | -| NUnit | 1,280.55 ms | 10.317 ms | 9.650 ms | -| xUnit | 1,334.41 ms | 11.679 ms | 10.925 ms | -| MSTest | 1,145.71 ms | 16.351 ms | 15.295 ms | +| TUnit_AOT | 26.02 ms | 0.612 ms | 1.805 ms | +| TUnit | 811.68 ms | 15.880 ms | 18.287 ms | +| NUnit | 1,285.99 ms | 12.210 ms | 11.421 ms | +| xUnit | 1,341.96 ms | 11.491 ms | 10.186 ms | +| MSTest | 1,130.38 ms | 7.813 ms | 7.308 ms | @@ -404,11 +404,11 @@ Job=.NET 9.0 Runtime=.NET 9.0 ``` | Method | Mean | Error | StdDev | |---------- |------------:|----------:|----------:| -| TUnit_AOT | 56.53 ms | 1.723 ms | 5.082 ms | -| TUnit | 858.40 ms | 17.018 ms | 27.961 ms | -| NUnit | 1,313.50 ms | 22.551 ms | 19.991 ms | -| xUnit | 1,357.87 ms | 18.671 ms | 16.551 ms | -| MSTest | 1,154.28 ms | 13.186 ms | 12.334 ms | +| TUnit_AOT | 56.95 ms | 1.909 ms | 5.599 ms | +| TUnit | 852.71 ms | 16.888 ms | 25.790 ms | +| NUnit | 1,310.94 ms | 11.451 ms | 10.711 ms | +| xUnit | 1,360.91 ms | 16.567 ms | 15.496 ms | +| MSTest | 1,166.01 ms | 15.708 ms | 14.693 ms | ### Scenario: A test that takes 50ms to execute, repeated 100 times (including spawning a new process and initialising the test framework) @@ -428,11 +428,11 @@ Job=.NET 9.0 Runtime=.NET 9.0 ``` | Method | Mean | Error | StdDev | |---------- |------------:|----------:|----------:| -| TUnit_AOT | 246.6 ms | 14.68 ms | 43.27 ms | -| TUnit | 640.9 ms | 21.10 ms | 62.23 ms | -| NUnit | 14,260.7 ms | 283.90 ms | 533.23 ms | -| xUnit | 14,476.0 ms | 285.56 ms | 409.54 ms | -| MSTest | 14,455.3 ms | 258.04 ms | 228.75 ms | +| TUnit_AOT | 242.8 ms | 15.84 ms | 46.69 ms | +| TUnit | 676.1 ms | 26.68 ms | 78.68 ms | +| NUnit | 13,799.6 ms | 275.92 ms | 524.96 ms | +| xUnit | 14,225.4 ms | 284.10 ms | 617.61 ms | +| MSTest | 14,176.5 ms | 280.68 ms | 476.61 ms | @@ -451,11 +451,11 @@ Job=.NET 9.0 Runtime=.NET 9.0 ``` | Method | Mean | Error | StdDev | |---------- |------------:|----------:|----------:| -| TUnit_AOT | 75.10 ms | 1.493 ms | 2.044 ms | -| TUnit | 896.80 ms | 17.246 ms | 16.938 ms | -| NUnit | 6,295.21 ms | 20.675 ms | 19.340 ms | -| xUnit | 6,435.26 ms | 18.831 ms | 17.614 ms | -| MSTest | 6,245.08 ms | 10.851 ms | 9.620 ms | +| TUnit_AOT | 75.40 ms | 1.450 ms | 1.612 ms | +| TUnit | 897.28 ms | 17.681 ms | 21.049 ms | +| NUnit | 6,297.87 ms | 11.476 ms | 10.734 ms | +| xUnit | 6,440.78 ms | 8.735 ms | 7.744 ms | +| MSTest | 6,273.68 ms | 15.032 ms | 14.061 ms | @@ -472,13 +472,13 @@ AMD EPYC 7763, 1 CPU, 4 logical and 2 physical cores Job=.NET 9.0 Runtime=.NET 9.0 ``` -| Method | Mean | Error | StdDev | -|---------- |-----------:|---------:|---------:| -| TUnit_AOT | 110.7 ms | 2.15 ms | 2.39 ms | -| TUnit | 953.0 ms | 18.10 ms | 22.89 ms | -| NUnit | 7,523.8 ms | 24.16 ms | 22.60 ms | -| xUnit | 7,579.1 ms | 25.45 ms | 23.81 ms | -| MSTest | 7,436.2 ms | 26.15 ms | 24.46 ms | +| Method | Mean | Error | StdDev | Median | +|---------- |-----------:|---------:|---------:|-----------:| +| TUnit_AOT | 112.7 ms | 2.25 ms | 4.54 ms | 109.5 ms | +| TUnit | 928.8 ms | 17.98 ms | 24.60 ms | 923.5 ms | +| NUnit | 7,489.2 ms | 22.25 ms | 19.73 ms | 7,488.3 ms | +| xUnit | 7,547.4 ms | 21.40 ms | 18.97 ms | 7,545.9 ms | +| MSTest | 7,430.8 ms | 43.95 ms | 41.11 ms | 7,433.7 ms | From beb9e247359f2f4b64850edcf39178635988468b Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sat, 17 May 2025 07:09:45 +0100 Subject: [PATCH 3/4] Update README.md (#2389) Co-authored-by: thomhurst <30480171_thomhurst@users.noreply.github.com> --- README.md | 100 +++++++++++++++++++++++++++--------------------------- 1 file changed, 50 insertions(+), 50 deletions(-) diff --git a/README.md b/README.md index ea32e1d81f..7c40b094f9 100644 --- a/README.md +++ b/README.md @@ -289,12 +289,12 @@ Apple M1 (Virtual), 1 CPU, 3 logical and 3 physical cores Job=.NET 9.0 Runtime=.NET 9.0 ``` -| Method | Mean | Error | StdDev | Median | -|------------- |-----------:|---------:|----------:|-----------:| -| Build_TUnit | 1,196.3 ms | 87.14 ms | 255.57 ms | 1,108.9 ms | -| Build_NUnit | 976.1 ms | 21.23 ms | 61.60 ms | 969.0 ms | -| Build_xUnit | 1,033.8 ms | 30.35 ms | 87.07 ms | 1,012.0 ms | -| Build_MSTest | 1,064.2 ms | 80.16 ms | 236.34 ms | 1,016.7 ms | +| Method | Mean | Error | StdDev | +|------------- |-----------:|---------:|---------:| +| Build_TUnit | 1,033.2 ms | 28.29 ms | 80.71 ms | +| Build_NUnit | 806.4 ms | 11.36 ms | 9.49 ms | +| Build_xUnit | 780.2 ms | 15.29 ms | 15.01 ms | +| Build_MSTest | 860.2 ms | 17.13 ms | 28.61 ms | @@ -313,10 +313,10 @@ Job=.NET 9.0 Runtime=.NET 9.0 ``` | Method | Mean | Error | StdDev | |------------- |--------:|---------:|---------:| -| Build_TUnit | 1.880 s | 0.0299 s | 0.0249 s | -| Build_NUnit | 1.459 s | 0.0116 s | 0.0103 s | -| Build_xUnit | 1.445 s | 0.0105 s | 0.0093 s | -| Build_MSTest | 1.467 s | 0.0141 s | 0.0132 s | +| Build_TUnit | 1.937 s | 0.0372 s | 0.0443 s | +| Build_NUnit | 1.497 s | 0.0155 s | 0.0145 s | +| Build_xUnit | 1.492 s | 0.0110 s | 0.0098 s | +| Build_MSTest | 1.527 s | 0.0240 s | 0.0224 s | @@ -335,10 +335,10 @@ Job=.NET 9.0 Runtime=.NET 9.0 ``` | Method | Mean | Error | StdDev | |------------- |--------:|---------:|---------:| -| Build_TUnit | 1.928 s | 0.0372 s | 0.0330 s | -| Build_NUnit | 1.504 s | 0.0167 s | 0.0140 s | -| Build_xUnit | 1.498 s | 0.0279 s | 0.0233 s | -| Build_MSTest | 1.527 s | 0.0233 s | 0.0218 s | +| Build_TUnit | 2.036 s | 0.0397 s | 0.0516 s | +| Build_NUnit | 1.592 s | 0.0264 s | 0.0247 s | +| Build_xUnit | 1.587 s | 0.0289 s | 0.0271 s | +| Build_MSTest | 1.606 s | 0.0244 s | 0.0216 s | ### Scenario: A single test that completes instantly (including spawning a new process and initialising the test framework) @@ -356,13 +356,13 @@ Apple M1 (Virtual), 1 CPU, 3 logical and 3 physical cores Job=.NET 9.0 Runtime=.NET 9.0 ``` -| Method | Mean | Error | StdDev | Median | -|---------- |----------:|----------:|-----------:|----------:| -| TUnit_AOT | 79.11 ms | 1.554 ms | 1.454 ms | 78.67 ms | -| TUnit | 576.59 ms | 36.021 ms | 106.209 ms | 542.81 ms | -| NUnit | 748.01 ms | 14.432 ms | 26.024 ms | 746.05 ms | -| xUnit | 720.94 ms | 6.845 ms | 6.403 ms | 720.02 ms | -| MSTest | 628.81 ms | 8.047 ms | 6.282 ms | 630.57 ms | +| Method | Mean | Error | StdDev | +|---------- |----------:|----------:|----------:| +| TUnit_AOT | 74.55 ms | 0.637 ms | 0.532 ms | +| TUnit | 473.61 ms | 8.172 ms | 6.824 ms | +| NUnit | 706.57 ms | 11.663 ms | 10.339 ms | +| xUnit | 735.63 ms | 14.611 ms | 21.417 ms | +| MSTest | 627.55 ms | 8.620 ms | 8.063 ms | @@ -381,11 +381,11 @@ Job=.NET 9.0 Runtime=.NET 9.0 ``` | Method | Mean | Error | StdDev | |---------- |------------:|----------:|----------:| -| TUnit_AOT | 26.02 ms | 0.612 ms | 1.805 ms | -| TUnit | 811.68 ms | 15.880 ms | 18.287 ms | -| NUnit | 1,285.99 ms | 12.210 ms | 11.421 ms | -| xUnit | 1,341.96 ms | 11.491 ms | 10.186 ms | -| MSTest | 1,130.38 ms | 7.813 ms | 7.308 ms | +| TUnit_AOT | 26.19 ms | 0.618 ms | 1.822 ms | +| TUnit | 802.91 ms | 15.800 ms | 16.226 ms | +| NUnit | 1,276.56 ms | 8.989 ms | 8.408 ms | +| xUnit | 1,340.94 ms | 15.552 ms | 12.987 ms | +| MSTest | 1,137.70 ms | 17.369 ms | 15.397 ms | @@ -402,13 +402,13 @@ AMD EPYC 7763, 1 CPU, 4 logical and 2 physical cores Job=.NET 9.0 Runtime=.NET 9.0 ``` -| Method | Mean | Error | StdDev | -|---------- |------------:|----------:|----------:| -| TUnit_AOT | 56.95 ms | 1.909 ms | 5.599 ms | -| TUnit | 852.71 ms | 16.888 ms | 25.790 ms | -| NUnit | 1,310.94 ms | 11.451 ms | 10.711 ms | -| xUnit | 1,360.91 ms | 16.567 ms | 15.496 ms | -| MSTest | 1,166.01 ms | 15.708 ms | 14.693 ms | +| Method | Mean | Error | StdDev | Median | +|---------- |------------:|----------:|----------:|------------:| +| TUnit_AOT | 59.48 ms | 2.295 ms | 6.766 ms | 57.45 ms | +| TUnit | 848.39 ms | 16.816 ms | 21.866 ms | 851.96 ms | +| NUnit | 1,295.08 ms | 8.461 ms | 7.914 ms | 1,298.54 ms | +| xUnit | 1,332.47 ms | 13.329 ms | 11.815 ms | 1,334.11 ms | +| MSTest | 1,145.93 ms | 7.210 ms | 6.392 ms | 1,145.01 ms | ### Scenario: A test that takes 50ms to execute, repeated 100 times (including spawning a new process and initialising the test framework) @@ -428,11 +428,11 @@ Job=.NET 9.0 Runtime=.NET 9.0 ``` | Method | Mean | Error | StdDev | |---------- |------------:|----------:|----------:| -| TUnit_AOT | 242.8 ms | 15.84 ms | 46.69 ms | -| TUnit | 676.1 ms | 26.68 ms | 78.68 ms | -| NUnit | 13,799.6 ms | 275.92 ms | 524.96 ms | -| xUnit | 14,225.4 ms | 284.10 ms | 617.61 ms | -| MSTest | 14,176.5 ms | 280.68 ms | 476.61 ms | +| TUnit_AOT | 243.7 ms | 13.22 ms | 38.57 ms | +| TUnit | 646.5 ms | 23.49 ms | 68.52 ms | +| NUnit | 14,101.3 ms | 281.41 ms | 581.15 ms | +| xUnit | 14,368.1 ms | 282.80 ms | 517.11 ms | +| MSTest | 14,327.9 ms | 281.44 ms | 599.78 ms | @@ -449,13 +449,13 @@ AMD EPYC 7763, 1 CPU, 4 logical and 2 physical cores Job=.NET 9.0 Runtime=.NET 9.0 ``` -| Method | Mean | Error | StdDev | -|---------- |------------:|----------:|----------:| -| TUnit_AOT | 75.40 ms | 1.450 ms | 1.612 ms | -| TUnit | 897.28 ms | 17.681 ms | 21.049 ms | -| NUnit | 6,297.87 ms | 11.476 ms | 10.734 ms | -| xUnit | 6,440.78 ms | 8.735 ms | 7.744 ms | -| MSTest | 6,273.68 ms | 15.032 ms | 14.061 ms | +| Method | Mean | Error | StdDev | Median | +|---------- |------------:|----------:|----------:|------------:| +| TUnit_AOT | 75.34 ms | 1.474 ms | 2.252 ms | 74.12 ms | +| TUnit | 874.94 ms | 17.026 ms | 18.925 ms | 875.78 ms | +| NUnit | 6,264.58 ms | 6.884 ms | 6.439 ms | 6,265.88 ms | +| xUnit | 6,401.00 ms | 10.440 ms | 9.766 ms | 6,400.99 ms | +| MSTest | 6,225.42 ms | 10.452 ms | 9.777 ms | 6,223.81 ms | @@ -474,11 +474,11 @@ Job=.NET 9.0 Runtime=.NET 9.0 ``` | Method | Mean | Error | StdDev | Median | |---------- |-----------:|---------:|---------:|-----------:| -| TUnit_AOT | 112.7 ms | 2.25 ms | 4.54 ms | 109.5 ms | -| TUnit | 928.8 ms | 17.98 ms | 24.60 ms | 923.5 ms | -| NUnit | 7,489.2 ms | 22.25 ms | 19.73 ms | 7,488.3 ms | -| xUnit | 7,547.4 ms | 21.40 ms | 18.97 ms | 7,545.9 ms | -| MSTest | 7,430.8 ms | 43.95 ms | 41.11 ms | 7,433.7 ms | +| TUnit_AOT | 109.4 ms | 1.21 ms | 0.95 ms | 109.2 ms | +| TUnit | 921.3 ms | 18.06 ms | 22.85 ms | 907.7 ms | +| NUnit | 7,487.3 ms | 19.78 ms | 18.50 ms | 7,488.5 ms | +| xUnit | 7,547.4 ms | 25.20 ms | 23.57 ms | 7,550.2 ms | +| MSTest | 7,425.2 ms | 25.38 ms | 23.74 ms | 7,427.1 ms | From 31fe062af09495c5e37a225882af51869870c677 Mon Sep 17 00:00:00 2001 From: Tom Longhurst <30480171+thomhurst@users.noreply.github.com> Date: Sat, 17 May 2025 12:20:06 +0100 Subject: [PATCH 4/4] FSharp Assertions (#2388) * FSharp Assertions * Import library props * Pack TUnit_Assertions_FSharp * FSharp doc * Fix --- TUnit.Assertions.FSharp/Extensions.fs | 17 ++++++++++ .../TUnit.Assertions.FSharp.fsproj | 15 +++++++++ .../TUnit.Assertions.FSharp.props | 13 ++++++++ TUnit.Assertions/TUnit.Assertions.props | 3 ++ TUnit.Core/AsyncConvert.cs | 31 +++++++++++++++++-- .../Modules/GetPackageProjectsModule.cs | 1 + .../TUnit.Aspire.Starter.AppHost.csproj | 2 +- .../TUnit.TestProject.FSharp.fsproj | 5 +++ TUnit.TestProject.FSharp/Tests.fs | 14 ++++++++- TUnit.TestProject.Library/Models/Dummy.cs | 3 ++ TUnit.TestProject.VB.NET/Program.vb | 16 +++++++++- TUnit.sln | 6 ++++ TestProject.props | 3 ++ .../tutorial-assertions/congratulations.md | 2 +- docs/docs/tutorial-assertions/fsharp.md | 20 ++++++++++++ 15 files changed, 145 insertions(+), 6 deletions(-) create mode 100644 TUnit.Assertions.FSharp/Extensions.fs create mode 100644 TUnit.Assertions.FSharp/TUnit.Assertions.FSharp.fsproj create mode 100644 TUnit.Assertions.FSharp/TUnit.Assertions.FSharp.props create mode 100644 TUnit.TestProject.Library/Models/Dummy.cs create mode 100644 docs/docs/tutorial-assertions/fsharp.md diff --git a/TUnit.Assertions.FSharp/Extensions.fs b/TUnit.Assertions.FSharp/Extensions.fs new file mode 100644 index 0000000000..1b4b1bd244 --- /dev/null +++ b/TUnit.Assertions.FSharp/Extensions.fs @@ -0,0 +1,17 @@ +namespace TUnit.Assertions.FSharp + +open TUnit.Assertions.AssertionBuilders + +module Extensions = + let check (assertion: IInvokableAssertionBuilder) = + Async.FromContinuations(fun (cont, econt, ccont) -> + let awaiter = assertion.GetAwaiter() + + awaiter.OnCompleted(fun () -> + try + if awaiter.IsCompleted then + cont(awaiter.GetResult()) + else + ccont (System.OperationCanceledException()) + with ex -> + econt ex)) \ No newline at end of file diff --git a/TUnit.Assertions.FSharp/TUnit.Assertions.FSharp.fsproj b/TUnit.Assertions.FSharp/TUnit.Assertions.FSharp.fsproj new file mode 100644 index 0000000000..2af7590863 --- /dev/null +++ b/TUnit.Assertions.FSharp/TUnit.Assertions.FSharp.fsproj @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/TUnit.Assertions.FSharp/TUnit.Assertions.FSharp.props b/TUnit.Assertions.FSharp/TUnit.Assertions.FSharp.props new file mode 100644 index 0000000000..d3e1101ad0 --- /dev/null +++ b/TUnit.Assertions.FSharp/TUnit.Assertions.FSharp.props @@ -0,0 +1,13 @@ + + + enable + auto + + + + + + + + + \ No newline at end of file diff --git a/TUnit.Assertions/TUnit.Assertions.props b/TUnit.Assertions/TUnit.Assertions.props index 5c0e2bda57..bdcc3c680e 100644 --- a/TUnit.Assertions/TUnit.Assertions.props +++ b/TUnit.Assertions/TUnit.Assertions.props @@ -5,4 +5,7 @@ true + + + diff --git a/TUnit.Core/AsyncConvert.cs b/TUnit.Core/AsyncConvert.cs index 9aaaaecb01..bcce9db2d7 100644 --- a/TUnit.Core/AsyncConvert.cs +++ b/TUnit.Core/AsyncConvert.cs @@ -1,4 +1,6 @@ -using System.Runtime.CompilerServices; +using System.Diagnostics.CodeAnalysis; +using System.Reflection; +using System.Runtime.CompilerServices; namespace TUnit.Core; @@ -7,6 +9,8 @@ namespace TUnit.Core; /// public static class AsyncConvert { + private static Type? _fSharpAsyncType; + [MethodImpl(MethodImplOptions.AggressiveInlining #if NET | MethodImplOptions.AggressiveOptimization @@ -92,6 +96,29 @@ public static ValueTask ConvertObject(object? invoke) return valueTask; } - throw new ArgumentException("Invalid object type"); + var type = invoke.GetType(); + if (type.IsGenericType + && type.GetGenericTypeDefinition().FullName == "Microsoft.FSharp.Control.FSharpAsync`1") + { + #pragma warning disable + return StartAsFSharpTask(invoke, type); + #pragma warning restore + } + + throw new ArgumentException("Invalid object type: " + type.Name, nameof(invoke)); + } + + [RequiresDynamicCode("Dynamic code is required to call F# async methods.")] + [RequiresUnreferencedCode("Dynamic code is required to call F# async methods.")] + private static ValueTask StartAsFSharpTask(object invoke, Type type) + { + var startAsTaskOpenGenericMethod = (_fSharpAsyncType ??= type.Assembly.GetType("Microsoft.FSharp.Control.FSharpAsync"))! + .GetRuntimeMethods() + .First(m => m.Name == "StartAsTask"); + + var fSharpTask = (Task)startAsTaskOpenGenericMethod.MakeGenericMethod(type.GetGenericArguments()[0]) + .Invoke(null, [invoke, null, null])!; + + return new ValueTask(fSharpTask); } } \ No newline at end of file diff --git a/TUnit.Pipeline/Modules/GetPackageProjectsModule.cs b/TUnit.Pipeline/Modules/GetPackageProjectsModule.cs index 08ec190586..02c2f0a19e 100644 --- a/TUnit.Pipeline/Modules/GetPackageProjectsModule.cs +++ b/TUnit.Pipeline/Modules/GetPackageProjectsModule.cs @@ -13,6 +13,7 @@ public class GetPackageProjectsModule : Module> return [ Sourcy.DotNet.Projects.TUnit_Assertions, + Sourcy.DotNet.Projects.TUnit_Assertions_FSharp, Sourcy.DotNet.Projects.TUnit_Core, Sourcy.DotNet.Projects.TUnit_Engine, Sourcy.DotNet.Projects.TUnit, diff --git a/TUnit.Templates.Tests/Snapshots/InstantiationTest.TUnit.Aspire.Starter._.verified/TUnit.Aspire.Starter/TUnit.Aspire.Starter.AppHost/TUnit.Aspire.Starter.AppHost.csproj b/TUnit.Templates.Tests/Snapshots/InstantiationTest.TUnit.Aspire.Starter._.verified/TUnit.Aspire.Starter/TUnit.Aspire.Starter.AppHost/TUnit.Aspire.Starter.AppHost.csproj index a49019522c..0526394a6d 100644 --- a/TUnit.Templates.Tests/Snapshots/InstantiationTest.TUnit.Aspire.Starter._.verified/TUnit.Aspire.Starter/TUnit.Aspire.Starter.AppHost/TUnit.Aspire.Starter.AppHost.csproj +++ b/TUnit.Templates.Tests/Snapshots/InstantiationTest.TUnit.Aspire.Starter._.verified/TUnit.Aspire.Starter/TUnit.Aspire.Starter.AppHost/TUnit.Aspire.Starter.AppHost.csproj @@ -1,6 +1,6 @@  - + Exe diff --git a/TUnit.TestProject.FSharp/TUnit.TestProject.FSharp.fsproj b/TUnit.TestProject.FSharp/TUnit.TestProject.FSharp.fsproj index 2c19aa3788..8fb67101fe 100644 --- a/TUnit.TestProject.FSharp/TUnit.TestProject.FSharp.fsproj +++ b/TUnit.TestProject.FSharp/TUnit.TestProject.FSharp.fsproj @@ -1,8 +1,13 @@  + + 9.0 + + + diff --git a/TUnit.TestProject.FSharp/Tests.fs b/TUnit.TestProject.FSharp/Tests.fs index b5424902b4..4c48eabb10 100644 --- a/TUnit.TestProject.FSharp/Tests.fs +++ b/TUnit.TestProject.FSharp/Tests.fs @@ -1,8 +1,20 @@ namespace TUnit.TestProject.FSharp +open System +open TUnit.Assertions +open TUnit.Assertions.Extensions +open TUnit.Assertions.FSharp.Extensions open TUnit.Core type Tests() = [] member this.Test() = - printfn "Test method executed" \ No newline at end of file + printfn "Test method executed" + +#if NETCOREAPP + [] + member this.TestAsync() = async { + let result = 1 + 1 + do! check (Assert.That(result).IsPositive()) + } +#endif \ No newline at end of file diff --git a/TUnit.TestProject.Library/Models/Dummy.cs b/TUnit.TestProject.Library/Models/Dummy.cs new file mode 100644 index 0000000000..07d62d8feb --- /dev/null +++ b/TUnit.TestProject.Library/Models/Dummy.cs @@ -0,0 +1,3 @@ +namespace TUnit.TestProject.Library.Models; + +public record Dummy; \ No newline at end of file diff --git a/TUnit.TestProject.VB.NET/Program.vb b/TUnit.TestProject.VB.NET/Program.vb index c6baf8e272..d8c7175547 100644 --- a/TUnit.TestProject.VB.NET/Program.vb +++ b/TUnit.TestProject.VB.NET/Program.vb @@ -1,3 +1,5 @@ +Imports TUnit.Assertions +Imports TUnit.Assertions.Extensions Imports TUnit.Core Public Class Tests @@ -5,4 +7,16 @@ Public Class Tests Public Sub Test() TestContext.Current.OutputWriter.WriteLine("Test method executed") End Sub -End Class \ No newline at end of file + +#If Not NETFRAMEWORK Then + + Public Async Function TestAsync() As Task + Dim result = 1 + 1 + Await Assert.That(result).IsNegative() + Dim assertionResult = Await Assert.That(result).IsPositive() + Console.WriteLine(assertionResult) + End Function +#End If + +End Class + diff --git a/TUnit.sln b/TUnit.sln index 8e69056cf4..7396e8fadd 100644 --- a/TUnit.sln +++ b/TUnit.sln @@ -113,6 +113,8 @@ Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "TUnit.TestProject.FSharp", EndProject Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "TUnit.TestProject.VB.NET", "TUnit.TestProject.VB.NET\TUnit.TestProject.VB.NET.vbproj", "{E0F6713B-3F3E-4335-B65F-69C9DE8FBA7C}" EndProject +Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "TUnit.Assertions.FSharp", "TUnit.Assertions.FSharp\TUnit.Assertions.FSharp.fsproj", "{D283B604-1860-4A6D-800A-A51849ACFEAF}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -291,6 +293,10 @@ Global {E0F6713B-3F3E-4335-B65F-69C9DE8FBA7C}.Debug|Any CPU.Build.0 = Debug|Any CPU {E0F6713B-3F3E-4335-B65F-69C9DE8FBA7C}.Release|Any CPU.ActiveCfg = Release|Any CPU {E0F6713B-3F3E-4335-B65F-69C9DE8FBA7C}.Release|Any CPU.Build.0 = Release|Any CPU + {D283B604-1860-4A6D-800A-A51849ACFEAF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D283B604-1860-4A6D-800A-A51849ACFEAF}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D283B604-1860-4A6D-800A-A51849ACFEAF}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D283B604-1860-4A6D-800A-A51849ACFEAF}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/TestProject.props b/TestProject.props index d23109da10..3fd34c7118 100644 --- a/TestProject.props +++ b/TestProject.props @@ -4,6 +4,9 @@ + + net472;net8.0;net9.0 diff --git a/docs/docs/tutorial-assertions/congratulations.md b/docs/docs/tutorial-assertions/congratulations.md index 61ae92a214..41a99bbc92 100644 --- a/docs/docs/tutorial-assertions/congratulations.md +++ b/docs/docs/tutorial-assertions/congratulations.md @@ -1,5 +1,5 @@ --- -sidebar_position: 8 +sidebar_position: 99 --- # Congratulations diff --git a/docs/docs/tutorial-assertions/fsharp.md b/docs/docs/tutorial-assertions/fsharp.md new file mode 100644 index 0000000000..0e6ad4d66a --- /dev/null +++ b/docs/docs/tutorial-assertions/fsharp.md @@ -0,0 +1,20 @@ +--- +sidebar_position: 10 +--- + +# FSharp + +As awaiting doesn't work quite the same in F#, the syntax instead looks like this: + +```csharp +do! check Assert.That(...).IsSomething() +``` + +So a test could look like: + +```csharp +member this.CheckPositive() = async { + let result = 1 + 1 + do! check (Assert.That(result).IsPositive()) + } +``` \ No newline at end of file