Skip to content

Commit fa4004d

Browse files
XUnit V3 (#2486)
1 parent 3a373e0 commit fa4004d

File tree

49 files changed

+425
-302
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

49 files changed

+425
-302
lines changed

.github/workflows/benchmarks.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,16 @@ env:
1616
LATEST_NET_VERSION: '9.0.x'
1717
PathToCommunityToolkitAnalyzersBenchmarkCsproj: 'src/CommunityToolkit.Maui.Analyzers.Benchmarks/CommunityToolkit.Maui.Analyzers.Benchmarks.csproj'
1818

19+
concurrency:
20+
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
21+
cancel-in-progress: true
22+
1923
jobs:
2024
run_benchmarks:
2125
name: Run Benchmarks
2226
runs-on: ${{ matrix.os }}
2327
strategy:
28+
fail-fast: false
2429
matrix:
2530
os: [windows-latest, macos-15]
2631

.github/workflows/dotnet-build.yml

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ env:
3232
PathToCommunityToolkitMediaElementCsproj: 'src/CommunityToolkit.Maui.MediaElement/CommunityToolkit.Maui.MediaElement.csproj'
3333
PathToCommunityToolkitMapsCsproj: 'src/CommunityToolkit.Maui.Maps/CommunityToolkit.Maui.Maps.csproj'
3434
PathToCommunityToolkitSampleCsproj: 'samples/CommunityToolkit.Maui.Sample/CommunityToolkit.Maui.Sample.csproj'
35-
PathToCommunityToolkitUnitTestCsproj: 'src/CommunityToolkit.Maui.UnitTests/CommunityToolkit.Maui.UnitTests.csproj'
35+
PathToCommunityToolkitUnitTestCsproj: 'src/CommunityToolkit.Maui.UnitTests'
3636
PathToCommunityToolkitAnalyzersCsproj: 'src/CommunityToolkit.Maui.Analyzers/CommunityToolkit.Maui.Analyzers.csproj'
3737
PathToCommunityToolkitCameraAnalyzersCsproj: 'src/CommunityToolkit.Maui.Camera.Analyzers/CommunityToolkit.Maui.Camera.Analyzers.csproj'
3838
PathToCommunityToolkitMediaElementAnalyzersCsproj: 'src/CommunityToolkit.Maui.MediaElement.Analyzers/CommunityToolkit.Maui.MediaElement.Analyzers.csproj'
@@ -41,16 +41,21 @@ env:
4141
PathToCommunityToolkitAnalyzersCodeFixCsproj: 'src/CommunityToolkit.Maui.Analyzers.CodeFixes/CommunityToolkit.Maui.Analyzers.CodeFixes.csproj'
4242
PathToCommunityToolkitCameraAnalyzersCodeFixCsproj: 'src/CommunityToolkit.Maui.Camera.Analyzers.CodeFixes/CommunityToolkit.Maui.Camera.Analyzers.CodeFixes.csproj'
4343
PathToCommunityToolkitMediaElementAnalyzersCodeFixCsproj: 'src/CommunityToolkit.Maui.MediaElement.Analyzers.CodeFixes/CommunityToolkit.Maui.MediaElement.Analyzers.CodeFixes.csproj'
44-
PathToCommunityToolkitAnalyzersUnitTestCsproj: 'src/CommunityToolkit.Maui.Analyzers.UnitTests/CommunityToolkit.Maui.Analyzers.UnitTests.csproj'
44+
PathToCommunityToolkitAnalyzersUnitTestCsproj: 'src/CommunityToolkit.Maui.Analyzers.UnitTests'
4545
PathToCommunityToolkitAnalyzersBenchmarkCsproj: 'src/CommunityToolkit.Maui.Analyzers.Benchmarks/CommunityToolkit.Maui.Analyzers.Benchmarks.csproj'
4646
CommunityToolkitSampleApp_Xcode_Version: '16.2'
4747
CommunityToolkitLibrary_Xcode_Version: '16.2'
4848

49+
concurrency:
50+
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
51+
cancel-in-progress: true
52+
4953
jobs:
5054
build_sample:
5155
name: Build Sample App using Latest .NET SDK
5256
runs-on: ${{ matrix.os }}
5357
strategy:
58+
fail-fast: false
5459
matrix:
5560
os: [windows-latest, macos-15]
5661
steps:
@@ -90,9 +95,8 @@ jobs:
9095
build_library:
9196
name: Build Library
9297
runs-on: ${{ matrix.os }}
93-
env:
94-
VSTEST_TESTHOST_SHUTDOWN_TIMEOUT: 1100 # Fixes "The active test run was aborted. Reason: Test host process crashed"
9598
strategy:
99+
fail-fast: false
96100
matrix:
97101
os: [windows-latest, macos-15]
98102
steps:
@@ -189,16 +193,24 @@ jobs:
189193
- name: 'Build CommunityToolkit.Maui'
190194
run: dotnet build ${{ env.PathToLibrarySolution }} -c Release -p:PackageVersion=${{ env.NugetPackageVersion }} -p:Version=${{ env.NugetPackageVersion }}
191195

192-
- name: Run All Unit Tests
193-
run: dotnet test -c Release ${{ env.PathToLibrarySolution }} --settings ".runsettings" --collect "XPlat code coverage" --logger trx --results-directory ${{ runner.temp }} --logger GitHubActions
196+
- name: Run CommunityToolkit Analyzers UnitTests
197+
run: |
198+
cd ${{ env.PathToCommunityToolkitAnalyzersUnitTestCsproj }}
199+
dotnet run -c Release --results-directory "${{ runner.temp }}" --coverage --coverage-output "${{ runner.temp }}/ut-analyzers.cobertura.xml" --coverage-output-format cobertura --report-xunit
200+
201+
- name: Run CommunityToolkit UnitTests
202+
run: |
203+
cd ${{ env.PathToCommunityToolkitUnitTestCsproj }}
204+
dotnet run -c Release --results-directory "${{ runner.temp }}" --coverage --coverage-output "${{ runner.temp }}/ut.cobertura.xml" --coverage-output-format cobertura --report-xunit
194205
195206
- name: Publish Test Results
196-
if: runner.os == 'Windows'
207+
if: runner.os == 'Windows' && (${{ success() || failure() }})
197208
uses: actions/upload-artifact@v4
198209
with:
199-
name: Test Results
210+
name: Test Results ${{ github.run_number }} ${{ runner.os }}
200211
path: |
201-
${{ runner.temp }}/**/*.trx
212+
${{ runner.temp }}/*.xunit
213+
${{ runner.temp }}/*cobertura.xml
202214
203215
- name: Pack CommunityToolkit.Maui.Core NuGet
204216
run: dotnet pack -c Release ${{ env.PathToCommunityToolkitCoreCsproj }} -p:PackageVersion=${{ env.NugetPackageVersion }}
File renamed without changes.

samples/CommunityToolkit.Maui.Sample.sln

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,10 @@ EndProject
1212
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{3ED2C978-9DDB-48FE-8C5A-521B254F18A3}"
1313
ProjectSection(SolutionItems) = preProject
1414
..\.editorconfig = ..\.editorconfig
15+
..\.github\workflows\benchmarks.yml = ..\.github\workflows\benchmarks.yml
1516
..\Directory.Build.props = ..\Directory.Build.props
1617
..\Directory.Build.targets = ..\Directory.Build.targets
18+
..\.github\workflows\dotnet-build.yml = ..\.github\workflows\dotnet-build.yml
1719
..\global.json = ..\global.json
1820
EndProjectSection
1921
EndProject

src/CommunityToolkit.Maui.Analyzers.UnitTests/CommunityToolkit.Maui.Analyzers.UnitTests.csproj

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,30 +2,35 @@
22

33
<PropertyGroup>
44
<TargetFramework>$(NetVersion)</TargetFramework>
5-
<IsPackable>false</IsPackable>
65
<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
76
<CompilerGeneratedFilesOutputPath>$(BaseIntermediateOutputPath)\GF</CompilerGeneratedFilesOutputPath>
87
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
98
<GenerateBindingRedirectsOutputType>true</GenerateBindingRedirectsOutputType>
9+
10+
<OutputType>Exe</OutputType>
11+
<RootNamespace>CommunityToolkit.Maui.Analyzers.UnitTests</RootNamespace>
12+
13+
<TestingPlatformDotnetTestSupport>false</TestingPlatformDotnetTestSupport>
14+
<UseMicrosoftTestingPlatformRunner>true</UseMicrosoftTestingPlatformRunner>
1015
</PropertyGroup>
1116

1217
<ItemGroup>
13-
<PackageReference Include="FluentAssertions" Version="8.0.1" />
14-
<PackageReference Include="FluentAssertions.Analyzers" Version="0.34.1" />
15-
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Analyzer.Testing.XUnit" Version="1.1.2" />
16-
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.CodeFix.Testing.XUnit" Version="1.1.2" />
17-
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.12.0" />
18-
<PackageReference Include="xunit" Version="2.9.3" />
19-
<PackageReference Include="xunit.runner.visualstudio" Version="3.0.1" PrivateAssets="All" />
20-
<PackageReference Include="coverlet.collector" Version="6.0.4" PrivateAssets="All" />
18+
<Content Include="xunit.runner.json" CopyToOutputDirectory="PreserveNewest"/>
19+
</ItemGroup>
20+
21+
<ItemGroup>
22+
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Analyzer.Testing" Version="1.1.2" />
23+
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.CodeFix.Testing" Version="1.1.2" />
24+
<PackageReference Include="xunit.v3" Version="1.0.1" />
25+
<PackageReference Include="Microsoft.Testing.Extensions.CodeCoverage" Version="17.13.1" />
2126
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="4.12.0" />
22-
<PackageReference Include="Microsoft.Maui.Controls" Version="$(MauiPackageVersion)" />
23-
<PackageReference Include="GitHubActionsTestLogger" Version="2.4.1" PrivateAssets="All" />
2427
</ItemGroup>
2528

2629
<ItemGroup>
2730
<!--Fix vulnerabilities-->
2831
<PackageReference Include="System.Formats.Asn1" Version="9.0.1" />
32+
<PackageReference Include="System.Net.Http" Version="4.3.4" />
33+
<PackageReference Include="System.Text.RegularExpressions" Version="4.3.1" />
2934
</ItemGroup>
3035

3136
<ItemGroup>
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"$schema": "https://xunit.net/schema/current/xunit.runner.schema.json"
3+
}

src/CommunityToolkit.Maui.MediaElement/Extensions/PageExtensions.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ internal static Page GetCurrentPage(this Page currentPage)
3131

3232
internal record struct ParentWindow
3333
{
34-
static Page CurrentPage => GetCurrentPage(Application.Current?.Windows[0].Page ?? throw new InvalidOperationException($"{nameof(Page)} cannot be null."));
34+
static Page CurrentPage => GetCurrentPage(Application.Current?.Windows[^1].Page ?? throw new InvalidOperationException($"{nameof(Page)} cannot be null."));
3535
/// <summary>
3636
/// Checks if the parent window is null.
3737
/// </summary>

src/CommunityToolkit.Maui.SourceGenerators/Generators/TextColorToGenerator.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,7 @@ namespace {{textStyleClassMetadata.Namespace}};
145145
public static Task<bool> TextColorTo{{textStyleClassMetadata.GenericArguments}}(this global::{{textStyleClassMetadata.Namespace}}.{{textStyleClassMetadata.ClassName}}{{textStyleClassMetadata.GenericArguments}} element, {{mauiColorFullName}} color, uint rate = 16u, uint length = 250u, Easing? easing = null, CancellationToken token = default)
146146
{{textStyleClassMetadata.GenericConstraints}}
147147
{
148+
token.ThrowIfCancellationRequested();
148149
ArgumentNullException.ThrowIfNull(element);
149150
ArgumentNullException.ThrowIfNull(color);
150151

src/CommunityToolkit.Maui.UnitTests/Alerts/SnackbarTests.cs

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ public async Task SnackbarShow_CancellationTokenExpires()
3838
var cts = new CancellationTokenSource(TimeSpan.FromMilliseconds(1));
3939

4040
// Ensure CancellationToken expires
41-
await Task.Delay(100, CancellationToken.None);
41+
await Task.Delay(100, TestContext.Current.CancellationToken);
4242

4343
await Assert.ThrowsAsync<OperationCanceledException>(() => snackbar.Show(cts.Token));
4444
}
@@ -61,7 +61,7 @@ public async Task SnackbarDismiss_CancellationTokenExpires()
6161
var cts = new CancellationTokenSource(TimeSpan.FromMilliseconds(1));
6262

6363
// Ensure CancellationToken expires
64-
await Task.Delay(100, CancellationToken.None);
64+
await Task.Delay(100, TestContext.Current.CancellationToken);
6565

6666
await Assert.ThrowsAsync<OperationCanceledException>(() => snackbar.Dismiss(cts.Token));
6767
}
@@ -81,14 +81,14 @@ await Assert.ThrowsAsync<OperationCanceledException>(() =>
8181
[Fact(Timeout = (int)TestDuration.Short)]
8282
public async Task SnackbarShow_IsShownTrue()
8383
{
84-
await snackbar.Show(CancellationToken.None);
84+
await snackbar.Show(TestContext.Current.CancellationToken);
8585
Assert.True(Snackbar.IsShown);
8686
}
8787

8888
[Fact(Timeout = (int)TestDuration.Short)]
8989
public async Task SnackbarDismissed_IsShownFalse()
9090
{
91-
await snackbar.Dismiss(CancellationToken.None);
91+
await snackbar.Dismiss(TestContext.Current.CancellationToken);
9292
Assert.False(Snackbar.IsShown);
9393
}
9494

@@ -100,7 +100,7 @@ public async Task SnackbarShow_ShownEventRaised()
100100
{
101101
receivedEvents.Add(e);
102102
};
103-
await snackbar.Show(CancellationToken.None);
103+
await snackbar.Show(TestContext.Current.CancellationToken);
104104
Assert.Single(receivedEvents);
105105
}
106106

@@ -112,7 +112,7 @@ public async Task SnackbarDismiss_DismissedEventRaised()
112112
{
113113
receivedEvents.Add(e);
114114
};
115-
await snackbar.Dismiss(CancellationToken.None);
115+
await snackbar.Dismiss(TestContext.Current.CancellationToken);
116116
Assert.Single(receivedEvents);
117117
}
118118

@@ -125,7 +125,7 @@ public async Task VisualElement_DisplaySnackbar_ShownEventReceived()
125125
receivedEvents.Add(e);
126126
};
127127
var button = new Button();
128-
await button.DisplaySnackbar("message", token: CancellationToken.None);
128+
await button.DisplaySnackbar("message", token: TestContext.Current.CancellationToken);
129129
Assert.Single(receivedEvents);
130130
}
131131

@@ -210,13 +210,13 @@ public async Task SnackbarDismiss_CancellationTokenNotCancelled_NotReceiveExcept
210210
[Fact(Timeout = (int)TestDuration.Short)]
211211
public async Task SnackbarShow_CancellationTokenNone_NotReceiveException()
212212
{
213-
await snackbar.Invoking(x => x.Show(CancellationToken.None)).Should().NotThrowAsync<OperationCanceledException>();
213+
await snackbar.Invoking(x => x.Show(TestContext.Current.CancellationToken)).Should().NotThrowAsync<OperationCanceledException>();
214214
}
215215

216216
[Fact(Timeout = (int)TestDuration.Short)]
217217
public async Task SnackbarDismiss_CancellationTokenNone_NotReceiveException()
218218
{
219-
await snackbar.Invoking(x => x.Dismiss(CancellationToken.None)).Should().NotThrowAsync<OperationCanceledException>();
219+
await snackbar.Invoking(x => x.Dismiss(TestContext.Current.CancellationToken)).Should().NotThrowAsync<OperationCanceledException>();
220220
}
221221

222222
[Fact]
@@ -233,8 +233,8 @@ public async Task SnackbarNullValuesThrowArgumentNullException()
233233
});
234234
Assert.Throws<ArgumentNullException>(() => Snackbar.Make(null));
235235
Assert.Throws<ArgumentNullException>(() => Snackbar.Make(string.Empty, actionButtonText: null));
236-
await Assert.ThrowsAsync<ArgumentNullException>(() => new Button().DisplaySnackbar(null, token: CancellationToken.None));
237-
await Assert.ThrowsAsync<ArgumentNullException>(() => new Button().DisplaySnackbar(string.Empty, actionButtonText: null, token: CancellationToken.None));
236+
await Assert.ThrowsAsync<ArgumentNullException>(() => new Button().DisplaySnackbar(null, token: TestContext.Current.CancellationToken));
237+
await Assert.ThrowsAsync<ArgumentNullException>(() => new Button().DisplaySnackbar(string.Empty, actionButtonText: null, token: TestContext.Current.CancellationToken));
238238
#pragma warning restore CS8625 // Cannot convert null literal to non-nullable reference type.
239239
}
240240
}

src/CommunityToolkit.Maui.UnitTests/Alerts/ToastTests.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ public async Task ToastShow_CancellationTokenExpires()
2121
var cts = new CancellationTokenSource(TimeSpan.FromMilliseconds(1));
2222

2323
// Ensure CancellationToken expires
24-
await Task.Delay(100, CancellationToken.None);
24+
await Task.Delay(100, TestContext.Current.CancellationToken);
2525

2626
await Assert.ThrowsAsync<OperationCanceledException>(() => toast.Show(cts.Token));
2727
}
@@ -44,7 +44,7 @@ public async Task ToastDismiss_CancellationTokenExpires()
4444
var cts = new CancellationTokenSource(TimeSpan.FromMilliseconds(1));
4545

4646
// Ensure CancellationToken expires
47-
await Task.Delay(100, CancellationToken.None);
47+
await Task.Delay(100, TestContext.Current.CancellationToken);
4848

4949
await Assert.ThrowsAsync<OperationCanceledException>(() => toast.Dismiss(cts.Token));
5050
}
@@ -116,13 +116,13 @@ public async Task ToastDismiss_CancellationTokenNotCancelled_NotReceiveException
116116
[Fact(Timeout = (int)TestDuration.Short)]
117117
public async Task ToastShow_CancellationTokenNone_NotReceiveException()
118118
{
119-
await toast.Invoking(x => x.Show(CancellationToken.None)).Should().NotThrowAsync<OperationCanceledException>();
119+
await toast.Invoking(x => x.Show(TestContext.Current.CancellationToken)).Should().NotThrowAsync<OperationCanceledException>();
120120
}
121121

122122
[Fact(Timeout = (int)TestDuration.Short)]
123123
public async Task ToastDismiss_CancellationTokenNone_NotReceiveException()
124124
{
125-
await toast.Invoking(x => x.Dismiss(CancellationToken.None)).Should().NotThrowAsync<OperationCanceledException>();
125+
await toast.Invoking(x => x.Dismiss(TestContext.Current.CancellationToken)).Should().NotThrowAsync<OperationCanceledException>();
126126
}
127127

128128
[Fact]

0 commit comments

Comments
 (0)