Skip to content

Commit be45653

Browse files
Migrate xUnit + FluentAssertions to NUnit 4.4.0 with Controlled Concurrency and Proper STA Thread Support (#4121)
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: glennawatson <5834289+glennawatson@users.noreply.github.com>
1 parent e2c4499 commit be45653

File tree

130 files changed

+11779
-9589
lines changed

Some content is hidden

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

130 files changed

+11779
-9589
lines changed

.editorconfig

Lines changed: 114 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -502,6 +502,119 @@ dotnet_diagnostic.RCS1190.severity=error
502502
dotnet_diagnostic.RCS1195.severity=error
503503
dotnet_diagnostic.RCS1214.severity=error
504504

505+
[*.{cs,vb}]
506+
#############################################
507+
# NUnit Analyzers — enable all as errors
508+
#############################################
509+
510+
# Structure Rules (NUnit1001 - )
511+
dotnet_diagnostic.NUnit1001.severity = error # TestCase args must match parameter types
512+
dotnet_diagnostic.NUnit1002.severity = error # TestCaseSource should use nameof
513+
dotnet_diagnostic.NUnit1003.severity = error # TestCase provided too few arguments
514+
dotnet_diagnostic.NUnit1004.severity = error # TestCase provided too many arguments
515+
dotnet_diagnostic.NUnit1005.severity = error # ExpectedResult type must match return type
516+
dotnet_diagnostic.NUnit1006.severity = error # ExpectedResult must not be used on void methods
517+
dotnet_diagnostic.NUnit1007.severity = error # Non-void method but no ExpectedResult provided
518+
dotnet_diagnostic.NUnit1008.severity = error # ParallelScope.Self at assembly level has no effect
519+
dotnet_diagnostic.NUnit1009.severity = error # ParallelScope.Children on non-parameterized test
520+
dotnet_diagnostic.NUnit1010.severity = error # ParallelScope.Fixtures on a test method
521+
dotnet_diagnostic.NUnit1011.severity = error # TestCaseSource member does not exist
522+
dotnet_diagnostic.NUnit1012.severity = error # async test method must have non-void return type
523+
dotnet_diagnostic.NUnit1013.severity = error # async method must use non-generic Task when no result
524+
dotnet_diagnostic.NUnit1014.severity = error # async method must use Task<T> when result expected
525+
dotnet_diagnostic.NUnit1015.severity = error # Source type does not implement I(Async)Enumerable
526+
dotnet_diagnostic.NUnit1016.severity = error # Source type lacks default constructor
527+
dotnet_diagnostic.NUnit1017.severity = error # Specified source is not static
528+
dotnet_diagnostic.NUnit1018.severity = error # TestCaseSource param count mismatch (target method)
529+
dotnet_diagnostic.NUnit1019.severity = error # Source does not return I(Async)Enumerable
530+
dotnet_diagnostic.NUnit1020.severity = error # Parameters provided to field/property source
531+
dotnet_diagnostic.NUnit1021.severity = error # ValueSource should use nameof
532+
dotnet_diagnostic.NUnit1022.severity = error # Specified ValueSource is not static
533+
dotnet_diagnostic.NUnit1023.severity = error # ValueSource cannot supply required parameters
534+
dotnet_diagnostic.NUnit1024.severity = error # ValueSource does not return I(Async)Enumerable
535+
dotnet_diagnostic.NUnit1025.severity = error # ValueSource member does not exist
536+
dotnet_diagnostic.NUnit1026.severity = error # Test or setup/teardown method is not public
537+
dotnet_diagnostic.NUnit1027.severity = error # Test method has parameters but no arguments supplied
538+
dotnet_diagnostic.NUnit1028.severity = error # Non-test method is public
539+
dotnet_diagnostic.NUnit1029.severity = error # TestCaseSource param count mismatch (Test method)
540+
dotnet_diagnostic.NUnit1030.severity = error # TestCaseSource parameter type mismatch (Test method)
541+
dotnet_diagnostic.NUnit1031.severity = error # ValuesAttribute args must match parameter types
542+
dotnet_diagnostic.NUnit1032.severity = error # IDisposable field/property should be disposed in TearDown
543+
dotnet_diagnostic.NUnit1033.severity = error # TestContext.Write methods will be obsolete
544+
dotnet_diagnostic.NUnit1034.severity = error # Base TestFixtures should be abstract
545+
dotnet_diagnostic.NUnit1035.severity = error # Range 'step' parameter cannot be zero
546+
dotnet_diagnostic.NUnit1036.severity = error # Range: from < to when step is positive
547+
dotnet_diagnostic.NUnit1037.severity = error # Range: from > to when step is negative
548+
dotnet_diagnostic.NUnit1038.severity = error # Attribute values' types must match parameter type
549+
550+
# Assertion Rules (NUnit2001 - )
551+
dotnet_diagnostic.NUnit2001.severity = error # Prefer Assert.That(..., Is.False) over ClassicAssert.False
552+
dotnet_diagnostic.NUnit2002.severity = error # Prefer Assert.That(..., Is.False) over ClassicAssert.IsFalse
553+
dotnet_diagnostic.NUnit2003.severity = error # Prefer Assert.That(..., Is.True) over ClassicAssert.IsTrue
554+
dotnet_diagnostic.NUnit2004.severity = error # Prefer Assert.That(..., Is.True) over ClassicAssert.True
555+
dotnet_diagnostic.NUnit2005.severity = error # Prefer Is.EqualTo over AreEqual
556+
dotnet_diagnostic.NUnit2006.severity = error # Prefer Is.Not.EqualTo over AreNotEqual
557+
dotnet_diagnostic.NUnit2007.severity = error # Actual value should not be a constant
558+
dotnet_diagnostic.NUnit2008.severity = error # Incorrect IgnoreCase usage
559+
dotnet_diagnostic.NUnit2009.severity = error # Same value used for actual and expected
560+
dotnet_diagnostic.NUnit2010.severity = error # Use EqualConstraint for better messages
561+
dotnet_diagnostic.NUnit2011.severity = error # Use ContainsConstraint for better messages
562+
dotnet_diagnostic.NUnit2012.severity = error # Use StartsWithConstraint for better messages
563+
dotnet_diagnostic.NUnit2013.severity = error # Use EndsWithConstraint for better messages
564+
dotnet_diagnostic.NUnit2014.severity = error # Use SomeItemsConstraint for better messages
565+
dotnet_diagnostic.NUnit2015.severity = error # Prefer Is.SameAs over AreSame
566+
dotnet_diagnostic.NUnit2016.severity = error # Prefer Is.Null over ClassicAssert.Null
567+
dotnet_diagnostic.NUnit2017.severity = error # Prefer Is.Null over ClassicAssert.IsNull
568+
dotnet_diagnostic.NUnit2018.severity = error # Prefer Is.Not.Null over ClassicAssert.NotNull
569+
dotnet_diagnostic.NUnit2019.severity = error # Prefer Is.Not.Null over ClassicAssert.IsNotNull
570+
dotnet_diagnostic.NUnit2020.severity = error # Incompatible types for SameAs constraint
571+
dotnet_diagnostic.NUnit2021.severity = error # Incompatible types for EqualTo constraint
572+
dotnet_diagnostic.NUnit2022.severity = error # Missing property required for constraint
573+
dotnet_diagnostic.NUnit2023.severity = error # Invalid NullConstraint usage
574+
dotnet_diagnostic.NUnit2024.severity = error # Wrong actual type with String constraint
575+
dotnet_diagnostic.NUnit2025.severity = error # Wrong actual type with ContainsConstraint
576+
dotnet_diagnostic.NUnit2026.severity = error # Wrong actual type with SomeItems+EqualConstraint
577+
dotnet_diagnostic.NUnit2027.severity = error # Prefer Is.GreaterThan over ClassicAssert.Greater
578+
dotnet_diagnostic.NUnit2028.severity = error # Prefer Is.GreaterThanOrEqualTo over GreaterOrEqual
579+
dotnet_diagnostic.NUnit2029.severity = error # Prefer Is.LessThan over ClassicAssert.Less
580+
dotnet_diagnostic.NUnit2030.severity = error # Prefer Is.LessThanOrEqualTo over LessOrEqual
581+
dotnet_diagnostic.NUnit2031.severity = error # Prefer Is.Not.SameAs over AreNotSame
582+
dotnet_diagnostic.NUnit2032.severity = error # Prefer Is.Zero over ClassicAssert.Zero
583+
dotnet_diagnostic.NUnit2033.severity = error # Prefer Is.Not.Zero over ClassicAssert.NotZero
584+
dotnet_diagnostic.NUnit2034.severity = error # Prefer Is.NaN over ClassicAssert.IsNaN
585+
dotnet_diagnostic.NUnit2035.severity = error # Prefer Is.Empty over ClassicAssert.IsEmpty
586+
dotnet_diagnostic.NUnit2036.severity = error # Prefer Is.Not.Empty over ClassicAssert.IsNotEmpty
587+
dotnet_diagnostic.NUnit2037.severity = error # Prefer Does.Contain over ClassicAssert.Contains
588+
dotnet_diagnostic.NUnit2038.severity = error # Prefer Is.InstanceOf over ClassicAssert.IsInstanceOf
589+
dotnet_diagnostic.NUnit2039.severity = error # Prefer Is.Not.InstanceOf over ClassicAssert.IsNotInstanceOf
590+
dotnet_diagnostic.NUnit2040.severity = error # Non-reference types for SameAs constraint
591+
dotnet_diagnostic.NUnit2041.severity = error # Incompatible types for comparison constraint
592+
dotnet_diagnostic.NUnit2042.severity = error # Comparison constraint on object
593+
dotnet_diagnostic.NUnit2043.severity = error # Use ComparisonConstraint for better messages
594+
dotnet_diagnostic.NUnit2044.severity = error # Non-delegate actual parameter
595+
dotnet_diagnostic.NUnit2045.severity = error # Use Assert.EnterMultipleScope or Assert.Multiple
596+
dotnet_diagnostic.NUnit2046.severity = error # Use CollectionConstraint for better messages
597+
dotnet_diagnostic.NUnit2047.severity = error # Incompatible types for Within constraint
598+
dotnet_diagnostic.NUnit2048.severity = error # Prefer Assert.That over StringAssert
599+
dotnet_diagnostic.NUnit2049.severity = error # Prefer Assert.That over CollectionAssert
600+
dotnet_diagnostic.NUnit2050.severity = error # NUnit 4 no longer supports string.Format spec
601+
dotnet_diagnostic.NUnit2051.severity = error # Prefer Is.Positive over ClassicAssert.Positive
602+
dotnet_diagnostic.NUnit2052.severity = error # Prefer Is.Negative over ClassicAssert.Negative
603+
dotnet_diagnostic.NUnit2053.severity = error # Prefer Is.AssignableFrom over ClassicAssert.IsAssignableFrom
604+
dotnet_diagnostic.NUnit2054.severity = error # Prefer Is.Not.AssignableFrom over ClassicAssert.IsNotAssignableFrom
605+
dotnet_diagnostic.NUnit2055.severity = error # Prefer Is.InstanceOf<T> over 'is T' expression
606+
dotnet_diagnostic.NUnit2056.severity = error # Prefer Assert.EnterMultipleScope statement over Multiple
607+
608+
# Suppressor Rules (NUnit3001 - )
609+
dotnet_diagnostic.NUnit3001.severity = error # Expression checked in NotNull/IsNotNull/Assert.That
610+
dotnet_diagnostic.NUnit3002.severity = error # Field/Property initialized in SetUp/OneTimeSetUp
611+
dotnet_diagnostic.NUnit3003.severity = error # TestFixture instantiated via reflection
612+
dotnet_diagnostic.NUnit3004.severity = error # Field should be disposed in TearDown/OneTimeTearDown
613+
614+
# Style Rules (NUnit4001 - )
615+
dotnet_diagnostic.NUnit4001.severity = error # Simplify the Values attribute
616+
dotnet_diagnostic.NUnit4002.severity = error # Use Specific constraint
617+
505618
# C++ Files
506619
[*.{cpp,h,in}]
507620
curly_bracket_next_line = true
@@ -529,4 +642,4 @@ end_of_line = lf
529642
[*.{cmd, bat}]
530643
end_of_line = crlf
531644

532-
vsspell_dictionary_languages = en-US
645+
vsspell_dictionary_languages = en-US
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
1-
// Copyright (c) 2025 .NET Foundation and Contributors. All rights reserved.
1+
// Copyright (c) 2025 .NET Foundation and Contributors. All rights reserved.
22
// Licensed to the .NET Foundation under one or more agreements.
33
// The .NET Foundation licenses this file to you under the MIT license.
44
// See the LICENSE file in the project root for full license information.
55

6-
using Xunit;
6+
using NUnit.Framework;
77

8-
[assembly: CollectionBehavior(DisableTestParallelization = true, MaxParallelThreads = 1)]
8+
[assembly: Parallelizable(ParallelScope.Fixtures)]
9+
[assembly: LevelOfParallelism(4)]

integrationtests/IntegrationTests.Shared.Tests/Features/Login/LoginViewModelTests.cs

Lines changed: 22 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -12,26 +12,25 @@
1212

1313
using DynamicData;
1414

15-
using FluentAssertions;
16-
1715
using Microsoft.Reactive.Testing;
1816

1917
using ReactiveUI;
2018
using ReactiveUI.Testing;
2119

22-
using Xunit;
20+
using NUnit.Framework;
2321

2422
namespace IntegrationTests.Shared.Tests.Features.Login
2523
{
2624
/// <summary>
2725
/// Tests associated with the LoginViewModel class.
2826
/// </summary>
27+
[TestFixture]
2928
public class LoginViewModelTests
3029
{
3130
/// <summary>
3231
/// Checks to make sure that the cancel command actually cancels a login attempt.
3332
/// </summary>
34-
[Fact]
33+
[Test]
3534
public void CancelButton_Cancels_Login()
3635
{
3736
var scheduler = new TestScheduler();
@@ -43,13 +42,13 @@ public void CancelButton_Cancels_Login()
4342

4443
scheduler.AdvanceByMs(TimeSpan.FromSeconds(1).Milliseconds);
4544

46-
sut.Login.Subscribe(x => x.Should().Be(true));
45+
sut.Login.Subscribe(x => Assert.That(x, Is.EqualTo(true)));
4746

4847
Observable
4948
.Return(Unit.Default)
5049
.InvokeCommand(sut.Login);
5150

52-
sut.Cancel.CanExecute.Subscribe(x => x.Should().Be(true));
51+
sut.Cancel.CanExecute.Subscribe(x => Assert.That(x, Is.EqualTo(true)));
5352

5453
scheduler.AdvanceByMs(1000);
5554

@@ -61,7 +60,7 @@ public void CancelButton_Cancels_Login()
6160
/// <summary>
6261
/// Checks to make sure that the cancel button is available within two seconds.
6362
/// </summary>
64-
[Fact]
63+
[Test]
6564
public void CancelButton_IsAvailableUntil_TwoSeconds()
6665
{
6766
var actual = false;
@@ -79,40 +78,40 @@ public void CancelButton_IsAvailableUntil_TwoSeconds()
7978

8079
Observable.Return(Unit.Default).InvokeCommand(sut.Login);
8180

82-
actual.Should().Be(false);
81+
Assert.That(actual, Is.EqualTo(false));
8382

8483
// 50ms
8584
scheduler.AdvanceByMs(50);
8685

87-
actual.Should().Be(true);
86+
Assert.That(actual, Is.EqualTo(true));
8887

8988
// 1sec 50ms
9089
scheduler.AdvanceByMs(TimeSpan.FromSeconds(1).TotalMilliseconds);
9190

92-
actual.Should().Be(true);
91+
Assert.That(actual, Is.EqualTo(true));
9392

9493
// 2sec 50sms
9594
scheduler.AdvanceByMs(TimeSpan.FromSeconds(1).TotalMilliseconds);
9695

97-
actual.Should().Be(false);
96+
Assert.That(actual, Is.EqualTo(false));
9897
}
9998

10099
/// <summary>
101100
/// Checks to make sure that the login button is disabled when not logging in.
102101
/// </summary>
103102
/// <returns>A task to monitor the progress.</returns>
104-
[Fact]
103+
[Test]
105104
public async Task CancelButton_IsDisabled_WhenNot_LoggingIn()
106105
{
107106
LoginViewModel sut = new LoginViewModelBuilder();
108107

109-
(await sut.Cancel.CanExecute.FirstAsync()).Should().Be(false);
108+
Assert.That((await sut.Cancel.CanExecute.FirstAsync()), Is.EqualTo(false));
110109
}
111110

112111
/// <summary>
113112
/// Checks to make sure that the login ticks correctly and the action is performed.
114113
/// </summary>
115-
[Fact]
114+
[Test]
116115
public void CanLogin_TicksCorrectly()
117116
{
118117
var scheduler = new TestScheduler();
@@ -127,20 +126,20 @@ public void CanLogin_TicksCorrectly()
127126

128127
scheduler.AdvanceByMs(TimeSpan.FromSeconds(5).TotalMilliseconds);
129128

130-
collection.ToList().Should().BeEquivalentTo(new[] { false, true, false });
129+
Assert.That(collection.ToList(), Is.EqualTo(new[] { false, true, false }));
131130
}
132131

133132
/// <summary>
134133
/// Checks to make sure that the login button is disabled with default values.
135134
/// </summary>
136135
/// <returns>A task to monitor the progress.</returns>
137-
[Fact]
136+
[Test]
138137
public async Task LoginButton_IsDisabled_ByDefault()
139138
{
140139
LoginViewModel sut = new LoginViewModelBuilder();
141140

142141
var result = await sut.Login.CanExecute.FirstAsync();
143-
result.Should().Be(false);
142+
Assert.That(result, Is.EqualTo(false));
144143
}
145144

146145
/// <summary>
@@ -162,7 +161,7 @@ public async Task LoginButton_IsDisabled_WhenUserNameOrPassword_IsEmpty(string u
162161
.WithUserName(userName)
163162
.WithPassword(password);
164163

165-
(await sut.Login.CanExecute.FirstAsync()).Should().Be(false);
164+
Assert.That((await sut.Login.CanExecute.FirstAsync()), Is.EqualTo(false));
166165
}
167166

168167
/// <summary>
@@ -179,13 +178,13 @@ public async Task LoginButton_IsEnabled_WhenUserNameAndPassword_IsNotEmptyAsync(
179178
.WithUserName(userName)
180179
.WithPassword(password);
181180

182-
(await sut.Login.CanExecute.FirstAsync()).Should().Be(true);
181+
Assert.That((await sut.Login.CanExecute.FirstAsync()), Is.EqualTo(true));
183182
}
184183

185184
/// <summary>
186185
/// Checks to make sure the user can login with a correct password.
187186
/// </summary>
188-
[Fact]
187+
[Test]
189188
public void User_CanLogin_WithCorrect_Password()
190189
{
191190
var scheduler = new TestScheduler();
@@ -201,13 +200,13 @@ public void User_CanLogin_WithCorrect_Password()
201200

202201
scheduler.AdvanceByMs(TimeSpan.FromSeconds(3).TotalMilliseconds);
203202

204-
value.Should().Be(true);
203+
Assert.That(value, Is.EqualTo(true));
205204
}
206205

207206
/// <summary>
208207
/// Checks to make sure the user cannot login with a incorrect password.
209208
/// </summary>
210-
[Fact]
209+
[Test]
211210
public void User_CannotLogin_WithIncorrect_Password()
212211
{
213212
var scheduler = new TestScheduler();
@@ -223,7 +222,7 @@ public void User_CannotLogin_WithIncorrect_Password()
223222

224223
scheduler.AdvanceByMs(TimeSpan.FromSeconds(3).TotalMilliseconds);
225224

226-
value.Should().Be(false);
225+
Assert.That(value, Is.EqualTo(false));
227226
}
228227
}
229228
}

integrationtests/IntegrationTests.Shared.Tests/IntegrationTests.Shared.Tests.csproj

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,11 @@
99

1010
<ItemGroup>
1111
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.14.1" />
12-
<PackageReference Include="xunit" Version="2.9.3" />
13-
<PackageReference Include="xunit.runner.console" Version="2.9.3">
12+
<PackageReference Include="NUnit" Version="4.4.0" />
13+
<PackageReference Include="NUnit3TestAdapter" Version="5.*">
1414
<PrivateAssets>all</PrivateAssets>
1515
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
1616
</PackageReference>
17-
<PackageReference Include="xunit.runner.visualstudio" Version="3.1.4">
18-
<PrivateAssets>all</PrivateAssets>
19-
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
20-
</PackageReference>
21-
<PackageReference Include="Xunit.StaFact" Version="1.2.69" />
22-
<PackageReference Include="FluentAssertions" Version="8.6.0" />
2317
</ItemGroup>
2418

2519
<ItemGroup>

src/Directory.Build.props

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -45,16 +45,14 @@
4545
<ContinuousIntegrationBuild>true</ContinuousIntegrationBuild>
4646
</PropertyGroup>
4747
<ItemGroup Condition="$(IsTestProject)">
48+
<PackageReference Include="NUnit" />
49+
<PackageReference Include="NUnit3TestAdapter" />
50+
<PackageReference Include="NUnit.Analyzers" />
4851
<PackageReference Include="Microsoft.NET.Test.Sdk" />
49-
<PackageReference Include="xunit" />
50-
<PackageReference Include="xunit.runner.console" />
51-
<PackageReference Include="xunit.runner.visualstudio" />
52-
<PackageReference Include="Xunit.StaFact" />
53-
<PackageReference Include="FluentAssertions" />
5452
<PackageReference Include="Microsoft.Reactive.Testing" />
5553
<PackageReference Include="PublicApiGenerator" />
5654
<PackageReference Include="coverlet.msbuild" PrivateAssets="All" />
57-
<PackageReference Include="Verify.Xunit" />
55+
<PackageReference Include="Verify.NUnit" />
5856
</ItemGroup>
5957
<ItemGroup Condition="'$(IsTestProject)' != 'true'">
6058
<PackageReference Include="Microsoft.SourceLink.GitHub" PrivateAssets="All" />

src/Directory.Packages.props

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,13 @@
1111
<ItemGroup>
1212
<PackageVersion Include="coverlet.msbuild" Version="6.0.4" />
1313
<PackageVersion Include="DynamicData" Version="9.4.1" />
14-
<PackageVersion Include="FluentAssertions" Version="8.6.0" />
1514
<PackageVersion Include="JetBrains.DotMemoryUnit" Version="3.2.20220510" />
1615
<PackageVersion Include="Microsoft.CodeAnalysis.Analyzers" Version="3.11.0" />
1716
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="4.14.0" />
1817
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.14.1" />
18+
<PackageVersion Include="NUnit" Version="4.4.0" />
19+
<PackageVersion Include="NUnit3TestAdapter" Version="5.1.0" />
20+
<PackageVersion Include="NUnit.Analyzers" Version="4.10.0" />
1921
<PackageVersion Include="Microsoft.Reactive.Testing" Version="6.0.2" />
2022
<PackageVersion Include="System.Reactive" Version="6.0.2" />
2123
<PackageVersion Include="Microsoft.SourceLink.GitHub" Version="8.0.0" />
@@ -36,11 +38,7 @@
3638
<PackageVersion Include="System.IO.FileSystem.Primitives" Version="4.3.0" />
3739
<PackageVersion Include="System.Runtime.Serialization.Primitives" Version="4.3.0" />
3840
<PackageVersion Include="System.Text.Json" Version="9.0.8" />
39-
<PackageVersion Include="Verify.Xunit" Version="30.7.3" />
40-
<PackageVersion Include="xunit" Version="2.9.3" />
41-
<PackageVersion Include="xunit.runner.console" Version="2.9.3" />
42-
<PackageVersion Include="xunit.runner.visualstudio" Version="3.1.4" />
43-
<PackageVersion Include="Xunit.StaFact" Version="1.2.69" />
41+
<PackageVersion Include="Verify.NUnit" Version="30.7.3" />
4442
<PackageVersion Include="Xamarin.AndroidX.Core" Version="$(XamarinAndroidXCoreVersion)" />
4543
<PackageVersion Include="Xamarin.AndroidX.Preference" Version="1.2.1.9" />
4644
<PackageVersion Include="Xamarin.AndroidX.Legacy.Support.Core.UI" Version="1.0.0.29" />

0 commit comments

Comments
 (0)