diff --git a/.editorconfig b/.editorconfig index 0194b90c..40b29b9d 100644 --- a/.editorconfig +++ b/.editorconfig @@ -10,6 +10,7 @@ insert_final_newline = true # Sort using and Import directives with System.* appearing first dotnet_sort_system_directives_first = true +csharp_using_directive_placement = outside_namespace:warning # Avoid "this." and "Me." if not necessary dotnet_style_qualification_for_field = false:suggestion diff --git a/NuGet.Config b/NuGet.Config index fe6bfad5..07534d7a 100644 --- a/NuGet.Config +++ b/NuGet.Config @@ -4,5 +4,6 @@ + diff --git a/src/xunit.analyzers.fixes/xunit.analyzers.fixes.csproj b/src/xunit.analyzers.fixes/xunit.analyzers.fixes.csproj index df0e71ae..39b5306a 100644 --- a/src/xunit.analyzers.fixes/xunit.analyzers.fixes.csproj +++ b/src/xunit.analyzers.fixes/xunit.analyzers.fixes.csproj @@ -9,14 +9,15 @@ false false false + portable-net45+win8 Xunit.Analyzers - netstandard1.3 + netstandard1.1 full - - + + diff --git a/src/xunit.analyzers.nuspec b/src/xunit.analyzers.nuspec index f494b24e..80d715d2 100644 --- a/src/xunit.analyzers.nuspec +++ b/src/xunit.analyzers.nuspec @@ -15,8 +15,8 @@ xunit.analyzers, analyzers, roslyn, xunit, xunit.net - - + + \ No newline at end of file diff --git a/src/xunit.analyzers/InlineDataMustMatchTheoryParameters.cs b/src/xunit.analyzers/InlineDataMustMatchTheoryParameters.cs index e4615638..68c803b3 100644 --- a/src/xunit.analyzers/InlineDataMustMatchTheoryParameters.cs +++ b/src/xunit.analyzers/InlineDataMustMatchTheoryParameters.cs @@ -23,7 +23,7 @@ public InlineDataMustMatchTheoryParameters() } /// For testing purposes only. - public InlineDataMustMatchTheoryParameters(string assemblyVersion) : base(new Version(assemblyVersion)) + protected InlineDataMustMatchTheoryParameters(string assemblyVersion) : base(new Version(assemblyVersion)) { } diff --git a/src/xunit.analyzers/TheoryMethodCannotHaveDefaultParameter.cs b/src/xunit.analyzers/TheoryMethodCannotHaveDefaultParameter.cs index ab12d8ef..b28dc989 100644 --- a/src/xunit.analyzers/TheoryMethodCannotHaveDefaultParameter.cs +++ b/src/xunit.analyzers/TheoryMethodCannotHaveDefaultParameter.cs @@ -13,7 +13,7 @@ public class TheoryMethodCannotHaveDefaultParameter : XunitDiagnosticAnalyzer public TheoryMethodCannotHaveDefaultParameter() { } /// For testing purposes only. - public TheoryMethodCannotHaveDefaultParameter(string assemblyVersion) : base(new Version(assemblyVersion)) { } + protected TheoryMethodCannotHaveDefaultParameter(string assemblyVersion) : base(new Version(assemblyVersion)) { } public override ImmutableArray SupportedDiagnostics => ImmutableArray.Create(Descriptors.X1023_TheoryMethodCannotHaveDefaultParameter); diff --git a/src/xunit.analyzers/TheoryMethodCannotHaveParamsArray.cs b/src/xunit.analyzers/TheoryMethodCannotHaveParamsArray.cs index 0b39f3bc..91caae54 100644 --- a/src/xunit.analyzers/TheoryMethodCannotHaveParamsArray.cs +++ b/src/xunit.analyzers/TheoryMethodCannotHaveParamsArray.cs @@ -12,7 +12,7 @@ public class TheoryMethodCannotHaveParamsArray : XunitDiagnosticAnalyzer public TheoryMethodCannotHaveParamsArray() { } /// For testing purposes only. - public TheoryMethodCannotHaveParamsArray(string assemblyVersion) : base(new Version(assemblyVersion)) { } + protected TheoryMethodCannotHaveParamsArray(string assemblyVersion) : base(new Version(assemblyVersion)) { } public override ImmutableArray SupportedDiagnostics => ImmutableArray.Create(Descriptors.X1022_TheoryMethodCannotHaveParameterArray); diff --git a/src/xunit.analyzers/xunit.analyzers.csproj b/src/xunit.analyzers/xunit.analyzers.csproj index 9d23e53e..e0b32a1f 100644 --- a/src/xunit.analyzers/xunit.analyzers.csproj +++ b/src/xunit.analyzers/xunit.analyzers.csproj @@ -9,14 +9,15 @@ false false false + portable-net45+win8 Xunit.Analyzers - netstandard1.3 + netstandard1.1 full - - + + \ No newline at end of file diff --git a/test/xunit.analyzers.tests/AssertCollectionContainsShouldNotUseBoolCheckTests.cs b/test/xunit.analyzers.tests/AssertCollectionContainsShouldNotUseBoolCheckTests.cs index c979949e..db281bba 100644 --- a/test/xunit.analyzers.tests/AssertCollectionContainsShouldNotUseBoolCheckTests.cs +++ b/test/xunit.analyzers.tests/AssertCollectionContainsShouldNotUseBoolCheckTests.cs @@ -1,13 +1,9 @@ -using System.Collections.Generic; -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.Diagnostics; +using Verify = Xunit.Analyzers.CSharpVerifier; namespace Xunit.Analyzers { public class AssertCollectionContainsShouldNotUseBoolCheckTests { - private readonly DiagnosticAnalyzer analyzer = new AssertCollectionContainsShouldNotUseBoolCheck(); - public static TheoryData Collections { get; } = new TheoryData { "new System.Collections.Generic.List()", @@ -21,165 +17,155 @@ public class AssertCollectionContainsShouldNotUseBoolCheckTests "System.Linq.Enumerable.Empty()" }; - private static void CheckDiagnostics(IEnumerable diagnostics) - { - Assert.Collection(diagnostics, d => - { - Assert.Equal("Do not use Contains() to check if a value exists in a collection.", d.GetMessage()); - Assert.Equal("xUnit2017", d.Id); - Assert.Equal(DiagnosticSeverity.Warning, d.Severity); - }); - } - [Theory] [MemberData(nameof(Collections))] public async void FindsWarningForTrueCollectionContainsCheck(string collection) { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = @"class TestClass { void TestMethod() { - Xunit.Assert.True(" + collection + @".Contains(1)); -} }"); + [|Xunit.Assert.True(" + collection + @".Contains(1))|]; +} }"; - CheckDiagnostics(diagnostics); + await Verify.VerifyAnalyzerAsync(source); } [Theory] [MemberData(nameof(Collections))] public async void FindsWarningForFalseCollectionContainsCheck(string collection) { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = @"class TestClass { void TestMethod() { - Xunit.Assert.False(" + collection + @".Contains(1)); -} }"); + [|Xunit.Assert.False(" + collection + @".Contains(1))|]; +} }"; - CheckDiagnostics(diagnostics); + await Verify.VerifyAnalyzerAsync(source); } [Theory] [MemberData(nameof(Enumerables))] public async void FindsWarningForTrueLinqContainsCheck(string enumerable) { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = @"using System.Linq; class TestClass { void TestMethod() { - Xunit.Assert.True(" + enumerable + @".Contains(1)); -} }"); + [|Xunit.Assert.True(" + enumerable + @".Contains(1))|]; +} }"; - CheckDiagnostics(diagnostics); + await Verify.VerifyAnalyzerAsync(source); } [Theory] [MemberData(nameof(Enumerables))] public async void FindsWarningForTrueLinqContainsCheckWithEqualityComparer(string enumerable) { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = @"using System.Linq; class TestClass { void TestMethod() { - Xunit.Assert.True(" + enumerable + @".Contains(1, System.Collections.Generic.EqualityComparer.Default)); -} }"); + [|Xunit.Assert.True(" + enumerable + @".Contains(1, System.Collections.Generic.EqualityComparer.Default))|]; +} }"; - CheckDiagnostics(diagnostics); + await Verify.VerifyAnalyzerAsync(source); } [Theory] [MemberData(nameof(Enumerables))] public async void FindsWarningForFalseLinqContainsCheck(string enumerable) { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = @"using System.Linq; class TestClass { void TestMethod() { - Xunit.Assert.False(" + enumerable + @".Contains(1)); -} }"); + [|Xunit.Assert.False(" + enumerable + @".Contains(1))|]; +} }"; - CheckDiagnostics(diagnostics); + await Verify.VerifyAnalyzerAsync(source); } [Theory] [MemberData(nameof(Enumerables))] public async void FindsWarningForFalseLinqContainsCheckWithEqualityComparer(string enumerable) { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = @"using System.Linq; class TestClass { void TestMethod() { - Xunit.Assert.False(" + enumerable + @".Contains(1, System.Collections.Generic.EqualityComparer.Default)); -} }"); + [|Xunit.Assert.False(" + enumerable + @".Contains(1, System.Collections.Generic.EqualityComparer.Default))|]; +} }"; - CheckDiagnostics(diagnostics); + await Verify.VerifyAnalyzerAsync(source); } [Theory] [MemberData(nameof(Collections))] public async void DoesNotFindWarningForTrueCollectionContainsCheckWithAssertionMessage(string collection) { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = @"class TestClass { void TestMethod() { Xunit.Assert.True(" + collection + @".Contains(1), ""Custom message""); -} }"); +} }"; - Assert.Empty(diagnostics); + await Verify.VerifyAnalyzerAsync(source); } [Theory] [MemberData(nameof(Collections))] public async void DoesNotFindWarningForFalseCollectionContainsCheckWithAssertionMessage(string collection) { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = @"class TestClass { void TestMethod() { Xunit.Assert.False(" + collection + @".Contains(1), ""Custom message""); -} }"); +} }"; - Assert.Empty(diagnostics); + await Verify.VerifyAnalyzerAsync(source); } [Theory] [MemberData(nameof(Enumerables))] public async void DoesNotFindWarningForTrueLinqContainsCheckWithAssertionMessage(string enumerable) { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = @"using System.Linq; class TestClass { void TestMethod() { Xunit.Assert.True(" + enumerable + @".Contains(1), ""Custom message""); -} }"); +} }"; - Assert.Empty(diagnostics); + await Verify.VerifyAnalyzerAsync(source); } [Theory] [MemberData(nameof(Enumerables))] public async void DoesNotFindWarningForFalseLinqContainsCheckWithAssertionMessage(string enumerable) { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = @"using System.Linq; class TestClass { void TestMethod() { Xunit.Assert.False(" + enumerable + @".Contains(1), ""Custom message""); -} }"); +} }"; - Assert.Empty(diagnostics); + await Verify.VerifyAnalyzerAsync(source); } [Fact] public async void DoesNotCrashForCollectionWithDifferentTypeParametersThanICollectionImplementation_ZeroParameters() { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = @"using System.Collections.Generic; class IntList : List { } class TestClass { void TestMethod() { - Xunit.Assert.False(new IntList().Contains(1)); -} }"); + [|Xunit.Assert.False(new IntList().Contains(1))|]; +} }"; - CheckDiagnostics(diagnostics); + await Verify.VerifyAnalyzerAsync(source); } [Fact] public async void DoesNotCrashForCollectionWithDifferentTypeParametersThanICollectionImplementation_TwoParameters() { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = @"using System.Collections.Generic; class TestClass { void TestMethod() { Xunit.Assert.False(new Dictionary().ContainsKey(1)); -} }"); +} }"; - Assert.Empty(diagnostics); + await Verify.VerifyAnalyzerAsync(source); } } -} \ No newline at end of file +} diff --git a/test/xunit.analyzers.tests/AssertEmptyCollectionCheckShouldNotBeUsedTests.cs b/test/xunit.analyzers.tests/AssertEmptyCollectionCheckShouldNotBeUsedTests.cs index ecd3e227..f9df19e8 100644 --- a/test/xunit.analyzers.tests/AssertEmptyCollectionCheckShouldNotBeUsedTests.cs +++ b/test/xunit.analyzers.tests/AssertEmptyCollectionCheckShouldNotBeUsedTests.cs @@ -1,12 +1,9 @@ -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.Diagnostics; +using Verify = Xunit.Analyzers.CSharpVerifier; namespace Xunit.Analyzers { public class AssertEmptyCollectionCheckShouldNotBeUsedTests { - private readonly DiagnosticAnalyzer analyzer = new AssertEmptyCollectionCheckShouldNotBeUsed(); - public static TheoryData Collections { get; } = new TheoryData { "new int[0]", @@ -20,28 +17,23 @@ public class AssertEmptyCollectionCheckShouldNotBeUsedTests [MemberData(nameof(Collections))] public async void FindsWarningForCollectionCheckWithoutAction(string collection) { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = @"class TestClass { void TestMethod() { - Xunit.Assert.Collection(" + collection + @"); -} }"); + [|Xunit.Assert.Collection(" + collection + @")|]; +} }"; - Assert.Collection(diagnostics, d => - { - Assert.Equal("Do not use Assert.Collection() to check for empty collections.", d.GetMessage()); - Assert.Equal("xUnit2011", d.Id); - Assert.Equal(DiagnosticSeverity.Warning, d.Severity); - }); + await Verify.VerifyAnalyzerAsync(source); } [Theory] [MemberData(nameof(Collections))] public async void DoesNotFindWarningForCollectionCheckWithAction(string collection) { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = @"class TestClass { void TestMethod() { Xunit.Assert.Collection(" + collection + @", i => Xunit.Assert.True(true)); -} }"); - Assert.Empty(diagnostics); +} }"; + await Verify.VerifyAnalyzerAsync(source); } } } diff --git a/test/xunit.analyzers.tests/AssertEnumerableAnyCheckShouldNotBeUsedForCollectionContainsCheckTests.cs b/test/xunit.analyzers.tests/AssertEnumerableAnyCheckShouldNotBeUsedForCollectionContainsCheckTests.cs index e8ac7cc0..e9d8df02 100644 --- a/test/xunit.analyzers.tests/AssertEnumerableAnyCheckShouldNotBeUsedForCollectionContainsCheckTests.cs +++ b/test/xunit.analyzers.tests/AssertEnumerableAnyCheckShouldNotBeUsedForCollectionContainsCheckTests.cs @@ -1,30 +1,22 @@ -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.Diagnostics; +using Verify = Xunit.Analyzers.CSharpVerifier; namespace Xunit.Analyzers { public class AssertEnumerableAnyCheckShouldNotBeUsedForCollectionContainsCheckTests { - private readonly DiagnosticAnalyzer analyzer = new AssertEnumerableAnyCheckShouldNotBeUsedForCollectionContainsCheck(); - public static TheoryData BooleanMethods = new TheoryData { "True", "False" }; [Theory] [MemberData(nameof(BooleanMethods))] public async void FindsWarning_ForLinqAnyCheck(string method) { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = @"using System.Linq; class TestClass { void TestMethod() { - Xunit.Assert." + method + @"(new [] { 1 }.Any(i => true)); -} }"); + [|Xunit.Assert." + method + @"(new [] { 1 }.Any(i => true))|]; +} }"; - Assert.Collection(diagnostics, d => - { - Assert.Equal("Do not use Enumerable.Any() to check if a value exists in a collection.", d.GetMessage()); - Assert.Equal("xUnit2012", d.Id); - Assert.Equal(DiagnosticSeverity.Warning, d.Severity); - }); + await Verify.VerifyAnalyzerAsync(source); } } -} \ No newline at end of file +} diff --git a/test/xunit.analyzers.tests/AssertEqualGenericShouldNotBeUsedForStringValueTests.cs b/test/xunit.analyzers.tests/AssertEqualGenericShouldNotBeUsedForStringValueTests.cs index 41a36e1d..a1753d16 100644 --- a/test/xunit.analyzers.tests/AssertEqualGenericShouldNotBeUsedForStringValueTests.cs +++ b/test/xunit.analyzers.tests/AssertEqualGenericShouldNotBeUsedForStringValueTests.cs @@ -1,12 +1,9 @@ -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.Diagnostics; +using Verify = Xunit.Analyzers.CSharpVerifier; namespace Xunit.Analyzers { public class AssertEqualGenericShouldNotBeUsedForStringValueTests { - readonly DiagnosticAnalyzer analyzer = new AssertEqualGenericShouldNotBeUsedForStringValue(); - public static TheoryData Data { get; } = new TheoryData { {"true.ToString()", "\"True\""}, @@ -22,62 +19,47 @@ public class AssertEqualGenericShouldNotBeUsedForStringValueTests [MemberData(nameof(Data))] public async void DoesNotFindWarningForStringEqualityCheckWithoutGenericType(string expected, string value) { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = @"class TestClass { void TestMethod() { Xunit.Assert.Equal(" + expected + @", " + value + @"); -} }"); - Assert.Empty(diagnostics); +} }"; + await Verify.VerifyAnalyzerAsync(source); } [Theory] [MemberData(nameof(Data))] public async void FindsWarningForStringEqualityCheckWithGenericType(string expected, string value) { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = @"class TestClass { void TestMethod() { - Xunit.Assert.Equal(" + expected + @", " + value + @"); -} }"); + [|Xunit.Assert.Equal(" + expected + @", " + value + @")|]; +} }"; - Assert.Collection(diagnostics, d => - { - Assert.Equal("Do not use generic Assert.Equal overload to test for string equality.", d.GetMessage()); - Assert.Equal("xUnit2006", d.Id); - Assert.Equal(DiagnosticSeverity.Warning, d.Severity); - }); + await Verify.VerifyAnalyzerAsync(source); } [Theory] [MemberData(nameof(Data))] public async void FindsWarningForStrictStringEqualityCheck(string expected, string value) { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = @"class TestClass { void TestMethod() { - Xunit.Assert.StrictEqual(" + expected + @", " + value + @"); -} }"); + [|Xunit.Assert.StrictEqual(" + expected + @", " + value + @")|]; +} }"; - Assert.Collection(diagnostics, d => - { - Assert.Equal("Do not use Assert.StrictEqual to test for string equality.", d.GetMessage()); - Assert.Equal("xUnit2006", d.Id); - Assert.Equal(DiagnosticSeverity.Warning, d.Severity); - }); + await Verify.VerifyAnalyzerAsync(source); } [Theory] [MemberData(nameof(Data))] public async void FindsWarningForStrictStringEqualityCheckWithGenericType(string expected, string value) { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = @"class TestClass { void TestMethod() { - Xunit.Assert.StrictEqual(" + expected + @", " + value + @"); -} }"); + [|Xunit.Assert.StrictEqual(" + expected + @", " + value + @")|]; +} }"; - Assert.Collection(diagnostics, d => - { - Assert.Equal("Do not use Assert.StrictEqual to test for string equality.", d.GetMessage()); - Assert.Equal("xUnit2006", d.Id); - Assert.Equal(DiagnosticSeverity.Warning, d.Severity); - }); + await Verify.VerifyAnalyzerAsync(source); } } } diff --git a/test/xunit.analyzers.tests/AssertEqualLiteralValueShouldBeFirstFixerTests.cs b/test/xunit.analyzers.tests/AssertEqualLiteralValueShouldBeFirstFixerTests.cs index 46b6fd9d..0dc03670 100644 --- a/test/xunit.analyzers.tests/AssertEqualLiteralValueShouldBeFirstFixerTests.cs +++ b/test/xunit.analyzers.tests/AssertEqualLiteralValueShouldBeFirstFixerTests.cs @@ -1,13 +1,10 @@ -using Microsoft.CodeAnalysis.CodeFixes; -using Microsoft.CodeAnalysis.Diagnostics; +using Microsoft.CodeAnalysis.Testing; +using Verify = Xunit.Analyzers.CSharpVerifier; namespace Xunit.Analyzers { public class AssertEqualLiteralValueShouldBeFirstFixerTests { - readonly DiagnosticAnalyzer analyzer = new AssertEqualLiteralValueShouldBeFirst(); - readonly CodeFixProvider fixer = new AssertEqualLiteralValueShouldBeFirstFixer(); - static readonly string Template = @" public class TestClass {{ @@ -23,44 +20,40 @@ public void TestMethod() public async void SwapArguments() { var source = string.Format(Template, "Assert.Equal(i, 0)"); - var expected = string.Format(Template, "Assert.Equal(0, i)"); - - var actual = await CodeAnalyzerHelper.GetFixedCodeAsync(analyzer, fixer, source); + var fixedSource = string.Format(Template, "Assert.Equal(0, i)"); - Assert.Equal(expected, actual); + var expected = Verify.Diagnostic().WithLocation(8, 9).WithArguments("0", "Assert.Equal(expected, actual)", "TestMethod", "TestClass"); + await Verify.VerifyCodeFixAsync(source, expected, fixedSource); } [Fact] public async void NamedArgumentsOnlySwapsArgumentValues() { var source = string.Format(Template, "Assert.Equal(actual: 0, expected: i)"); - var expected = string.Format(Template, "Assert.Equal(actual: i, expected: 0)"); + var fixedSource = string.Format(Template, "Assert.Equal(actual: i, expected: 0)"); - var actual = await CodeAnalyzerHelper.GetFixedCodeAsync(analyzer, fixer, source); - - Assert.Equal(expected, actual); + var expected = Verify.Diagnostic().WithLocation(8, 9).WithArguments("0", "Assert.Equal(expected, actual)", "TestMethod", "TestClass"); + await Verify.VerifyCodeFixAsync(source, expected, fixedSource); } [Fact] public async void NamedArgumentsInCorrectPositionOnlySwapsArgumentValues() { var source = string.Format(Template, "Assert.Equal(expected: i, actual: 0)"); - var expected = string.Format(Template, "Assert.Equal(expected: 0, actual: i)"); - - var actual = await CodeAnalyzerHelper.GetFixedCodeAsync(analyzer, fixer, source); + var fixedSource = string.Format(Template, "Assert.Equal(expected: 0, actual: i)"); - Assert.Equal(expected, actual); + var expected = Verify.Diagnostic().WithLocation(8, 9).WithArguments("0", "Assert.Equal(expected, actual)", "TestMethod", "TestClass"); + await Verify.VerifyCodeFixAsync(source, expected, fixedSource); } [Fact] public async void NamedArgumentsTakePossibleThirdParameterIntoAccount() { var source = string.Format(Template, "Assert.Equal(comparer: null, actual: 0, expected: i)"); - var expected = string.Format(Template, "Assert.Equal(comparer: null, actual: i, expected: 0)"); + var fixedSource = string.Format(Template, "Assert.Equal(comparer: null, actual: i, expected: 0)"); - var actual = await CodeAnalyzerHelper.GetFixedCodeAsync(analyzer, fixer, source); - - Assert.Equal(expected, actual); + var expected = Verify.Diagnostic().WithLocation(8, 9).WithArguments("0", "Assert.Equal(expected, actual, comparer)", "TestMethod", "TestClass"); + await Verify.VerifyCodeFixAsync(source, expected, fixedSource); } [Fact] @@ -69,11 +62,14 @@ public async void PartiallyNamedArgumentsInCorrectPositionOnlySwapsArgumentValue // C# 7.2 supports this new supported "non-trailing named arguments" var source = string.Format(Template, "Assert.Equal(expected: i, 0)"); - var expected = string.Format(Template, "Assert.Equal(expected: 0, i)"); - - var actual = await CodeAnalyzerHelper.GetFixedCodeAsync(analyzer, fixer, source, CompilationReporting.IgnoreErrors); - - Assert.Equal(expected, actual); + var fixedSource = string.Format(Template, "Assert.Equal(expected: 0, i)"); + + DiagnosticResult[] expected = + { + Verify.Diagnostic().WithLocation(8, 9).WithArguments("0", "Assert.Equal(expected, actual)", "TestMethod", "TestClass"), + Verify.CompilerError("CS1738").WithLocation(8, 41).WithMessage("Named argument specifications must appear after all fixed arguments have been specified"), + }; + await Verify.VerifyCodeFixAsync(source, expected, fixedSource); } } } diff --git a/test/xunit.analyzers.tests/AssertEqualLiteralValueShouldBeFirstTests.cs b/test/xunit.analyzers.tests/AssertEqualLiteralValueShouldBeFirstTests.cs index e73b227f..0da2a139 100644 --- a/test/xunit.analyzers.tests/AssertEqualLiteralValueShouldBeFirstTests.cs +++ b/test/xunit.analyzers.tests/AssertEqualLiteralValueShouldBeFirstTests.cs @@ -1,21 +1,18 @@ -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.Diagnostics; +using Verify = Xunit.Analyzers.CSharpVerifier; namespace Xunit.Analyzers { public class AssertEqualLiteralValueShouldBeFirstTests { - readonly DiagnosticAnalyzer analyzer = new AssertEqualLiteralValueShouldBeFirst(); - [Fact] public async void DoesNotFindWarningWhenConstantOrLiteralUsedForBothArguments() { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = @"class TestClass { void TestMethod() { Xunit.Assert.Equal(""TestMethod"", nameof(TestMethod)); -} }"); +} }"; - Assert.Empty(diagnostics); + await Verify.VerifyAnalyzerAsync(source); } public static TheoryData TypesAndValues { get; } = new TheoryData @@ -35,30 +32,26 @@ public async void DoesNotFindWarningWhenConstantOrLiteralUsedForBothArguments() [MemberData(nameof(TypesAndValues))] public async void DoesNotFindWarningForExpectedConstantOrLiteralValueAsFirstArgument(string type, string value) { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = @"class TestClass { void TestMethod() { var v = default(" + type + @"); Xunit.Assert.Equal(" + value + @", v); -} }"); - Assert.Empty(diagnostics); +} }"; + await Verify.VerifyAnalyzerAsync(source); } [Theory] [MemberData(nameof(TypesAndValues))] public async void FindsWarningForExpectedConstantOrLiteralValueAsSecondArgument(string type, string value) { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = @"class TestClass { void TestMethod() { var v = default(" + type + @"); Xunit.Assert.Equal(v, " + value + @"); -} }"); +} }"; - Assert.Collection(diagnostics, d => - { - Assert.Equal($"The literal or constant value {value} should be passed as the 'expected' argument in the call to 'Assert.Equal(expected, actual)' in method 'TestMethod' on type 'TestClass'.", d.GetMessage()); - Assert.Equal("xUnit2000", d.Id); - Assert.Equal(DiagnosticSeverity.Warning, d.Severity); - }); + var expected = Verify.Diagnostic().WithLocation(3, 5).WithArguments(value, "Assert.Equal(expected, actual)", "TestMethod", "TestClass"); + await Verify.VerifyAnalyzerAsync(source, expected); } [Theory] @@ -67,47 +60,43 @@ public async void FindsWarningForExpectedConstantOrLiteralValueAsSecondArgument( public async void DoesNotFindWarningForExpectedConstantOrLiteralValueAsNamedExpectedArgument(bool useAlternateForm) { var s = useAlternateForm ? "@" : ""; - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = @"class TestClass { void TestMethod() { var v = default(int); Xunit.Assert.Equal(" + s + "actual: v, " + s + @"expected: 0); -} }"); +} }"; - Assert.Empty(diagnostics); + await Verify.VerifyAnalyzerAsync(source); } [Theory] [MemberData(nameof(TypesAndValues))] public async void FindsWarningForExpectedConstantOrLiteralValueAsNamedExpectedArgument(string type, string value) { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = @"class TestClass { void TestMethod() { var v = default(" + type + @"); Xunit.Assert.Equal(actual: " + value + @",expected: v); -} }"); +} }"; - Assert.Collection(diagnostics, d => - { - Assert.Equal($"The literal or constant value {value} should be passed as the 'expected' argument in the call to 'Assert.Equal(expected, actual)' in method 'TestMethod' on type 'TestClass'.", d.GetMessage()); - Assert.Equal("xUnit2000", d.Id); - Assert.Equal(DiagnosticSeverity.Warning, d.Severity); - }); + var expected = Verify.Diagnostic().WithLocation(3, 5).WithArguments(value, "Assert.Equal(expected, actual)", "TestMethod", "TestClass"); + await Verify.VerifyAnalyzerAsync(source, expected); } [Theory] - [InlineData("act", "exp")] - [InlineData("expected", "expected")] - [InlineData("actual", "actual")] - [InlineData("foo", "bar")] + [InlineData("{|CS1739:act|}", "exp")] + [InlineData("expected", "{|CS1740:expected|}")] + [InlineData("actual", "{|CS1740:actual|}")] + [InlineData("{|CS1739:foo|}", "bar")] public async void DoesNotFindWarningWhenArgumentsAreNotNamedCorrectly(string firstArgumentName, string secondArgumentName) { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, CompilationReporting.IgnoreErrors, + var source = @"class TestClass { void TestMethod() { var v = default(int); Xunit.Assert.Equal(" + firstArgumentName + @": 1, " + secondArgumentName + @": v); -} }"); +} }"; - Assert.Empty(diagnostics); + await Verify.VerifyAnalyzerAsync(source); } } } diff --git a/test/xunit.analyzers.tests/AssertEqualPrecisionShouldBeInRangeTest.cs b/test/xunit.analyzers.tests/AssertEqualPrecisionShouldBeInRangeTest.cs index b91f405f..5371a2cf 100644 --- a/test/xunit.analyzers.tests/AssertEqualPrecisionShouldBeInRangeTest.cs +++ b/test/xunit.analyzers.tests/AssertEqualPrecisionShouldBeInRangeTest.cs @@ -1,93 +1,76 @@ -using System.Collections.Immutable; -using System.Threading.Tasks; -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.Diagnostics; +using Microsoft.CodeAnalysis; +using Verify = Xunit.Analyzers.CSharpVerifier; namespace Xunit.Analyzers { public class AssertEqualPrecisionShouldBeInRangeTest { - public class Analyzer - { - readonly DiagnosticAnalyzer analyzer = new AssertEqualPrecisionShouldBeInRange(); - - [Theory] - [InlineData(0)] - [InlineData(1)] - [InlineData(8)] - [InlineData(14)] - [InlineData(15)] - public async void DoesNotFindError_ForDoubleArgumentWithPrecisionProvidedInRange(int precision) - { - var diagnostics = await AnalyzeTestMethod( - "double num = 0.133d;" + - $"Xunit.Assert.Equal(0.13d, num, {precision});"); + static readonly string Template = "class TestClass {{ void TestMethod() {{{0}}}}}"; - Assert.Empty(diagnostics); - } + [Theory] + [InlineData(0)] + [InlineData(1)] + [InlineData(8)] + [InlineData(14)] + [InlineData(15)] + public async void DoesNotFindError_ForDoubleArgumentWithPrecisionProvidedInRange(int precision) + { + var source = string.Format(Template, + "double num = 0.133d;" + + $"Xunit.Assert.Equal(0.13d, num, {precision});"); - [Theory] - [InlineData(int.MinValue)] - [InlineData(-2000)] - [InlineData(-1)] - [InlineData(16)] - [InlineData(17000)] - [InlineData(int.MaxValue)] - public async void FindsError_ForDoubleArgumentWithPrecisionProvidedOutOfRange(int precision) - { - var diagnostics = await AnalyzeTestMethod( - "double num = 0.133d;" + - $"Xunit.Assert.Equal(0.13d, num, {precision});"); + await Verify.VerifyAnalyzerAsync(source); + } - Assert.Collection(diagnostics, d => - { - Assert.Equal("Keep precision in range [0..15] when asserting equality of double typed actual value.", d.GetMessage()); - Assert.Equal("xUnit2016", d.Id); - Assert.Equal(DiagnosticSeverity.Error, d.Severity); - }); - } + [Theory] + [InlineData(int.MinValue)] + [InlineData(-2000)] + [InlineData(-1)] + [InlineData(16)] + [InlineData(17000)] + [InlineData(int.MaxValue)] + public async void FindsError_ForDoubleArgumentWithPrecisionProvidedOutOfRange(int precision) + { + var source = string.Format(Template, + "double num = 0.133d;" + + $"Xunit.Assert.Equal(0.13d, num, {precision});"); - [Theory] - [InlineData(0)] - [InlineData(1)] - [InlineData(14)] - [InlineData(27)] - [InlineData(28)] - public async void DoesNotFindError_ForDecimalArgumentWithPrecisionProvidedInRange(int precision) - { - var diagnostics = await AnalyzeTestMethod( - "decimal num = 0.133m;" + - $"Xunit.Assert.Equal(0.13m, num, {precision});"); + var expected = Verify.Diagnostic().WithLocation(1, 89).WithSeverity(DiagnosticSeverity.Error) + .WithArguments("[0..15]", "double"); + await Verify.VerifyAnalyzerAsync(source, expected); + } - Assert.Empty(diagnostics); - } + [Theory] + [InlineData(0)] + [InlineData(1)] + [InlineData(14)] + [InlineData(27)] + [InlineData(28)] + public async void DoesNotFindError_ForDecimalArgumentWithPrecisionProvidedInRange(int precision) + { + var source = string.Format(Template, + "decimal num = 0.133m;" + + $"Xunit.Assert.Equal(0.13m, num, {precision});"); - [Theory] - [InlineData(int.MinValue)] - [InlineData(-2000)] - [InlineData(-1)] - [InlineData(29)] - [InlineData(30000)] - [InlineData(int.MaxValue)] - public async void FindsError_ForDecimalArgumentWithPrecisionProvidedOutOfRange(int precision) - { - var diagnostics = await AnalyzeTestMethod( - "decimal num = 0.133m;" + - $"Xunit.Assert.Equal(0.13m, num, {precision});"); + await Verify.VerifyAnalyzerAsync(source); + } - Assert.Collection(diagnostics, d => - { - Assert.Equal("Keep precision in range [0..28] when asserting equality of decimal typed actual value.", d.GetMessage()); - Assert.Equal("xUnit2016", d.Id); - Assert.Equal(DiagnosticSeverity.Error, d.Severity); - }); - } + [Theory] + [InlineData(int.MinValue)] + [InlineData(-2000)] + [InlineData(-1)] + [InlineData(29)] + [InlineData(30000)] + [InlineData(int.MaxValue)] + public async void FindsError_ForDecimalArgumentWithPrecisionProvidedOutOfRange(int precision) + { + var source = string.Format(Template, + "decimal num = 0.133m;" + + $"Xunit.Assert.Equal(0.13m, num, {precision});"); - private async Task> AnalyzeTestMethod(string methodBody) - { - return await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, - "class TestClass { void TestMethod() {" + methodBody + "}}"); - } + var expected = Verify.Diagnostic().WithLocation(1, 90).WithSeverity(DiagnosticSeverity.Error) + .WithArguments("[0..28]", "decimal"); + await Verify.VerifyAnalyzerAsync(source, expected); } } -} \ No newline at end of file +} diff --git a/test/xunit.analyzers.tests/AssertEqualShouldNotBeUsedForBoolLiteralCheckTests.cs b/test/xunit.analyzers.tests/AssertEqualShouldNotBeUsedForBoolLiteralCheckTests.cs index 44f5c81f..e19b5182 100644 --- a/test/xunit.analyzers.tests/AssertEqualShouldNotBeUsedForBoolLiteralCheckTests.cs +++ b/test/xunit.analyzers.tests/AssertEqualShouldNotBeUsedForBoolLiteralCheckTests.cs @@ -1,36 +1,24 @@ -using System.Collections.Generic; -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.Diagnostics; +using Microsoft.CodeAnalysis; +using Verify = Xunit.Analyzers.CSharpVerifier; namespace Xunit.Analyzers { public class AssertEqualShouldNotBeUsedForBoolLiteralCheckTests { - readonly DiagnosticAnalyzer analyzer = new AssertEqualShouldNotBeUsedForBoolLiteralCheck(); - public static TheoryData Methods = new TheoryData { "Equal", "NotEqual", "StrictEqual", "NotStrictEqual", }; - private static void AssertHasDiagnostic(IEnumerable diagnostics, string method) - { - Assert.Collection(diagnostics, d => - { - Assert.Equal($"Do not use Assert.{method}() to check for boolean conditions.", d.GetMessage()); - Assert.Equal("xUnit2004", d.Id); - Assert.Equal(DiagnosticSeverity.Warning, d.Severity); - }); - } - [Theory] [MemberData(nameof(Methods))] public async void FindsWarning_ForFirstBoolLiteral(string method) { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = @"class TestClass { void TestMethod() { bool val = true; Xunit.Assert." + method + @"(true, val); -} }"); +} }"; - AssertHasDiagnostic(diagnostics, method); + var expected = Verify.Diagnostic().WithSpan(3, 5, 3, 29 + method.Length).WithSeverity(DiagnosticSeverity.Warning).WithArguments($"Assert.{method}()"); + await Verify.VerifyAnalyzerAsync(source, expected); } [Theory] @@ -38,52 +26,53 @@ public async void FindsWarning_ForFirstBoolLiteral(string method) [InlineData("NotEqual")] public async void FindsWarning_ForFirstBoolLiteral_WithCustomComparer(string method) { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = @"class TestClass { void TestMethod() { bool val = false; Xunit.Assert." + method + @"(false, val, System.Collections.Generic.EqualityComparer.Default); -} }"); +} }"; - AssertHasDiagnostic(diagnostics, method); + var expected = Verify.Diagnostic().WithSpan(3, 5, 3, 89 + method.Length).WithSeverity(DiagnosticSeverity.Warning).WithArguments($"Assert.{method}()"); + await Verify.VerifyAnalyzerAsync(source, expected); } [Theory] [MemberData(nameof(Methods))] public async void DoesNotFindWarning_ForFirstBoolLiteral_ObjectOverload(string method) { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = @"class TestClass { void TestMethod() { object val = false; Xunit.Assert." + method + @"(true, val); -} }"); +} }"; - Assert.Empty(diagnostics); + await Verify.VerifyAnalyzerAsync(source); } [Theory] [MemberData(nameof(Methods))] public async void DoesNotFindWarning_ForOtherLiteral(string method) { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = @"class TestClass { void TestMethod() { int val = 1; Xunit.Assert." + method + @"(1, val); -} }"); +} }"; - Assert.Empty(diagnostics); + await Verify.VerifyAnalyzerAsync(source); } [Theory] [MemberData(nameof(Methods))] public async void DoesNotFindWarning_ForSecondBoolLiteral(string method) { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = @"class TestClass { void TestMethod() { bool val = false; Xunit.Assert." + method + @"(val, true); -} }"); +} }"; - Assert.Empty(diagnostics); + await Verify.VerifyAnalyzerAsync(source); } } } diff --git a/test/xunit.analyzers.tests/AssertEqualShouldNotBeUsedForCollectionSizeCheckTests.cs b/test/xunit.analyzers.tests/AssertEqualShouldNotBeUsedForCollectionSizeCheckTests.cs index b3e5e30d..685c82fc 100644 --- a/test/xunit.analyzers.tests/AssertEqualShouldNotBeUsedForCollectionSizeCheckTests.cs +++ b/test/xunit.analyzers.tests/AssertEqualShouldNotBeUsedForCollectionSizeCheckTests.cs @@ -1,13 +1,10 @@ -using System.Collections.Generic; using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.Diagnostics; +using Verify = Xunit.Analyzers.CSharpVerifier; namespace Xunit.Analyzers { public class AssertEqualShouldNotBeUsedForCollectionSizeCheckTests { - private readonly DiagnosticAnalyzer analyzer = new AssertEqualShouldNotBeUsedForCollectionSizeCheck(); - public static TheoryData Collections { get; } = new TheoryData { "new int[0].Length", @@ -32,59 +29,52 @@ public class AssertEqualShouldNotBeUsedForCollectionSizeCheckTests { "System.Linq.Enumerable.Empty().Count()", 354 }, }; - private static void CheckDiagnostics(IEnumerable diagnostics, string method) - { - Assert.Collection(diagnostics, d => - { - Assert.Equal($"Do not use Assert.{method}() to check for collection size.", d.GetMessage()); - Assert.Equal("xUnit2013", d.Id); - Assert.Equal(DiagnosticSeverity.Warning, d.Severity); - }); - } - [Theory] [MemberData(nameof(Collections))] public async void FindsWarningForEmptyCollectionSizeCheck(string collection) { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = @"using System.Linq; class TestClass { void TestMethod() { Xunit.Assert.Equal(0, " + collection + @"); -} }"); +} }"; - CheckDiagnostics(diagnostics, "Equal"); + var expected = Verify.Diagnostic().WithSpan(3, 5, 3, 28 + collection.Length).WithSeverity(DiagnosticSeverity.Warning).WithArguments("Assert.Equal()"); + await Verify.VerifyAnalyzerAsync(source, expected); } [Theory] [MemberData(nameof(Collections))] public async void FindsWarningForNonEmptyCollectionSizeCheck(string collection) { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = @"using System.Linq; class TestClass { void TestMethod() { Xunit.Assert.NotEqual(0, " + collection + @"); - } }"); + } }"; - CheckDiagnostics(diagnostics, "NotEqual"); + var expected = Verify.Diagnostic().WithSpan(3, 13, 3, 39 + collection.Length).WithSeverity(DiagnosticSeverity.Warning).WithArguments("Assert.NotEqual()"); + await Verify.VerifyAnalyzerAsync(source, expected); } [Theory] [MemberData(nameof(Collections))] public async void FindsWarningForSingleItemCollectionSizeCheck(string collection) { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = @"using System.Linq; class TestClass { void TestMethod() { Xunit.Assert.Equal(1, " + collection + @"); - } }"); + } }"; - CheckDiagnostics(diagnostics, "Equal"); + var expected = Verify.Diagnostic().WithSpan(3, 13, 3, 36 + collection.Length).WithSeverity(DiagnosticSeverity.Warning).WithArguments("Assert.Equal()"); + await Verify.VerifyAnalyzerAsync(source, expected); } [Fact] public async void FindsWarningForSymbolDeclaringTypeHasZeroArity_ImplementsICollectionOfT() { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, @" + var source = @" using System.Collections; using System.Collections.Generic; using Xunit; @@ -108,89 +98,90 @@ void TestMethod() { Assert.Equal(1, new IntCollection().Count); } -}"); +}"; - CheckDiagnostics(diagnostics, "Equal"); + var expected = Verify.Diagnostic().WithSpan(23, 9, 23, 51).WithSeverity(DiagnosticSeverity.Warning).WithArguments("Assert.Equal()"); + await Verify.VerifyAnalyzerAsync(source, expected); } [Theory] [MemberData(nameof(Collections))] public async void DoesNotFindWarningForNonSingleItemCollectionSizeCheck(string collection) { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = @"using System.Linq; class TestClass { void TestMethod() { Xunit.Assert.NotEqual(1, " + collection + @"); - } }"); + } }"; - Assert.Empty(diagnostics); + await Verify.VerifyAnalyzerAsync(source); } [Theory] [MemberData(nameof(CollectionsWithUnsupportedSize))] public async void DoesNotFindWarningForUnsupportedCollectionSizeCheck(string collection, int size) { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = @"using System.Linq; class TestClass { void TestMethod() { Xunit.Assert.Equal(" + size + ", " + collection + @"); - } }"); + } }"; - Assert.Empty(diagnostics); + await Verify.VerifyAnalyzerAsync(source); } [Theory] [MemberData(nameof(CollectionsWithUnsupportedSize))] public async void DoesNotFindWarningForUnsupportedNonEqualCollectionSizeCheck(string collection, int size) { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = @"using System.Linq; class TestClass { void TestMethod() { Xunit.Assert.NotEqual(" + size + ", " + collection + @"); - } }"); + } }"; - Assert.Empty(diagnostics); + await Verify.VerifyAnalyzerAsync(source); } [Fact] public async void DoesNotCrashForSymbolDeclaringTypeHasDifferentArityThanICollection_Zero() { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = @"using System.Collections.Generic; interface IIntCollection : ICollection { new int Count { get; } } class TestClass { void TestMethod() { Xunit.Assert.Equal(1, ((IIntCollection)null).Count); - } }"); + } }"; - Assert.Empty(diagnostics); + await Verify.VerifyAnalyzerAsync(source); } [Fact] public async void DoesNotCrashForSymbolDeclaringTypeHasDifferentArityThanICollection_Two() { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = @"using System.Collections.Generic; interface IDictionary2 : ICollection> { new int Count { get; } } class TestClass { void TestMethod() { Xunit.Assert.Equal(1, ((IDictionary2)null).Count); - } }"); + } }"; - Assert.Empty(diagnostics); + await Verify.VerifyAnalyzerAsync(source); } [Fact] public async void DoesNotCrash_ForNonIntArguments() { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = @"class TestClass { void TestMethod() { Xunit.Assert.Equal('b', new int[0].Length); - } }"); + } }"; - Assert.Empty(diagnostics); + await Verify.VerifyAnalyzerAsync(source); } } } diff --git a/test/xunit.analyzers.tests/AssertEqualShouldNotBeUsedForNullCheckTests.cs b/test/xunit.analyzers.tests/AssertEqualShouldNotBeUsedForNullCheckTests.cs index 256dbdf1..e905d471 100644 --- a/test/xunit.analyzers.tests/AssertEqualShouldNotBeUsedForNullCheckTests.cs +++ b/test/xunit.analyzers.tests/AssertEqualShouldNotBeUsedForNullCheckTests.cs @@ -1,12 +1,10 @@ using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.Diagnostics; +using Verify = Xunit.Analyzers.CSharpVerifier; namespace Xunit.Analyzers { public class AssertEqualShouldNotBeUsedForNullCheckTests { - readonly DiagnosticAnalyzer analyzer = new AssertEqualShouldNotBeUsedForNullCheck(); - public static TheoryData Methods = new TheoryData { "Equal", "NotEqual", "StrictEqual", "NotStrictEqual", "Same", "NotSame" }; [Theory] @@ -14,18 +12,14 @@ public class AssertEqualShouldNotBeUsedForNullCheckTests [InlineData("NotEqual")] public async void FindsWarning_ForFirstNullLiteral_StringOverload(string method) { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = @"class TestClass { void TestMethod() { string val = null; Xunit.Assert." + method + @"(null, val); -} }"); - - Assert.Collection(diagnostics, d => - { - Assert.Equal($"Do not use Assert.{method}() to check for null value.", d.GetMessage()); - Assert.Equal("xUnit2003", d.Id); - Assert.Equal(DiagnosticSeverity.Warning, d.Severity); - }); +} }"; + + var expected = Verify.Diagnostic().WithSpan(3, 5, 3, 29 + method.Length).WithSeverity(DiagnosticSeverity.Warning).WithArguments($"Assert.{method}()"); + await Verify.VerifyAnalyzerAsync(source, expected); } [Theory] @@ -33,36 +27,28 @@ public async void FindsWarning_ForFirstNullLiteral_StringOverload(string method) [InlineData("NotEqual")] public async void FindsWarning_ForFirstNullLiteral_StringOverload_WithCustomComparer(string method) { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = @"class TestClass { void TestMethod() { string val = null; Xunit.Assert." + method + @"(null, val, System.StringComparer.Ordinal); -} }"); - - Assert.Collection(diagnostics, d => - { - Assert.Equal($"Do not use Assert.{method}() to check for null value.", d.GetMessage()); - Assert.Equal("xUnit2003", d.Id); - Assert.Equal(DiagnosticSeverity.Warning, d.Severity); - }); +} }"; + + var expected = Verify.Diagnostic().WithSpan(3, 5, 3, 60 + method.Length).WithSeverity(DiagnosticSeverity.Warning).WithArguments($"Assert.{method}()"); + await Verify.VerifyAnalyzerAsync(source, expected); } [Theory] [MemberData(nameof(Methods))] public async void FindsWarning_ForFirstNullLiteral_ObjectOverload(string method) { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = @"class TestClass { void TestMethod() { object val = null; Xunit.Assert." + method + @"(null, val); -} }"); - - Assert.Collection(diagnostics, d => - { - Assert.Equal($"Do not use Assert.{method}() to check for null value.", d.GetMessage()); - Assert.Equal("xUnit2003", d.Id); - Assert.Equal(DiagnosticSeverity.Warning, d.Severity); - }); +} }"; + + var expected = Verify.Diagnostic().WithSpan(3, 5, 3, 29 + method.Length).WithSeverity(DiagnosticSeverity.Warning).WithArguments($"Assert.{method}()"); + await Verify.VerifyAnalyzerAsync(source, expected); } [Theory] @@ -70,18 +56,14 @@ public async void FindsWarning_ForFirstNullLiteral_ObjectOverload(string method) [InlineData("NotEqual")] public async void FindsWarning_ForFirstNullLiteral_ObjectOverload_WithCustomComparer(string method) { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = @"class TestClass { void TestMethod() { object val = null; Xunit.Assert." + method + @"(null, val, System.Collections.Generic.EqualityComparer.Default); -} }"); - - Assert.Collection(diagnostics, d => - { - Assert.Equal($"Do not use Assert.{method}() to check for null value.", d.GetMessage()); - Assert.Equal("xUnit2003", d.Id); - Assert.Equal(DiagnosticSeverity.Warning, d.Severity); - }); +} }"; + + var expected = Verify.Diagnostic().WithSpan(3, 5, 3, 90 + method.Length).WithSeverity(DiagnosticSeverity.Warning).WithArguments($"Assert.{method}()"); + await Verify.VerifyAnalyzerAsync(source, expected); } [Theory] @@ -91,18 +73,14 @@ public async void FindsWarning_ForFirstNullLiteral_ObjectOverload_WithCustomComp [InlineData("NotStrictEqual")] public async void FindsWarning_ForFirstNullLiteral_GenericOverload(string method) { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = @"class TestClass { void TestMethod() { TestClass val = null; Xunit.Assert." + method + @"(null, val); -} }"); - - Assert.Collection(diagnostics, d => - { - Assert.Equal($"Do not use Assert.{method}() to check for null value.", d.GetMessage()); - Assert.Equal("xUnit2003", d.Id); - Assert.Equal(DiagnosticSeverity.Warning, d.Severity); - }); +} }"; + + var expected = Verify.Diagnostic().WithSpan(3, 5, 3, 40 + method.Length).WithSeverity(DiagnosticSeverity.Warning).WithArguments($"Assert.{method}()"); + await Verify.VerifyAnalyzerAsync(source, expected); } [Theory] @@ -110,44 +88,40 @@ public async void FindsWarning_ForFirstNullLiteral_GenericOverload(string method [InlineData("NotEqual")] public async void FindsWarning_ForFirstNullLiteral_GenericOverload_WithCustomComparer(string method) { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = @"class TestClass { void TestMethod() { TestClass val = null; Xunit.Assert." + method + @"(null, val, System.Collections.Generic.EqualityComparer.Default); -} }"); - - Assert.Collection(diagnostics, d => - { - Assert.Equal($"Do not use Assert.{method}() to check for null value.", d.GetMessage()); - Assert.Equal("xUnit2003", d.Id); - Assert.Equal(DiagnosticSeverity.Warning, d.Severity); - }); +} }"; + + var expected = Verify.Diagnostic().WithSpan(3, 5, 3, 104 + method.Length).WithSeverity(DiagnosticSeverity.Warning).WithArguments($"Assert.{method}()"); + await Verify.VerifyAnalyzerAsync(source, expected); } [Theory] [MemberData(nameof(Methods))] public async void DoesNotFindWarning_ForOtherLiteral(string method) { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = @"class TestClass { void TestMethod() { int val = 1; Xunit.Assert." + method + @"(1, val); -} }"); +} }"; - Assert.Empty(diagnostics); + await Verify.VerifyAnalyzerAsync(source); } [Theory] [MemberData(nameof(Methods))] public async void DoesNotFindWarning_ForSecondNullLiteral(string method) { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = @"class TestClass { void TestMethod() { string val = null; Xunit.Assert." + method + @"(val, null); -} }"); +} }"; - Assert.Empty(diagnostics); + await Verify.VerifyAnalyzerAsync(source); } } } diff --git a/test/xunit.analyzers.tests/AssertEqualsShouldNotBeUsedTests.cs b/test/xunit.analyzers.tests/AssertEqualsShouldNotBeUsedTests.cs index 208cebed..2cccff14 100644 --- a/test/xunit.analyzers.tests/AssertEqualsShouldNotBeUsedTests.cs +++ b/test/xunit.analyzers.tests/AssertEqualsShouldNotBeUsedTests.cs @@ -1,28 +1,27 @@ using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.Diagnostics; +using Microsoft.CodeAnalysis.Testing; +using Verify = Xunit.Analyzers.CSharpVerifier; namespace Xunit.Analyzers { public class AssertEqualsShouldNotBeUsedTests { - readonly DiagnosticAnalyzer analyzer = new AssertEqualsShouldNotBeUsed(); - [Theory] - [InlineData("Equals")] - [InlineData("ReferenceEquals")] - public async void FindsHiddenDiagnosticWhenProhibitedMethodIsUsed(string method) + [InlineData("Equals", "Equal")] + [InlineData("ReferenceEquals", "Same")] + public async void FindsHiddenDiagnosticWhenProhibitedMethodIsUsed(string method, string replacement) { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, CompilationReporting.IgnoreErrors, + var source = @"class TestClass { void TestMethod() { Xunit.Assert." + method + @"(null, null); -} }"); +} }"; - Assert.Collection(diagnostics, d => + DiagnosticResult[] expected = { - Assert.Equal($"Do not use Assert.{method}().", d.GetMessage()); - Assert.Equal("xUnit2001", d.Id); - Assert.Equal(DiagnosticSeverity.Hidden, d.Severity); - }); + Verify.CompilerError("CS0619").WithSpan(2, 5, 2, 30 + method.Length).WithMessage($"'Assert.{method}(object, object)' is obsolete: 'This is an override of Object.{method}(). Call Assert.{replacement}() instead.'"), + Verify.Diagnostic().WithSpan(2, 5, 2, 30 + method.Length).WithSeverity(DiagnosticSeverity.Hidden).WithArguments($"Assert.{method}()"), + }; + await Verify.VerifyAnalyzerAsync(source, expected); } } } diff --git a/test/xunit.analyzers.tests/AssertIsTypeShouldNotBeUsedForAbstractTypeTests.cs b/test/xunit.analyzers.tests/AssertIsTypeShouldNotBeUsedForAbstractTypeTests.cs index 39b07790..1a5048ac 100755 --- a/test/xunit.analyzers.tests/AssertIsTypeShouldNotBeUsedForAbstractTypeTests.cs +++ b/test/xunit.analyzers.tests/AssertIsTypeShouldNotBeUsedForAbstractTypeTests.cs @@ -1,30 +1,17 @@ -using System.Collections.Generic; -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.Diagnostics; +using Microsoft.CodeAnalysis; +using Verify = Xunit.Analyzers.CSharpVerifier; namespace Xunit.Analyzers { public class AssertIsTypeShouldNotBeUsedForAbstractTypeTests { - private static DiagnosticAnalyzer Analyzer { get; } = new AssertIsTypeShouldNotBeUsedForAbstractType(); - public static TheoryData Methods { get; } = new TheoryData { "IsType", "IsNotType" }; - private static void AssertHasDiagnostic(IEnumerable diagnostics, string typeKind, string type) - { - Assert.Collection(diagnostics, d => - { - Assert.Equal($"Do not compare an object's exact type to the {typeKind} '{type}'.", d.GetMessage()); - Assert.Equal("xUnit2018", d.Id); - Assert.Equal(DiagnosticSeverity.Warning, d.Severity); - }); - } - [Theory] [MemberData(nameof(Methods))] public async void FindsError_Interface(string method) { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(Analyzer, @" + var source = @" using System; using Xunit; @@ -34,16 +21,17 @@ void TestMethod() { Assert." + method + @"(new object()); } -}"); +}"; - AssertHasDiagnostic(diagnostics, "interface", "System.IDisposable"); + var expected = Verify.Diagnostic().WithSpan(9, 9, 9, 43 + method.Length).WithSeverity(DiagnosticSeverity.Warning).WithArguments("interface", "System.IDisposable"); + await Verify.VerifyAnalyzerAsync(source, expected); } [Theory] [MemberData(nameof(Methods))] public async void FindsError_AbstractClass(string method) { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(Analyzer, @" + var source = @" using System.IO; using Xunit; @@ -53,16 +41,17 @@ void TestMethod() { Assert." + method + @"(new object()); } -}"); +}"; - AssertHasDiagnostic(diagnostics, "abstract class", "System.IO.Stream"); + var expected = Verify.Diagnostic().WithSpan(9, 9, 9, 38 + method.Length).WithSeverity(DiagnosticSeverity.Warning).WithArguments("abstract class", "System.IO.Stream"); + await Verify.VerifyAnalyzerAsync(source, expected); } [Theory] [MemberData(nameof(Methods))] public async void FindsError_UsingStatic(string method) { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(Analyzer, @" + var source = @" using System; using static Xunit.Assert; @@ -72,16 +61,17 @@ void TestMethod() { " + method + @"(new object()); } -}"); +}"; - AssertHasDiagnostic(diagnostics, "interface", "System.IDisposable"); + var expected = Verify.Diagnostic().WithSpan(9, 9, 9, 36 + method.Length).WithSeverity(DiagnosticSeverity.Warning).WithArguments("interface", "System.IDisposable"); + await Verify.VerifyAnalyzerAsync(source, expected); } [Theory] [MemberData(nameof(Methods))] public async void DoesNotFindError_NonAbstractClass(string method) { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(Analyzer, @" + var source = @" using Xunit; class TestClass @@ -90,16 +80,16 @@ void TestMethod() { Assert." + method + @"(new object()); } -}"); +}"; - Assert.Empty(diagnostics); + await Verify.VerifyAnalyzerAsync(source); } [Theory] [InlineData("IsAssignableFrom")] public async void DoesNotFindError_OtherMethods(string method) { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(Analyzer, @" + var source = @" using System; using Xunit; @@ -109,9 +99,9 @@ void TestMethod() { Assert." + method + @"(new object()); } -}"); +}"; - Assert.Empty(diagnostics); + await Verify.VerifyAnalyzerAsync(source); } } } diff --git a/test/xunit.analyzers.tests/AssertIsTypeShouldUseGenericOverloadTests.cs b/test/xunit.analyzers.tests/AssertIsTypeShouldUseGenericOverloadTests.cs index 76574930..a3846057 100644 --- a/test/xunit.analyzers.tests/AssertIsTypeShouldUseGenericOverloadTests.cs +++ b/test/xunit.analyzers.tests/AssertIsTypeShouldUseGenericOverloadTests.cs @@ -1,47 +1,35 @@ -using System.Collections.Generic; -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.Diagnostics; +using Microsoft.CodeAnalysis; +using Verify = Xunit.Analyzers.CSharpVerifier; namespace Xunit.Analyzers { public class AssertIsTypeShouldUseGenericOverloadTests { - readonly DiagnosticAnalyzer analyzer = new AssertIsTypeShouldUseGenericOverloadType(); - public static TheoryData Methods = new TheoryData { "IsType", "IsNotType", "IsAssignableFrom" }; - private static void AssertHasDiagnostic(IEnumerable diagnostics, string type) - { - Assert.Collection(diagnostics, d => - { - Assert.Equal($"Do not use typeof({type}) expression to check the type.", d.GetMessage()); - Assert.Equal("xUnit2007", d.Id); - Assert.Equal(DiagnosticSeverity.Warning, d.Severity); - }); - } - [Theory] [MemberData(nameof(Methods))] public async void FindsWarning_ForNonGenericCall(string method) { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = @"class TestClass { void TestMethod() { Xunit.Assert." + method + @"(typeof(int), 1); -} }"); +} }"; - AssertHasDiagnostic(diagnostics, "int"); + var expected = Verify.Diagnostic().WithSpan(2, 5, 2, 34 + method.Length).WithSeverity(DiagnosticSeverity.Warning).WithArguments("int"); + await Verify.VerifyAnalyzerAsync(source, expected); } [Theory] [MemberData(nameof(Methods))] public async void DoesNotFindWarning_ForGenericCall(string method) { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = @"class TestClass { void TestMethod() { Xunit.Assert." + method + @"(1); -} }"); +} }"; - Assert.Empty(diagnostics); + await Verify.VerifyAnalyzerAsync(source); } } } diff --git a/test/xunit.analyzers.tests/AssertNullShouldNotBeCalledOnValueTypesFixerTests.cs b/test/xunit.analyzers.tests/AssertNullShouldNotBeCalledOnValueTypesFixerTests.cs index 934ed67b..c4857ac4 100644 --- a/test/xunit.analyzers.tests/AssertNullShouldNotBeCalledOnValueTypesFixerTests.cs +++ b/test/xunit.analyzers.tests/AssertNullShouldNotBeCalledOnValueTypesFixerTests.cs @@ -1,14 +1,9 @@ -using System; -using Microsoft.CodeAnalysis.CodeFixes; -using Microsoft.CodeAnalysis.Diagnostics; +using Verify = Xunit.Analyzers.CSharpVerifier; namespace Xunit.Analyzers { public class AssertNullShouldNotBeCalledOnValueTypesFixerTests { - readonly DiagnosticAnalyzer analyzer = new AssertNullShouldNotBeCalledOnValueTypes(); - readonly CodeFixProvider fixer = new AssertNullShouldNotBeCalledOnValueTypesFixer(); - [Fact] public async void ForValueTypeNullAssert_RemovesAssertion() { @@ -22,7 +17,7 @@ public void TestMethod() { int i = 1; - Assert.NotNull(i); + [|Assert.NotNull(i)|]; } }"; @@ -37,9 +32,8 @@ public void TestMethod() int i = 1; } }"; - var actual = await CodeAnalyzerHelper.GetFixedCodeAsync(analyzer, fixer, original); - Assert.Equal(expected, actual); + await Verify.VerifyCodeFixAsync(original, expected); } [Fact] @@ -61,7 +55,7 @@ public void Test1() // I am a comment which gets deleted by the quick fix // Assert - Assert.NotNull(i); + [|Assert.NotNull(i)|]; Assert.Null(null); } } @@ -85,13 +79,8 @@ public void Test1() } } }"; - var actual = await CodeAnalyzerHelper.GetFixedCodeAsync(analyzer, fixer, original); - - // Code fixer always inserts \r\n even on Linux, so fix up the actual result - if (Environment.NewLine != "\r\n") - actual = actual.Replace("\r\n", Environment.NewLine); - Assert.Equal(expected, actual); + await Verify.VerifyCodeFixAsync(original, expected); } } } diff --git a/test/xunit.analyzers.tests/AssertNullShouldNotBeCalledOnValueTypesTests.cs b/test/xunit.analyzers.tests/AssertNullShouldNotBeCalledOnValueTypesTests.cs index 1180be42..5eac4a8b 100644 --- a/test/xunit.analyzers.tests/AssertNullShouldNotBeCalledOnValueTypesTests.cs +++ b/test/xunit.analyzers.tests/AssertNullShouldNotBeCalledOnValueTypesTests.cs @@ -1,63 +1,57 @@ using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.Diagnostics; +using Verify = Xunit.Analyzers.CSharpVerifier; namespace Xunit.Analyzers { public class AssertNullShouldNotBeCalledOnValueTypesTests { - readonly DiagnosticAnalyzer analyzer = new AssertNullShouldNotBeCalledOnValueTypes(); - public static TheoryData Methods = new TheoryData { "Null", "NotNull" }; [Theory] [MemberData(nameof(Methods))] public async void FindsWarning_ForValueType(string method) { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = @"class TestClass { void TestMethod() { int val = 1; Xunit.Assert." + method + @"(val); -} }"); +} }"; - Assert.Collection(diagnostics, d => - { - Assert.Equal($"Do not use Assert.{method}() on value type 'int'.", d.GetMessage()); - Assert.Equal("xUnit2002", d.Id); - Assert.Equal(DiagnosticSeverity.Warning, d.Severity); - }); + var expected = Verify.Diagnostic().WithSpan(3, 5, 3, 23 + method.Length).WithSeverity(DiagnosticSeverity.Warning).WithArguments($"Assert.{method}()", "int"); + await Verify.VerifyAnalyzerAsync(source, expected); } [Theory] [MemberData(nameof(Methods))] public async void DoesNotFindWarning_ForNullableValueType(string method) { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = @"class TestClass { void TestMethod() { int? val = 1; Xunit.Assert." + method + @"(val); -} }"); +} }"; - Assert.Empty(diagnostics); + await Verify.VerifyAnalyzerAsync(source); } [Theory] [MemberData(nameof(Methods))] public async void DoesNotFindWarning_ForNullableReferenceType(string method) { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = @"class TestClass { void TestMethod() { string val = null; Xunit.Assert." + method + @"(val); -} }"); +} }"; - Assert.Empty(diagnostics); + await Verify.VerifyAnalyzerAsync(source); } [Theory] [MemberData(nameof(Methods))] public async void DoesNotFindWarning_ForClassConstrainedGenericTypes(string method) { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = @" class Class where T : class { @@ -65,15 +59,15 @@ public void Method(T arg) { Xunit.Assert." + method + @"(arg); } -}"); - Assert.Empty(diagnostics); +}"; + await Verify.VerifyAnalyzerAsync(source); } - + [Theory] [MemberData(nameof(Methods))] public async void DoesNotFindWarning_ForInterfaceConstrainedGenericTypes(string method) { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = @" interface IDo {} @@ -86,15 +80,15 @@ public void Method(System.Collections.Generic.IEnumerable collection) Xunit.Assert." + method + @"(item); } } -}"); - Assert.Empty(diagnostics); +}"; + await Verify.VerifyAnalyzerAsync(source); } - + [Theory] [MemberData(nameof(Methods))] public async void DoesNotFindWarning_ForUnconstrainedGenericTypes(string method) { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = @" class Class { @@ -105,8 +99,8 @@ public void Method(System.Collections.Generic.IEnumerable collection) Xunit.Assert." + method + @"(item); } } -}"); - Assert.Empty(diagnostics); +}"; + await Verify.VerifyAnalyzerAsync(source); } } } diff --git a/test/xunit.analyzers.tests/AssertRegexMatchShouldNotUseBoolLiteralCheckTests.cs b/test/xunit.analyzers.tests/AssertRegexMatchShouldNotUseBoolLiteralCheckTests.cs index 7bbbd745..165248f0 100644 --- a/test/xunit.analyzers.tests/AssertRegexMatchShouldNotUseBoolLiteralCheckTests.cs +++ b/test/xunit.analyzers.tests/AssertRegexMatchShouldNotUseBoolLiteralCheckTests.cs @@ -1,60 +1,50 @@ -using System.Collections.Generic; -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.Diagnostics; +using Microsoft.CodeAnalysis; +using Verify = Xunit.Analyzers.CSharpVerifier; namespace Xunit.Analyzers { public class AssertRegexMatchShouldNotUseBoolLiteralCheckTests { - readonly DiagnosticAnalyzer analyzer = new AssertRegexMatchShouldNotUseBoolLiteralCheck(); - public static TheoryData Methods = new TheoryData { "True", "False" }; - private static void AssertHasDiagnostic(IEnumerable diagnostics, string method) - { - Assert.Collection(diagnostics, d => - { - Assert.Equal($"Do not use Assert.{method}() to match on regular expressions.", d.GetMessage()); - Assert.Equal("xUnit2008", d.Id); - Assert.Equal(DiagnosticSeverity.Warning, d.Severity); - }); - } - [Theory] [MemberData(nameof(Methods))] public async void FindsWarning_ForStaticRegexIsMatch(string method) { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = @"class TestClass { void TestMethod() { Xunit.Assert." + method + @"(System.Text.RegularExpressions.Regex.IsMatch(""abc"", ""\\w*"")); -} }"); +} }"; - AssertHasDiagnostic(diagnostics, method); + var expected = Verify.Diagnostic().WithSpan(2, 5, 2, 79 + method.Length).WithSeverity(DiagnosticSeverity.Warning).WithArguments($"Assert.{method}()"); + await Verify.VerifyAnalyzerAsync(source, expected); } [Theory] [MemberData(nameof(Methods))] public async void FindsWarning_ForInstaceRegexIsMatchWithInlineConstructedRegex(string method) { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = @"class TestClass { void TestMethod() { Xunit.Assert." + method + @"(new System.Text.RegularExpressions.Regex(""abc"").IsMatch(""\\w*"")); -} }"); +} }"; - AssertHasDiagnostic(diagnostics, method); + var expected = Verify.Diagnostic().WithSpan(2, 5, 2, 83 + method.Length).WithSeverity(DiagnosticSeverity.Warning).WithArguments($"Assert.{method}()"); + await Verify.VerifyAnalyzerAsync(source, expected); } [Theory] [MemberData(nameof(Methods))] public async void FindsWarning_ForInstaceRegexIsMatchWithConstructedRegexVariable(string method) { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = @"class TestClass { void TestMethod() { var regex = new System.Text.RegularExpressions.Regex(""abc""); Xunit.Assert." + method + @"(regex.IsMatch(""\\w*"")); -} }"); +} }"; - AssertHasDiagnostic(diagnostics, method); + var expected = Verify.Diagnostic().WithSpan(3, 5, 3, 41 + method.Length).WithSeverity(DiagnosticSeverity.Warning).WithArguments($"Assert.{method}()"); + await Verify.VerifyAnalyzerAsync(source, expected); } } } diff --git a/test/xunit.analyzers.tests/AssertSameShouldNotBeCalledOnValueTypesTests.cs b/test/xunit.analyzers.tests/AssertSameShouldNotBeCalledOnValueTypesTests.cs index 7e147a00..e1a66490 100644 --- a/test/xunit.analyzers.tests/AssertSameShouldNotBeCalledOnValueTypesTests.cs +++ b/test/xunit.analyzers.tests/AssertSameShouldNotBeCalledOnValueTypesTests.cs @@ -1,29 +1,23 @@ using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.Diagnostics; +using Verify = Xunit.Analyzers.CSharpVerifier; namespace Xunit.Analyzers { public class AssertSameShouldNotBeCalledOnValueTypesTests { - readonly DiagnosticAnalyzer analyzer = new AssertSameShouldNotBeCalledOnValueTypes(); - [Theory] [InlineData("Same")] [InlineData("NotSame")] public async void FindsWarningForTwoValueParameters(string method) { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, CompilationReporting.IgnoreErrors, + var source = @"class TestClass { void TestMethod() { int a = 0; Xunit.Assert." + method + @"(0, a); -} }"); +} }"; - Assert.Collection(diagnostics, d => - { - Assert.Equal($"Do not use Assert.{method}() on value type 'int'.", d.GetMessage()); - Assert.Equal("xUnit2005", d.Id); - Assert.Equal(DiagnosticSeverity.Warning, d.Severity); - }); + var expected = Verify.Diagnostic().WithSpan(3, 5, 3, 24 + method.Length).WithSeverity(DiagnosticSeverity.Warning).WithArguments($"Assert.{method}()", "int"); + await Verify.VerifyAnalyzerAsync(source, expected); } [Theory] @@ -31,18 +25,14 @@ public async void FindsWarningForTwoValueParameters(string method) [InlineData("NotSame")] public async void FindsWarningForFirstValueParameters(string method) { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, CompilationReporting.IgnoreErrors, + var source = @"class TestClass { void TestMethod() { object a = 0; Xunit.Assert." + method + @"(0, a); -} }"); +} }"; - Assert.Collection(diagnostics, d => - { - Assert.Equal($"Do not use Assert.{method}() on value type 'int'.", d.GetMessage()); - Assert.Equal("xUnit2005", d.Id); - Assert.Equal(DiagnosticSeverity.Warning, d.Severity); - }); + var expected = Verify.Diagnostic().WithSpan(3, 5, 3, 24 + method.Length).WithSeverity(DiagnosticSeverity.Warning).WithArguments($"Assert.{method}()", "int"); + await Verify.VerifyAnalyzerAsync(source, expected); } [Theory] @@ -50,18 +40,14 @@ public async void FindsWarningForFirstValueParameters(string method) [InlineData("NotSame")] public async void FindsWarningForSecondValueParameters(string method) { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, CompilationReporting.IgnoreErrors, + var source = @"class TestClass { void TestMethod() { object a = 0; Xunit.Assert." + method + @"(a, 0); -} }"); +} }"; - Assert.Collection(diagnostics, d => - { - Assert.Equal($"Do not use Assert.{method}() on value type 'int'.", d.GetMessage()); - Assert.Equal("xUnit2005", d.Id); - Assert.Equal(DiagnosticSeverity.Warning, d.Severity); - }); + var expected = Verify.Diagnostic().WithSpan(3, 5, 3, 24 + method.Length).WithSeverity(DiagnosticSeverity.Warning).WithArguments($"Assert.{method}()", "int"); + await Verify.VerifyAnalyzerAsync(source, expected); } } } diff --git a/test/xunit.analyzers.tests/AssertStringEqualityCheckShouldNotUseBoolCheckTest.cs b/test/xunit.analyzers.tests/AssertStringEqualityCheckShouldNotUseBoolCheckTest.cs index d771f353..f79b2951 100644 --- a/test/xunit.analyzers.tests/AssertStringEqualityCheckShouldNotUseBoolCheckTest.cs +++ b/test/xunit.analyzers.tests/AssertStringEqualityCheckShouldNotUseBoolCheckTest.cs @@ -1,14 +1,11 @@ using System; -using System.Collections.Generic; using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.Diagnostics; +using Verify = Xunit.Analyzers.CSharpVerifier; namespace Xunit.Analyzers { public class AssertStringEqualityCheckShouldNotUseBoolCheckTest { - readonly DiagnosticAnalyzer analyzer = new AssertStringEqualityCheckShouldNotUseBoolCheck(); - public static TheoryData AssertMethods = new TheoryData { "True", "False" }; public static TheoryData SupportedStringComparisons = new TheoryData @@ -35,110 +32,104 @@ public class AssertStringEqualityCheckShouldNotUseBoolCheckTest StringComparison.InvariantCultureIgnoreCase }; - private static void AssertHasDiagnostic(IEnumerable diagnostics, string method) - { - Assert.Collection(diagnostics, d => - { - Assert.Equal($"Do not use Assert.{method}() to check for string equality.", d.GetMessage(), ignoreCase: true); - Assert.Equal("xUnit2010", d.Id); - Assert.Equal(DiagnosticSeverity.Warning, d.Severity); - }); - } - [Theory] [MemberData(nameof(AssertMethods))] public async void FindsWarning_ForInstanceEqualsCheck(string method) { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = @"class TestClass { void TestMethod() { Xunit.Assert." + method + @"(""abc"".Equals(""a"")); -} }"); +} }"; - AssertHasDiagnostic(diagnostics, method); + var expected = Verify.Diagnostic().WithSpan(2, 5, 2, 37 + method.Length).WithSeverity(DiagnosticSeverity.Warning).WithArguments($"Assert.{method}()"); + await Verify.VerifyAnalyzerAsync(source, expected); } [Theory] [MemberData(nameof(SupportedStringComparisons))] public async void FindsWarning_ForTrueInstanceEqualsCheck_WithSupportedStringComparison(StringComparison comparison) { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = @"class TestClass { void TestMethod() { Xunit.Assert.True(""abc"".Equals(""a"", System.StringComparison." + comparison + @")); -} }"); +} }"; - AssertHasDiagnostic(diagnostics, "True"); + var expected = Verify.Diagnostic().WithSpan(2, 5, 2, 67 + comparison.ToString().Length).WithSeverity(DiagnosticSeverity.Warning).WithArguments($"Assert.True()"); + await Verify.VerifyAnalyzerAsync(source, expected); } [Theory] [MemberData(nameof(UnsupportedStringComparisons))] public async void DoesNotFindWarning_ForTrueInstanceEqualsCheck_WithUnsupportedStringComparison(StringComparison comparison) { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = @"class TestClass { void TestMethod() { Xunit.Assert.True(""abc"".Equals(""a"", System.StringComparison." + comparison + @")); -} }"); +} }"; - Assert.Empty(diagnostics); + await Verify.VerifyAnalyzerAsync(source); } [Theory] [MemberData(nameof(AllStringComparisons))] public async void DoesNotFindWarning_ForFalseInstanceEqualsCheck_WithStringComparison(StringComparison comparison) { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = @"class TestClass { void TestMethod() { Xunit.Assert.False(""abc"".Equals(""a"", System.StringComparison." + comparison + @")); -} }"); +} }"; - Assert.Empty(diagnostics); + await Verify.VerifyAnalyzerAsync(source); } [Theory] [MemberData(nameof(AssertMethods))] public async void FindsWarning_ForStaticEqualsCheck(string method) { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = @"class TestClass { void TestMethod() { Xunit.Assert." + method + @"(System.String.Equals(""abc"", ""a"")); -} }"); +} }"; - AssertHasDiagnostic(diagnostics, method); + var expected = Verify.Diagnostic().WithSpan(2, 5, 2, 52 + method.Length).WithSeverity(DiagnosticSeverity.Warning).WithArguments($"Assert.{method}()"); + await Verify.VerifyAnalyzerAsync(source, expected); } [Theory] [MemberData(nameof(SupportedStringComparisons))] public async void FindsWarning_ForTrueStaticEqualsCheck_WithSupportedStringComparison(StringComparison comparison) { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = @"class TestClass { void TestMethod() { Xunit.Assert.True(System.String.Equals(""abc"", ""a"", System.StringComparison." + comparison + @")); -} }"); +} }"; - AssertHasDiagnostic(diagnostics, "True"); + var expected = Verify.Diagnostic().WithSpan(2, 5, 2, 82 + comparison.ToString().Length).WithSeverity(DiagnosticSeverity.Warning).WithArguments($"Assert.True()"); + await Verify.VerifyAnalyzerAsync(source, expected); } [Theory] [MemberData(nameof(UnsupportedStringComparisons))] public async void DoesNotFindWarning_ForTrueStaticEqualsCheck_WithUnsupportedStringComparison(StringComparison comparison) { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = @"class TestClass { void TestMethod() { Xunit.Assert.True(System.String.Equals(""abc"", ""a"", System.StringComparison." + comparison + @")); -} }"); +} }"; - Assert.Empty(diagnostics); + await Verify.VerifyAnalyzerAsync(source); } [Theory] [MemberData(nameof(AllStringComparisons))] public async void DoesNotFindWarning_ForFalseStaticEqualsCheck_WithStringComparison(StringComparison comparison) { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = @"class TestClass { void TestMethod() { Xunit.Assert.False(System.String.Equals(""abc"", ""a"", System.StringComparison." + comparison + @")); -} }"); +} }"; - Assert.Empty(diagnostics); + await Verify.VerifyAnalyzerAsync(source); } } } diff --git a/test/xunit.analyzers.tests/AssertSubstringCheckShouldNotUseBoolCheckTests.cs b/test/xunit.analyzers.tests/AssertSubstringCheckShouldNotUseBoolCheckTests.cs index d86cc888..4439753b 100644 --- a/test/xunit.analyzers.tests/AssertSubstringCheckShouldNotUseBoolCheckTests.cs +++ b/test/xunit.analyzers.tests/AssertSubstringCheckShouldNotUseBoolCheckTests.cs @@ -1,231 +1,223 @@ -using System.Collections.Generic; -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.Diagnostics; +using Microsoft.CodeAnalysis; +using Verify = Xunit.Analyzers.CSharpVerifier; namespace Xunit.Analyzers { public class AssertSubstringCheckShouldNotUseBoolCheckTests { - readonly DiagnosticAnalyzer analyzer = new AssertSubstringCheckShouldNotUseBoolCheck(); - public static TheoryData BooleanMethods = new TheoryData { "True", "False" }; - private static void AssertHasDiagnostic(IEnumerable diagnostics, string method) - { - Assert.Collection(diagnostics, d => - { - Assert.Equal($"Do not use Assert.{method}() to check for substrings.", d.GetMessage()); - Assert.Equal("xUnit2009", d.Id); - Assert.Equal(DiagnosticSeverity.Warning, d.Severity); - }); - } - [Theory] [MemberData(nameof(BooleanMethods))] public async void FindsWarning_ForBooleanContainsCheck(string method) { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = @"class TestClass { void TestMethod() { Xunit.Assert." + method + @"(""abc"".Contains(""a"")); -} }"); +} }"; - AssertHasDiagnostic(diagnostics, method); + var expected = Verify.Diagnostic().WithSpan(2, 5, 2, 39 + method.Length).WithSeverity(DiagnosticSeverity.Warning).WithArguments($"Assert.{method}()"); + await Verify.VerifyAnalyzerAsync(source, expected); } [Theory] [MemberData(nameof(BooleanMethods))] public async void DoesNotFindWarning_ForBooleanContainsCheck_WithUserMessage(string method) { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = @"class TestClass { void TestMethod() { Xunit.Assert." + method + @"(""abc"".Contains(""a""), ""message""); -} }"); +} }"; - Assert.Empty(diagnostics); + await Verify.VerifyAnalyzerAsync(source); } [Fact] public async void FindsWarning_ForBooleanTrueStartsWithCheck() { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = @"class TestClass { void TestMethod() { Xunit.Assert.True(""abc"".StartsWith(""a"")); -} }"); +} }"; - AssertHasDiagnostic(diagnostics, "True"); + var expected = Verify.Diagnostic().WithSpan(2, 5, 2, 45).WithSeverity(DiagnosticSeverity.Warning).WithArguments("Assert.True()"); + await Verify.VerifyAnalyzerAsync(source, expected); } [Fact] public async void FindsWarning_ForBooleanTrueStartsWithCheck_WithStringComparison() { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = @"class TestClass { void TestMethod() { Xunit.Assert.True(""abc"".StartsWith(""a"", System.StringComparison.CurrentCulture)); -} }"); +} }"; - AssertHasDiagnostic(diagnostics, "True"); + var expected = Verify.Diagnostic().WithSpan(2, 5, 2, 85).WithSeverity(DiagnosticSeverity.Warning).WithArguments("Assert.True()"); + await Verify.VerifyAnalyzerAsync(source, expected); } [Fact] public async void DoesNotFindWarning_ForBooleanFalseStartsWithCheck() { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = @"class TestClass { void TestMethod() { Xunit.Assert.False(""abc"".StartsWith(""a"")); -} }"); +} }"; - Assert.Empty(diagnostics); + await Verify.VerifyAnalyzerAsync(source); } [Fact] public async void DoesNotFindWarning_ForBooleanFalseStartsWithCheck_WithStringComparison() { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = @"class TestClass { void TestMethod() { Xunit.Assert.False(""abc"".StartsWith(""a"", System.StringComparison.CurrentCulture)); -} }"); +} }"; - Assert.Empty(diagnostics); + await Verify.VerifyAnalyzerAsync(source); } [Theory] [MemberData(nameof(BooleanMethods))] public async void DoesNotFindWarning_ForBooleanStartsWithCheck_WithUserMessage(string method) { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = @"class TestClass { void TestMethod() { Xunit.Assert." + method + @"(""abc"".StartsWith(""a""), ""message""); -} }"); +} }"; - Assert.Empty(diagnostics); + await Verify.VerifyAnalyzerAsync(source); } [Theory] [MemberData(nameof(BooleanMethods))] public async void DoesNotFindWarning_ForBooleanStartsWithCheck_WithStringComparison_AndUserMessage(string method) { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = @"class TestClass { void TestMethod() { Xunit.Assert." + method + @"(""abc"".StartsWith(""a"", System.StringComparison.CurrentCulture), ""message""); -} }"); +} }"; - Assert.Empty(diagnostics); + await Verify.VerifyAnalyzerAsync(source); } [Theory] [MemberData(nameof(BooleanMethods))] public async void DoesNotFindWarning_ForBooleanStartsWithCheck_WithBoolAndCulture(string method) { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = @"class TestClass { void TestMethod() { Xunit.Assert." + method + @"(""abc"".StartsWith(""a"", true, System.Globalization.CultureInfo.CurrentCulture)); -} }"); +} }"; - Assert.Empty(diagnostics); + await Verify.VerifyAnalyzerAsync(source); } [Theory] [MemberData(nameof(BooleanMethods))] public async void DoesNotFindWarning_ForBooleanStartsWithCheck_WithBoolAndCulture_AndUserMessage(string method) { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = @"class TestClass { void TestMethod() { Xunit.Assert." + method + @"(""abc"".StartsWith(""a"", true, System.Globalization.CultureInfo.CurrentCulture), ""message""); -} }"); +} }"; - Assert.Empty(diagnostics); + await Verify.VerifyAnalyzerAsync(source); } [Fact] public async void FindsWarning_ForBooleanTrueEndsWithCheck() { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = @"class TestClass { void TestMethod() { Xunit.Assert.True(""abc"".EndsWith(""a"")); -} }"); +} }"; - AssertHasDiagnostic(diagnostics, "True"); + var expected = Verify.Diagnostic().WithSpan(2, 5, 2, 43).WithSeverity(DiagnosticSeverity.Warning).WithArguments("Assert.True()"); + await Verify.VerifyAnalyzerAsync(source, expected); } [Fact] public async void FindsWarning_ForBooleanTrueEndsWithCheck_WithStringComparison() { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = @"class TestClass { void TestMethod() { Xunit.Assert.True(""abc"".EndsWith(""a"", System.StringComparison.CurrentCulture)); -} }"); +} }"; - AssertHasDiagnostic(diagnostics, "True"); + var expected = Verify.Diagnostic().WithSpan(2, 5, 2, 83).WithSeverity(DiagnosticSeverity.Warning).WithArguments("Assert.True()"); + await Verify.VerifyAnalyzerAsync(source, expected); } [Fact] public async void DoesNotFindWarning_ForBooleanFalseEndsWithCheck() { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = @"class TestClass { void TestMethod() { Xunit.Assert.False(""abc"".EndsWith(""a"")); -} }"); +} }"; - Assert.Empty(diagnostics); + await Verify.VerifyAnalyzerAsync(source); } [Fact] public async void DoesNotFindWarning_ForBooleanFalseEndsWithCheck_WithStringComparison() { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = @"class TestClass { void TestMethod() { Xunit.Assert.False(""abc"".EndsWith(""a"", System.StringComparison.CurrentCulture)); -} }"); +} }"; - Assert.Empty(diagnostics); + await Verify.VerifyAnalyzerAsync(source); } [Theory] [MemberData(nameof(BooleanMethods))] public async void DoesNotFindWarning_ForBooleanEndsWithCheck_WithUserMessage(string method) { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = @"class TestClass { void TestMethod() { Xunit.Assert." + method + @"(""abc"".EndsWith(""a""), ""message""); -} }"); +} }"; - Assert.Empty(diagnostics); + await Verify.VerifyAnalyzerAsync(source); } [Theory] [MemberData(nameof(BooleanMethods))] public async void DoesNotFindWarning_ForBooleanEndsWithCheck_WithStringComparison_AndUserMessage(string method) { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = @"class TestClass { void TestMethod() { Xunit.Assert." + method + @"(""abc"".EndsWith(""a"", System.StringComparison.CurrentCulture), ""message""); -} }"); +} }"; - Assert.Empty(diagnostics); + await Verify.VerifyAnalyzerAsync(source); } [Theory] [MemberData(nameof(BooleanMethods))] public async void DoesNotFindWarning_ForBooleanEndsWithCheck_WithBoolAndCulture(string method) { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = @"class TestClass { void TestMethod() { Xunit.Assert." + method + @"(""abc"".EndsWith(""a"", true, System.Globalization.CultureInfo.CurrentCulture)); -} }"); +} }"; - Assert.Empty(diagnostics); + await Verify.VerifyAnalyzerAsync(source); } [Theory] [MemberData(nameof(BooleanMethods))] public async void DoesNotFindWarning_ForBooleanEndsWithCheck_WithBoolAndCulture_AndUserMessage(string method) { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = @"class TestClass { void TestMethod() { Xunit.Assert." + method + @"(""abc"".EndsWith(""a"", true, System.Globalization.CultureInfo.CurrentCulture), ""message""); -} }"); +} }"; - Assert.Empty(diagnostics); + await Verify.VerifyAnalyzerAsync(source); } } } diff --git a/test/xunit.analyzers.tests/AssertThrowsShouldNotBeUsedForAsyncThrowsCheckTests.cs b/test/xunit.analyzers.tests/AssertThrowsShouldNotBeUsedForAsyncThrowsCheckTests.cs index d3eae4c8..13a1bb28 100644 --- a/test/xunit.analyzers.tests/AssertThrowsShouldNotBeUsedForAsyncThrowsCheckTests.cs +++ b/test/xunit.analyzers.tests/AssertThrowsShouldNotBeUsedForAsyncThrowsCheckTests.cs @@ -1,17 +1,16 @@ using System.Threading.Tasks; using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.Diagnostics; +using Microsoft.CodeAnalysis.Testing; +using Verify = Xunit.Analyzers.CSharpVerifier; namespace Xunit.Analyzers { public class AssertThrowsShouldNotBeUsedForAsyncThrowsCheckTests { - private readonly DiagnosticAnalyzer analyzer = new AssertThrowsShouldNotBeUsedForAsyncThrowsCheck(); - [Fact] public async Task FindsWarning_ForThrowsCheck_WithExceptionParameter_OnThrowingMethod() { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = @"class TestClass { System.Threading.Tasks.Task ThrowingMethod() { throw new System.NotImplementedException(); @@ -19,52 +18,40 @@ System.Threading.Tasks.Task ThrowingMethod() { void TestMethod() { Xunit.Assert.Throws(typeof(System.NotImplementedException), ThrowingMethod); -} }"); +} }"; - Assert.Collection(diagnostics, d => - { - Assert.Equal("Do not use Assert.Throws() to check for asynchronously thrown exceptions.", d.GetMessage()); - Assert.Equal("xUnit2014", d.Id); - Assert.Equal(DiagnosticSeverity.Error, d.Severity); - }); + var expected = Verify.Diagnostic("xUnit2014").WithSpan(7, 5, 7, 80).WithSeverity(DiagnosticSeverity.Error).WithArguments("Assert.Throws()"); + await Verify.VerifyAnalyzerAsync(source, expected); } [Fact] public async Task FindsWarning_ForThrowsCheck_WithExceptionParameter_OnThrowingLambda() { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = @"class TestClass { void TestMethod() { Xunit.Assert.Throws(typeof(System.NotImplementedException), () => System.Threading.Tasks.Task.Delay(0)); -} }"); +} }"; - Assert.Collection(diagnostics, d => - { - Assert.Equal("Do not use Assert.Throws() to check for asynchronously thrown exceptions.", d.GetMessage()); - Assert.Equal("xUnit2014", d.Id); - Assert.Equal(DiagnosticSeverity.Error, d.Severity); - }); + var expected = Verify.Diagnostic("xUnit2014").WithSpan(2, 5, 2, 108).WithSeverity(DiagnosticSeverity.Error).WithArguments("Assert.Throws()"); + await Verify.VerifyAnalyzerAsync(source, expected); } [Fact] public async Task FindsWarning_ForThrowsCheck_WithExceptionParameter_OnAsyncThrowingLambda() { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = @"class TestClass { void TestMethod() { Xunit.Assert.Throws(typeof(System.NotImplementedException), async () => await System.Threading.Tasks.Task.Delay(0)); -} }"); +} }"; - Assert.Collection(diagnostics, d => - { - Assert.Equal("Do not use Assert.Throws() to check for asynchronously thrown exceptions.", d.GetMessage()); - Assert.Equal("xUnit2014", d.Id); - Assert.Equal(DiagnosticSeverity.Error, d.Severity); - }); + var expected = Verify.Diagnostic("xUnit2014").WithSpan(2, 5, 2, 120).WithSeverity(DiagnosticSeverity.Error).WithArguments("Assert.Throws()"); + await Verify.VerifyAnalyzerAsync(source, expected); } [Fact] public async Task FindsWarning_ForThrowsCheck_WithExceptionTypeArgument_OnThrowingMethod() { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, CompilationReporting.IgnoreErrors, + var source = @"class TestClass { System.Threading.Tasks.Task ThrowingMethod() { throw new System.NotImplementedException(); @@ -72,52 +59,52 @@ System.Threading.Tasks.Task ThrowingMethod() { void TestMethod() { Xunit.Assert.Throws(ThrowingMethod); -} }"); +} }"; - Assert.Collection(diagnostics, d => + DiagnosticResult[] expected = { - Assert.Equal("Do not use obsolete Assert.Throws() to check for asynchronously thrown exceptions.", d.GetMessage()); - Assert.Equal("xUnit2019", d.Id); - Assert.Equal(DiagnosticSeverity.Hidden, d.Severity); - }); + Verify.CompilerError("CS0619").WithSpan(7, 5, 7, 72).WithMessage("'Assert.Throws(Func)' is obsolete: 'You must call Assert.ThrowsAsync (and await the result) when testing async code.'"), + Verify.Diagnostic("xUnit2019").WithSpan(7, 5, 7, 72).WithSeverity(DiagnosticSeverity.Hidden).WithArguments("Assert.Throws()"), + }; + await Verify.VerifyAnalyzerAsync(source, expected); } [Fact] public async Task FindsWarning_ForThrowsCheck_WithExceptionTypeArgument_OnThrowingLambda() { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, CompilationReporting.IgnoreErrors, + var source = @"class TestClass { void TestMethod() { Xunit.Assert.Throws(() => System.Threading.Tasks.Task.Delay(0)); -} }"); +} }"; - Assert.Collection(diagnostics, d => + DiagnosticResult[] expected = { - Assert.Equal("Do not use obsolete Assert.Throws() to check for asynchronously thrown exceptions.", d.GetMessage()); - Assert.Equal("xUnit2019", d.Id); - Assert.Equal(DiagnosticSeverity.Hidden, d.Severity); - }); + Verify.CompilerError("CS0619").WithSpan(2, 5, 2, 100).WithMessage("'Assert.Throws(Func)' is obsolete: 'You must call Assert.ThrowsAsync (and await the result) when testing async code.'"), + Verify.Diagnostic("xUnit2019").WithSpan(2, 5, 2, 100).WithSeverity(DiagnosticSeverity.Hidden).WithArguments("Assert.Throws()"), + }; + await Verify.VerifyAnalyzerAsync(source, expected); } [Fact] public async Task FindsWarning_ForThrowsCheck_WithExceptionTypeArgument_OnAsyncThrowingLambda() { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, CompilationReporting.IgnoreErrors, + var source = @"class TestClass { void TestMethod() { Xunit.Assert.Throws(async () => await System.Threading.Tasks.Task.Delay(0)); -} }"); +} }"; - Assert.Collection(diagnostics, d => + DiagnosticResult[] expected = { - Assert.Equal("Do not use obsolete Assert.Throws() to check for asynchronously thrown exceptions.", d.GetMessage()); - Assert.Equal("xUnit2019", d.Id); - Assert.Equal(DiagnosticSeverity.Hidden, d.Severity); - }); + Verify.CompilerError("CS0619").WithSpan(2, 5, 2, 112).WithMessage("'Assert.Throws(Func)' is obsolete: 'You must call Assert.ThrowsAsync (and await the result) when testing async code.'"), + Verify.Diagnostic("xUnit2019").WithSpan(2, 5, 2, 112).WithSeverity(DiagnosticSeverity.Hidden).WithArguments("Assert.Throws()"), + }; + await Verify.VerifyAnalyzerAsync(source, expected); } [Fact] public async Task FindsWarning_ForThrowsCheck_WithExceptionTypeArgument_OnThrowingMethodWithParamName() { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, CompilationReporting.IgnoreErrors, + var source = @"class TestClass { System.Threading.Tasks.Task ThrowingMethod() { throw new System.NotImplementedException(); @@ -125,52 +112,52 @@ System.Threading.Tasks.Task ThrowingMethod() { void TestMethod() { Xunit.Assert.Throws(""param1"", ThrowingMethod); -} }"); +} }"; - Assert.Collection(diagnostics, d => + DiagnosticResult[] expected = { - Assert.Equal("Do not use obsolete Assert.Throws() to check for asynchronously thrown exceptions.", d.GetMessage()); - Assert.Equal("xUnit2019", d.Id); - Assert.Equal(DiagnosticSeverity.Hidden, d.Severity); - }); + Verify.CompilerError("CS0619").WithSpan(7, 5, 7, 76).WithMessage("'Assert.Throws(string, Func)' is obsolete: 'You must call Assert.ThrowsAsync (and await the result) when testing async code.'"), + Verify.Diagnostic("xUnit2019").WithSpan(7, 5, 7, 76).WithSeverity(DiagnosticSeverity.Hidden).WithArguments("Assert.Throws()"), + }; + await Verify.VerifyAnalyzerAsync(source, expected); } [Fact] public async Task FindsWarning_ForThrowsCheck_WithExceptionTypeArgument_OnThrowingLambdaWithParamName() { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, CompilationReporting.IgnoreErrors, + var source = @"class TestClass { void TestMethod() { Xunit.Assert.Throws(""param1"", () => System.Threading.Tasks.Task.Delay(0)); -} }"); +} }"; - Assert.Collection(diagnostics, d => + DiagnosticResult[] expected = { - Assert.Equal("Do not use obsolete Assert.Throws() to check for asynchronously thrown exceptions.", d.GetMessage()); - Assert.Equal("xUnit2019", d.Id); - Assert.Equal(DiagnosticSeverity.Hidden, d.Severity); - }); + Verify.CompilerError("CS0619").WithSpan(2, 5, 2, 104).WithMessage("'Assert.Throws(string, Func)' is obsolete: 'You must call Assert.ThrowsAsync (and await the result) when testing async code.'"), + Verify.Diagnostic("xUnit2019").WithSpan(2, 5, 2, 104).WithSeverity(DiagnosticSeverity.Hidden).WithArguments("Assert.Throws()"), + }; + await Verify.VerifyAnalyzerAsync(source, expected); } [Fact] public async Task FindsWarning_ForThrowsCheck_WithExceptionTypeArgument_OnAsyncThrowingLambdaWithParamName() { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, CompilationReporting.IgnoreErrors, + var source = @"class TestClass { void TestMethod() { Xunit.Assert.Throws(""param1"", async () => await System.Threading.Tasks.Task.Delay(0)); -} }"); +} }"; - Assert.Collection(diagnostics, d => + DiagnosticResult[] expected = { - Assert.Equal("Do not use obsolete Assert.Throws() to check for asynchronously thrown exceptions.", d.GetMessage()); - Assert.Equal("xUnit2019", d.Id); - Assert.Equal(DiagnosticSeverity.Hidden, d.Severity); - }); + Verify.CompilerError("CS0619").WithSpan(2, 5, 2, 116).WithMessage("'Assert.Throws(string, Func)' is obsolete: 'You must call Assert.ThrowsAsync (and await the result) when testing async code.'"), + Verify.Diagnostic("xUnit2019").WithSpan(2, 5, 2, 116).WithSeverity(DiagnosticSeverity.Hidden).WithArguments("Assert.Throws()"), + }; + await Verify.VerifyAnalyzerAsync(source, expected); } [Fact] public async Task FindsWarning_ForThrowsAnyCheck_WithExceptionTypeArgument_OnThrowingMethod() { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, CompilationReporting.IgnoreErrors, + var source = @"class TestClass { System.Threading.Tasks.Task ThrowingMethod() { throw new System.NotImplementedException(); @@ -178,52 +165,40 @@ System.Threading.Tasks.Task ThrowingMethod() { void TestMethod() { Xunit.Assert.ThrowsAny(ThrowingMethod); -} }"); +} }"; - Assert.Collection(diagnostics, d => - { - Assert.Equal("Do not use Assert.ThrowsAny() to check for asynchronously thrown exceptions.", d.GetMessage()); - Assert.Equal("xUnit2014", d.Id); - Assert.Equal(DiagnosticSeverity.Error, d.Severity); - }); + var expected = Verify.Diagnostic("xUnit2014").WithSpan(7, 5, 7, 75).WithSeverity(DiagnosticSeverity.Error).WithArguments("Assert.ThrowsAny()"); + await Verify.VerifyAnalyzerAsync(source, expected); } [Fact] public async Task FindsWarning_ForThrowsAnyCheck_WithExceptionTypeArgument_OnThrowingLambda() { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, CompilationReporting.IgnoreErrors, + var source = @"class TestClass { void TestMethod() { Xunit.Assert.ThrowsAny(() => System.Threading.Tasks.Task.Delay(0)); -} }"); +} }"; - Assert.Collection(diagnostics, d => - { - Assert.Equal("Do not use Assert.ThrowsAny() to check for asynchronously thrown exceptions.", d.GetMessage()); - Assert.Equal("xUnit2014", d.Id); - Assert.Equal(DiagnosticSeverity.Error, d.Severity); - }); + var expected = Verify.Diagnostic("xUnit2014").WithSpan(2, 5, 2, 103).WithSeverity(DiagnosticSeverity.Error).WithArguments("Assert.ThrowsAny()"); + await Verify.VerifyAnalyzerAsync(source, expected); } [Fact] public async Task FindsWarning_ForThrowsAnyCheck_WithExceptionTypeArgument_OnAsyncThrowingLambda() { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, CompilationReporting.IgnoreErrors, + var source = @"class TestClass { void TestMethod() { Xunit.Assert.ThrowsAny(async () => await System.Threading.Tasks.Task.Delay(0)); -} }"); +} }"; - Assert.Collection(diagnostics, d => - { - Assert.Equal("Do not use Assert.ThrowsAny() to check for asynchronously thrown exceptions.", d.GetMessage()); - Assert.Equal("xUnit2014", d.Id); - Assert.Equal(DiagnosticSeverity.Error, d.Severity); - }); + var expected = Verify.Diagnostic("xUnit2014").WithSpan(2, 5, 2, 115).WithSeverity(DiagnosticSeverity.Error).WithArguments("Assert.ThrowsAny()"); + await Verify.VerifyAnalyzerAsync(source, expected); } [Fact] public async void DoesNotFindWarning_ForThrowsCheck_WithExceptionParameter_OnNonAsyncThrowingMethod() { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, CompilationReporting.IgnoreErrors, + var source = @"class TestClass { void ThrowingMethod() { throw new System.NotImplementedException(); @@ -231,27 +206,28 @@ void ThrowingMethod() { void TestMethod() { Xunit.Assert.Throws(typeof(System.NotImplementedException), ThrowingMethod); -} }"); +} }"; - Assert.Empty(diagnostics); + var expected = Verify.CompilerError("CS0121").WithSpan(7, 18, 7, 24).WithMessage("The call is ambiguous between the following methods or properties: 'Assert.Throws(Type, Action)' and 'Assert.Throws(Type, Func)'"); + await Verify.VerifyAnalyzerAsync(source, expected); } [Fact] public async void DoesNotFindWarning_ForThrowsCheck_WithExceptionParameter_OnNonAsyncThrowingLamba() { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, CompilationReporting.IgnoreErrors, + var source = @"class TestClass { void TestMethod() { Xunit.Assert.Throws(typeof(System.NotImplementedException), () => 1); -} }"); +} }"; - Assert.Empty(diagnostics); + await Verify.VerifyAnalyzerAsync(source); } [Fact] public async void DoesNotFindWarning_ForThrowsAsyncCheck_WithExceptionParameter_OnThrowingMethod() { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = @"class TestClass { System.Threading.Tasks.Task ThrowingMethod() { throw new System.NotImplementedException(); @@ -259,26 +235,26 @@ System.Threading.Tasks.Task ThrowingMethod() { async System.Threading.Tasks.Task TestMethod() { await Xunit.Assert.ThrowsAsync(typeof(System.NotImplementedException), ThrowingMethod); -} }"); +} }"; - Assert.Empty(diagnostics); + await Verify.VerifyAnalyzerAsync(source); } [Fact] public async void DoesNotFindWarning_ForThrowsAsyncCheck_WithExceptionParameter_OnThrowingLambda() { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = @"class TestClass { async System.Threading.Tasks.Task TestMethod() { await Xunit.Assert.ThrowsAsync(typeof(System.NotImplementedException), () => System.Threading.Tasks.Task.Delay(0)); -} }"); +} }"; - Assert.Empty(diagnostics); + await Verify.VerifyAnalyzerAsync(source); } [Fact] public async void DoesNotFindWarning_ForThrowsAsyncCheck_WithExceptionTypeArgument_OnThrowingMethod() { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = @"class TestClass { System.Threading.Tasks.Task ThrowingMethod() { throw new System.NotImplementedException(); @@ -286,26 +262,26 @@ System.Threading.Tasks.Task ThrowingMethod() { async System.Threading.Tasks.Task TestMethod() { await Xunit.Assert.ThrowsAsync(ThrowingMethod); -} }"); +} }"; - Assert.Empty(diagnostics); + await Verify.VerifyAnalyzerAsync(source); } [Fact] public async void DoesNotFindWarning_ForThrowsAsyncCheck_WithExceptionTypeArgument_OnThrowingLambda() { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = @"class TestClass { async System.Threading.Tasks.Task TestMethod() { await Xunit.Assert.ThrowsAsync(() => System.Threading.Tasks.Task.Delay(0)); -} }"); +} }"; - Assert.Empty(diagnostics); + await Verify.VerifyAnalyzerAsync(source); } [Fact] public async void DoesNotFindWarning_ForThrowsAnyAsyncCheck_WithExceptionTypeArgument_OnThrowingMethod() { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = @"class TestClass { System.Threading.Tasks.Task ThrowingMethod() { throw new System.NotImplementedException(); @@ -313,20 +289,20 @@ System.Threading.Tasks.Task ThrowingMethod() { async System.Threading.Tasks.Task TestMethod() { await Xunit.Assert.ThrowsAnyAsync(ThrowingMethod); -} }"); +} }"; - Assert.Empty(diagnostics); + await Verify.VerifyAnalyzerAsync(source); } [Fact] public async void DoesNotFindWarning_ForThrowsAnyAsyncCheck_WithExceptionTypeArgument_OnThrowingLambda() { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = @"class TestClass { async System.Threading.Tasks.Task TestMethod() { await Xunit.Assert.ThrowsAnyAsync(() => System.Threading.Tasks.Task.Delay(0)); -} }"); +} }"; - Assert.Empty(diagnostics); + await Verify.VerifyAnalyzerAsync(source); } } } diff --git a/test/xunit.analyzers.tests/AssertThrowsShouldUseGenericOverloadTests.cs b/test/xunit.analyzers.tests/AssertThrowsShouldUseGenericOverloadTests.cs index ca9e52fa..544c4007 100644 --- a/test/xunit.analyzers.tests/AssertThrowsShouldUseGenericOverloadTests.cs +++ b/test/xunit.analyzers.tests/AssertThrowsShouldUseGenericOverloadTests.cs @@ -1,31 +1,18 @@ -using System.Collections.Generic; -using System.Threading.Tasks; +using System.Threading.Tasks; using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.Diagnostics; +using Verify = Xunit.Analyzers.CSharpVerifier; namespace Xunit.Analyzers { public class AssertThrowsShouldUseGenericOverloadTests { - private readonly DiagnosticAnalyzer analyzer = new AssertThrowsShouldUseGenericOverloadCheck(); - public static TheoryData Methods = new TheoryData { "Throws", "ThrowsAsync" }; - private static void AssertHasDiagnostic(IEnumerable diagnostics) - { - Assert.Collection(diagnostics, d => - { - Assert.Equal("Do not use typeof() expression to check the exception type.", d.GetMessage()); - Assert.Equal("xUnit2015", d.Id); - Assert.Equal(DiagnosticSeverity.Warning, d.Severity); - }); - } - [Theory] [MemberData(nameof(Methods))] public async Task FindsWarning_ForThrowsCheck_WithExceptionParameter_OnThrowingMethod(string method) { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = @"class TestClass { System.Threading.Tasks.Task ThrowingMethod() { throw new System.NotImplementedException(); @@ -33,50 +20,79 @@ System.Threading.Tasks.Task ThrowingMethod() { void TestMethod() { Xunit.Assert." + method + @"(typeof(System.NotImplementedException), ThrowingMethod); -} }"); +} }"; - AssertHasDiagnostic(diagnostics); + var expected = Verify.Diagnostic().WithSpan(7, 5, 7, 74 + method.Length).WithSeverity(DiagnosticSeverity.Warning); + await Verify.VerifyAnalyzerAsync(source, expected); } [Theory] [MemberData(nameof(Methods))] public async Task FindsWarning_ForThrowsCheck_WithExceptionParameter_OnThrowingLambda(string method) { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = @"class TestClass { void TestMethod() { Xunit.Assert." + method + @"(typeof(System.NotImplementedException), () => System.Threading.Tasks.Task.Delay(0)); -} }"); +} }"; - AssertHasDiagnostic(diagnostics); + var expected = Verify.Diagnostic().WithSpan(2, 5, 2, 102 + method.Length).WithSeverity(DiagnosticSeverity.Warning); + await Verify.VerifyAnalyzerAsync(source, expected); } - [Theory] - [MemberData(nameof(Methods))] - public async void DoesNotFindWarning_ForThrowsCheck_WithExceptionTypeArgument_OnThrowingMethod(string method) + [Fact] + public async void DoesNotFindWarning_ForThrowsCheck_WithExceptionTypeArgument_OnThrowingMethod() { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, CompilationReporting.IgnoreErrors, + var source = + @"class TestClass { +System.Threading.Tasks.Task ThrowingMethod() { + throw new System.NotImplementedException(); +} + +void TestMethod() { + Xunit.Assert.Throws(ThrowingMethod); +} }"; + + var expected = Verify.CompilerError("CS0619").WithSpan(7, 5, 7, 72).WithMessage("'Assert.Throws(Func)' is obsolete: 'You must call Assert.ThrowsAsync (and await the result) when testing async code.'"); + await Verify.VerifyAnalyzerAsync(source, expected); + } + + [Fact] + public async void DoesNotFindWarning_ForThrowsAsyncCheck_WithExceptionTypeArgument_OnThrowingMethod() + { + var source = @"class TestClass { System.Threading.Tasks.Task ThrowingMethod() { throw new System.NotImplementedException(); } async System.Threading.Tasks.Task TestMethod() { - await Xunit.Assert." + method + @"(ThrowingMethod); -} }"); + await Xunit.Assert.ThrowsAsync(ThrowingMethod); +} }"; - Assert.Empty(diagnostics); + await Verify.VerifyAnalyzerAsync(source); } - [Theory] - [MemberData(nameof(Methods))] - public async void DoesNotFindWarning_ForThrowsCheck_WithExceptionTypeArgument_OnThrowingLambda(string method) + [Fact] + public async void DoesNotFindWarning_ForThrowsCheck_WithExceptionTypeArgument_OnThrowingLambda() + { + var source = + @"class TestClass { void TestMethod() { + Xunit.Assert.Throws(() => System.Threading.Tasks.Task.Delay(0)); +} }"; + + var expected = Verify.CompilerError("CS0619").WithSpan(2, 5, 2, 100).WithMessage("'Assert.Throws(Func)' is obsolete: 'You must call Assert.ThrowsAsync (and await the result) when testing async code.'"); + await Verify.VerifyAnalyzerAsync(source, expected); + } + + [Fact] + public async void DoesNotFindWarning_ForThrowsAsyncCheck_WithExceptionTypeArgument_OnThrowingLambda() { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, CompilationReporting.IgnoreErrors, + var source = @"class TestClass { async System.Threading.Tasks.Task TestMethod() { - await Xunit.Assert." + method + @"(() => System.Threading.Tasks.Task.Delay(0)); -} }"); + await Xunit.Assert.ThrowsAsync(() => System.Threading.Tasks.Task.Delay(0)); +} }"; - Assert.Empty(diagnostics); + await Verify.VerifyAnalyzerAsync(source); } } } diff --git a/test/xunit.analyzers.tests/CSharpVerifier`1.cs b/test/xunit.analyzers.tests/CSharpVerifier`1.cs new file mode 100644 index 00000000..498a4383 --- /dev/null +++ b/test/xunit.analyzers.tests/CSharpVerifier`1.cs @@ -0,0 +1,95 @@ +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CodeFixes; +using Microsoft.CodeAnalysis.CSharp.Testing; +using Microsoft.CodeAnalysis.Diagnostics; +using Microsoft.CodeAnalysis.Testing; +using Microsoft.CodeAnalysis.Testing.Verifiers; + +namespace Xunit.Analyzers +{ + public class CSharpVerifier + where TAnalyzer : DiagnosticAnalyzer, new() + { + public static DiagnosticResult Diagnostic() + => CSharpCodeFixVerifier.Diagnostic(); + + public static DiagnosticResult Diagnostic(string diagnosticId) + => CSharpCodeFixVerifier.Diagnostic(diagnosticId); + + public static DiagnosticResult Diagnostic(DiagnosticDescriptor descriptor) + => new DiagnosticResult(descriptor); + + public static DiagnosticResult CompilerError(string errorIdentifier) + => new DiagnosticResult(errorIdentifier, DiagnosticSeverity.Error); + + public static Task VerifyAnalyzerAsync(string source, params DiagnosticResult[] expected) + { + var test = new Test { TestCode = source }; + test.ExpectedDiagnostics.AddRange(expected); + return test.RunAsync(); + } + + public static Task VerifyCodeFixAsync(string source, string fixedSource) + => VerifyCodeFixAsync(source, DiagnosticResult.EmptyDiagnosticResults, fixedSource); + + public static Task VerifyCodeFixAsync(string source, DiagnosticResult expected, string fixedSource) + => VerifyCodeFixAsync(source, new[] { expected }, fixedSource); + + public static Task VerifyCodeFixAsync(string source, DiagnosticResult[] expected, string fixedSource) + { + var test = new Test + { + TestCode = source, + FixedCode = fixedSource, + }; + + test.ExpectedDiagnostics.AddRange(expected); + return test.RunAsync(); + } + + public class Test : CSharpCodeFixTest + { + public Test() + { + SolutionTransforms.Add((solution, projectId) => + { + solution = solution + .AddMetadataReference(projectId, CodeAnalyzerHelper.XunitAbstractionsReference) + .AddMetadataReference(projectId, CodeAnalyzerHelper.XunitAssertReference) + .AddMetadataReference(projectId, CodeAnalyzerHelper.XunitCoreReference) + .AddMetadataReference(projectId, CodeAnalyzerHelper.SystemThreadingTasksReference); + +#if NETCOREAPP2_2 + solution = solution + .AddMetadataReference(projectId, CodeAnalyzerHelper.SystemCollectionsReference) + .AddMetadataReference(projectId, CodeAnalyzerHelper.SystemCollectionsNonGenericReference) + .AddMetadataReference(projectId, CodeAnalyzerHelper.SystemConsoleReference) + .AddMetadataReference(projectId, CodeAnalyzerHelper.SystemRuntimeReference) + .AddMetadataReference(projectId, CodeAnalyzerHelper.SystemRuntimeExtensionsReference) + .AddMetadataReference(projectId, CodeAnalyzerHelper.SystemTextRegularExpressionsReference); +#endif + + return solution; + }); + + // xunit diagnostics are reported in both normal and generated code + TestBehaviors |= TestBehaviors.SkipGeneratedCodeCheck; + } + + protected override IEnumerable GetCodeFixProviders() + { + var analyzer = new TAnalyzer(); + foreach (var provider in CodeFixProviderDiscovery.GetCodeFixProviders(Language)) + { + if (analyzer.SupportedDiagnostics.Any(diagnostic => provider.FixableDiagnosticIds.Contains(diagnostic.Id))) + { + yield return provider; + } + } + } + } + } +} diff --git a/test/xunit.analyzers.tests/ClassDataAttributeMustPointAtValidClassTests.cs b/test/xunit.analyzers.tests/ClassDataAttributeMustPointAtValidClassTests.cs index 68c4eced..3a6f290e 100644 --- a/test/xunit.analyzers.tests/ClassDataAttributeMustPointAtValidClassTests.cs +++ b/test/xunit.analyzers.tests/ClassDataAttributeMustPointAtValidClassTests.cs @@ -1,75 +1,83 @@ -using Microsoft.CodeAnalysis.Diagnostics; +using Verify = Xunit.Analyzers.CSharpVerifier; namespace Xunit.Analyzers { public class ClassDataAttributeMustPointAtValidClassTests { private static readonly string TestMethodSource = "public class TestClass { [Xunit.Theory][Xunit.ClassData(typeof(DataClass))] public void TestMethod() { } }"; - readonly DiagnosticAnalyzer analyzer = new ClassDataAttributeMustPointAtValidClass(); [Fact] public async void DoesNotFindErrorForFactMethod() { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, TestMethodSource, + var source = @"class DataClass : System.Collections.Generic.IEnumerable { public System.Collections.Generic.IEnumerator GetEnumerator() => null; System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => null; -}"); +}"; - Assert.Empty(diagnostics); + await new Verify.Test + { + TestState = { Sources = { TestMethodSource, source } }, + }.RunAsync(); } [Fact] public async void FindsErrorForDataClassNotImplementingInterface() { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, TestMethodSource, + var source = @"class DataClass : System.Collections.Generic.IEnumerable { public System.Collections.Generic.IEnumerator GetEnumerator() => null; System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => null; -}"); +}"; - Assert.Collection(diagnostics, - d => + await new Verify.Test + { + TestState = { - Assert.Equal("ClassData must point at a valid class", d.GetMessage()); - Assert.Equal("xUnit1007", d.Descriptor.Id); - }); + Sources = { TestMethodSource, source }, + ExpectedDiagnostics = { Verify.Diagnostic().WithSpan(1, 64, 1, 73) }, + }, + }.RunAsync(); } [Fact] public async void FindsErrorForAbstractDataClass() { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, TestMethodSource, + var source = @"abstract class DataClass : System.Collections.Generic.IEnumerable { public DataClass() {} public System.Collections.Generic.IEnumerator GetEnumerator() => null; System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => null; -}"); +}"; - Assert.Collection(diagnostics, - d => + await new Verify.Test + { + TestState = { - Assert.Equal("ClassData must point at a valid class", d.GetMessage()); - Assert.Equal("xUnit1007", d.Descriptor.Id); - }); + Sources = { TestMethodSource, source }, + ExpectedDiagnostics = { Verify.Diagnostic().WithSpan(1, 64, 1, 73) }, + }, + }.RunAsync(); } [Fact] public async void FindsErrorForDataClassWithImplicitPrivateConstructor() { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, TestMethodSource, + var source = @"class DataClass : System.Collections.Generic.IEnumerable { public DataClass(string parameter) {} public System.Collections.Generic.IEnumerator GetEnumerator() => null; System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => null; -}"); +}"; - Assert.Collection(diagnostics, - d => + await new Verify.Test + { + TestState = { - Assert.Equal("ClassData must point at a valid class", d.GetMessage()); - Assert.Equal("xUnit1007", d.Descriptor.Id); - }); + Sources = { TestMethodSource, source }, + ExpectedDiagnostics = { Verify.Diagnostic().WithSpan(1, 64, 1, 73) }, + }, + }.RunAsync(); } [Theory] @@ -77,19 +85,21 @@ public DataClass(string parameter) {} [InlineData("internal")] public async void FindsErrorForDataClassWithExplicitNonPublicConstructor(string accessiblity) { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, TestMethodSource, + var source = string.Format(@"class DataClass : System.Collections.Generic.IEnumerable {{ {0} DataClass() {{}} public System.Collections.Generic.IEnumerator GetEnumerator() => null; System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => null; -}}", accessiblity)); +}}", accessiblity); - Assert.Collection(diagnostics, - d => + await new Verify.Test + { + TestState = { - Assert.Equal("ClassData must point at a valid class", d.GetMessage()); - Assert.Equal("xUnit1007", d.Descriptor.Id); - }); + Sources = { TestMethodSource, source }, + ExpectedDiagnostics = { Verify.Diagnostic().WithSpan(1, 64, 1, 73) }, + }, + }.RunAsync(); } } } diff --git a/test/xunit.analyzers.tests/CodeAnalyzerHelper.cs b/test/xunit.analyzers.tests/CodeAnalyzerHelper.cs index 262d561f..e52252ba 100644 --- a/test/xunit.analyzers.tests/CodeAnalyzerHelper.cs +++ b/test/xunit.analyzers.tests/CodeAnalyzerHelper.cs @@ -1,275 +1,55 @@ -using System; -using System.Collections.Generic; -using System.Collections.Immutable; +using System.Collections.Generic; +using System.IO; using System.Linq; using System.Reflection; -using System.Threading; -using System.Threading.Tasks; using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CodeActions; -using Microsoft.CodeAnalysis.CodeFixes; using Microsoft.CodeAnalysis.CSharp; -using Microsoft.CodeAnalysis.Diagnostics; -using Microsoft.CodeAnalysis.Text; using Xunit.Abstractions; using Xunit.Sdk; namespace Xunit.Analyzers { - enum CompilationReporting - { - /// Ignores all errors and warnings - IgnoreErrors = -1, - - /// Fails on all errors, ignores all warnings - FailOnErrors = 0, - - /// Fails on all errors and level 1 warnings, ignores all other warnings - FailOnErrorsAndLevel1Warnings = 1, - - /// Fails on all errors and level 1 and 2 warnings, ignores all other warnings - FailOnErrorsAndLevel2Warnings = 2, - - /// Fails on all errors and level 1 through 3 warnings, ignores all other warnings - FailOnErrorsAndLevel3Warnings = 3, - - /// Fails on all errors and warnings - FailOnErrorsAndLevel4Warnings = 4, - } - - [Flags] - enum XunitReferences - { - None = 0, - - /// Adds a reference to xunit.abstractions - Abstractions = 0x01, - - /// Adds a reference to xunit.assert - Assert = 0x02, - - /// Adds a reference to xunit.core - Core = 0x04, - - /// Adds a reference to xunit.execution - Execution = 0x08, - - /// - /// This adds references akin to the xunit.extensibility.core NuGet package. This is appropriate - /// for simulating the typing references used when writing core-only extensibility. - /// - PkgCoreExtensibility = Abstractions | Core, - - /// - /// This adds references akin to the xunit.extensibility.execution NuGet package. This is appropriate - /// for simulating the typing references used when writing full extensibility. - /// - PkgExecutionExtensibility = Abstractions | Core | Execution, - - /// - /// This adds references akin to the xunit NuGet package. This is appropriate for simulating the - /// typical references used when writing unit tests. - /// - PkgXunit = Abstractions | Assert | Core, - - /// - /// This adds references akin to the xunit.core NuGet package. This is appropriate for simulating the - /// typical references used when writing unit tests with a third party assertion library. - /// - PkgXunitCore = Abstractions | Core, - } - class CodeAnalyzerHelper { - static readonly MetadataReference CorlibReference = GetAssemblyReference(typeof(object)); - static readonly MetadataReference NetStandardReference = GetAssemblyReference("netstandard, Version=2.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51"); - static readonly MetadataReference SystemCollectionsImmutableReference = GetAssemblyReference(typeof(ImmutableArray)); - static readonly MetadataReference SystemCollectionsReference = GetAssemblyReference("System.Collections"); - static readonly MetadataReference SystemConsoleReference = GetAssemblyReference("System.Console"); - static readonly MetadataReference SystemCoreReference = GetAssemblyReference(typeof(Enumerable)); - static readonly MetadataReference SystemTextReference = GetAssemblyReference(typeof(System.Text.RegularExpressions.Regex)); - static readonly MetadataReference SystemRuntimeExtensionsReference = GetAssemblyReference("System.Runtime.Extensions"); - static readonly MetadataReference SystemRuntimeReference; - static readonly MetadataReference SystemThreadingTasksReference; - static readonly MetadataReference XunitAbstractionsReference = GetAssemblyReference(typeof(ITest)); - static readonly MetadataReference XunitAssertReference = GetAssemblyReference(typeof(Assert)); - static readonly MetadataReference XunitCoreReference = GetAssemblyReference(typeof(FactAttribute)); - static readonly MetadataReference XunitExecutionReference = GetAssemblyReference(typeof(XunitTestCase)); - - static readonly IEnumerable SystemReferences; - - static readonly Dictionary ReferenceMap = new Dictionary { - { XunitReferences.Abstractions, new[] { XunitAbstractionsReference } }, - { XunitReferences.Assert, new[] { XunitAssertReference } }, - { XunitReferences.Core, new[] { XunitCoreReference } }, - { XunitReferences.Execution, new[] { XunitExecutionReference } }, - }; +#if NETCOREAPP2_2 + internal static readonly PortableExecutableReference SystemCollectionsReference; + internal static readonly MetadataReference SystemCollectionsNonGenericReference; + internal static readonly MetadataReference SystemConsoleReference; + internal static readonly MetadataReference SystemRuntimeReference; + internal static readonly MetadataReference SystemRuntimeExtensionsReference; + internal static readonly MetadataReference SystemTextRegularExpressionsReference; +#endif + internal static readonly MetadataReference SystemThreadingTasksReference; + internal static readonly MetadataReference XunitAbstractionsReference = MetadataReference.CreateFromFile(typeof(ITest).GetTypeInfo().Assembly.Location); + internal static readonly MetadataReference XunitAssertReference = MetadataReference.CreateFromFile(typeof(Assert).GetTypeInfo().Assembly.Location); + internal static readonly MetadataReference XunitCoreReference = MetadataReference.CreateFromFile(typeof(FactAttribute).GetTypeInfo().Assembly.Location); + internal static readonly MetadataReference XunitExecutionReference = MetadataReference.CreateFromFile(typeof(XunitTestCase).GetTypeInfo().Assembly.Location); static CodeAnalyzerHelper() { // Xunit is a PCL linked against System.Runtime, however on the Desktop framework all types in that assembly have been forwarded to // System.Core, so we need to find the assembly by name to compile without errors. var referencedAssemblies = typeof(FactAttribute).Assembly.GetReferencedAssemblies(); - +#if NETCOREAPP2_2 + SystemCollectionsReference = GetAssemblyReference(referencedAssemblies, "System.Collections"); SystemRuntimeReference = GetAssemblyReference(referencedAssemblies, "System.Runtime"); - SystemThreadingTasksReference = GetAssemblyReference(referencedAssemblies, "System.Threading.Tasks"); - SystemReferences = new[] { - CorlibReference, - NetStandardReference, - SystemCollectionsImmutableReference, - SystemCollectionsReference, - SystemConsoleReference, - SystemCoreReference, - SystemRuntimeReference, - SystemRuntimeExtensionsReference, - SystemTextReference, - SystemThreadingTasksReference, - }.Where(x => x != null).ToArray(); - } - - static async Task> ApplyAnalyzers(Compilation compilation, params DiagnosticAnalyzer[] analyzers) - { - var compilationWithAnalyzers = compilation - .WithOptions(((CSharpCompilationOptions)compilation.Options) - .WithWarningLevel(4)) - .WithAnalyzers(ImmutableArray.Create(analyzers)); - - var allDiagnostics = await compilationWithAnalyzers.GetAllDiagnosticsAsync(); - - Assert.DoesNotContain(allDiagnostics, d => d.Id == "AD0001"); - - return await compilationWithAnalyzers.GetAnalyzerDiagnosticsAsync(); - } + SystemRuntimeExtensionsReference = GetAssemblyReference(referencedAssemblies, "System.Runtime.Extensions"); +#endif - static MetadataReference GetAssemblyReference(Type type) - => MetadataReference.CreateFromFile(type.GetTypeInfo().Assembly.Location); - - static MetadataReference GetAssemblyReference(string name) - { - try - { - return MetadataReference.CreateFromFile(Assembly.Load(name).Location); - } - catch - { - return null; - } - } - - static MetadataReference GetAssemblyReference(IEnumerable assemblies, string name) - => MetadataReference.CreateFromFile(Assembly.Load(assemblies.First(n => n.Name == name)).Location); - - static async Task<(Compilation, Document, Workspace)> GetCompilationAsync(CompilationReporting compilationReporting, XunitReferences references, string source, params string[] additionalSources) - { - const string fileNamePrefix = "Source"; - const string projectName = "Project"; - - var projectId = ProjectId.CreateNewId(debugName: projectName); - - var workspace = new AdhocWorkspace(); - var solution = workspace - .CurrentSolution - .AddProject(projectId, projectName, projectName, LanguageNames.CSharp) - .AddMetadataReferences(projectId, GetMetadataReferences(references)); - - var count = 0; - var firstDocument = default(Document); - - foreach (var text in new[] { source }.Concat(additionalSources)) - { - var newFileName = $"{fileNamePrefix}{count++}.cs"; - var documentId = DocumentId.CreateNewId(projectId, debugName: newFileName); - solution = solution.AddDocument(documentId, newFileName, SourceText.From(text)); - if (firstDocument == default(Document)) - firstDocument = solution.GetDocument(documentId); - } - - var compileWarningLevel = Math.Max(0, (int)compilationReporting); - var project = solution.GetProject(projectId); - var compilationOptions = ((CSharpCompilationOptions)project.CompilationOptions) - .WithOutputKind(OutputKind.DynamicallyLinkedLibrary) - .WithWarningLevel(compileWarningLevel); - project = project.WithCompilationOptions(compilationOptions); - - var compilation = await project.GetCompilationAsync(); - if (compilationReporting != CompilationReporting.IgnoreErrors) - { - var compilationDiagnostics = compilation.GetDiagnostics(); - if (compilationDiagnostics.Length > 0) - { - var messages = compilationDiagnostics.Select(d => (diag: d, line: d.Location.GetLineSpan().StartLinePosition)) - .Select(t => $"source.cs({t.line.Line},{t.line.Character}): {t.diag.Severity.ToString().ToLowerInvariant()} {t.diag.Id}: {t.diag.GetMessage()}"); - throw new InvalidOperationException($"Compilation has issues:{Environment.NewLine}{string.Join(Environment.NewLine, messages)}"); - } - } - - return (compilation, firstDocument, workspace); - } - - public static Task> GetDiagnosticsAsync(DiagnosticAnalyzer analyzer, string source, params string[] additionalSources) - => GetDiagnosticsAsync(analyzer, CompilationReporting.FailOnErrors, XunitReferences.PkgXunit, source, additionalSources); - - public static Task> GetDiagnosticsAsync(DiagnosticAnalyzer analyzer, CompilationReporting compilationReporting, string source, params string[] additionalSources) - => GetDiagnosticsAsync(analyzer, compilationReporting, XunitReferences.PkgXunit, source, additionalSources); - - public static Task> GetDiagnosticsAsync(DiagnosticAnalyzer analyzer, XunitReferences references, string source, params string[] additionalSources) - => GetDiagnosticsAsync(analyzer, CompilationReporting.FailOnErrors, references, source, additionalSources); - - public static async Task> GetDiagnosticsAsync(DiagnosticAnalyzer analyzer, CompilationReporting compilationReporting, XunitReferences references, string source, params string[] additionalSources) - { - var (compilation, _, workspace) = await GetCompilationAsync(compilationReporting, references, source, additionalSources); - - using (workspace) - return await ApplyAnalyzers(compilation, analyzer); - } - - public static async Task GetFixedCodeAsync(DiagnosticAnalyzer analyzer, - CodeFixProvider fixer, - string source, - CompilationReporting compilationReporting = CompilationReporting.FailOnErrors, - XunitReferences references = XunitReferences.PkgXunit, - int actionIndex = 0) - { - var (compilation, document, workspace) = await GetCompilationAsync(compilationReporting, references, source); - - using (workspace) - { - var diagnostics = await ApplyAnalyzers(compilation, analyzer); - if (diagnostics.Length == 0) - throw new InvalidOperationException("The requested source code does not trigger the analyzer"); - if (diagnostics.Length > 1) - throw new InvalidOperationException($"The requested source code triggered the analyzer too many times (expected 1, got {diagnostics.Length})"); - - var codeActions = new List(); - var context = new CodeFixContext(document, diagnostics[0], (a, d) => codeActions.Add(a), CancellationToken.None); - await fixer.RegisterCodeFixesAsync(context); - if (codeActions.Count <= actionIndex) - throw new InvalidOperationException($"Not enough code actions were registered (index {actionIndex} is out of range for length {codeActions.Count})"); - - var operations = await codeActions[actionIndex].GetOperationsAsync(CancellationToken.None); - var changeOperations = operations.OfType().ToList(); - if (changeOperations.Count != 1) - throw new InvalidOperationException($"The change action did not yield the right number of ApplyChangesOperation objects (expected 1, got {changeOperations.Count})"); - - var changeOperation = changeOperations[0]; - changeOperation.Apply(workspace, CancellationToken.None); + SystemThreadingTasksReference = GetAssemblyReference(referencedAssemblies, "System.Threading.Tasks"); - var solution = changeOperation.ChangedSolution; - var changedDocument = solution.GetDocument(document.Id); - var text = await changedDocument.GetTextAsync(); - return text.ToString(); - } +#if NETCOREAPP2_2 + // Xunit doesn't directly reference System.Collections.NonGeneric, so we locate it relative to + // System.Collections. + SystemCollectionsNonGenericReference = MetadataReference.CreateFromFile(Path.Combine(Path.GetDirectoryName(SystemCollectionsReference.FilePath), "System.Collections.NonGeneric.dll")); + SystemConsoleReference = MetadataReference.CreateFromFile(Path.Combine(Path.GetDirectoryName(SystemCollectionsReference.FilePath), "System.Console.dll")); + SystemTextRegularExpressionsReference = MetadataReference.CreateFromFile(Path.Combine(Path.GetDirectoryName(SystemCollectionsReference.FilePath), "System.Text.RegularExpressions.dll")); +#endif } - static IEnumerable GetMetadataReferences(XunitReferences references) + static PortableExecutableReference GetAssemblyReference(IEnumerable assemblies, string name) { - var result = SystemReferences; - - foreach (var kvp in ReferenceMap) - if (references.HasFlag(kvp.Key)) - result = result.Concat(kvp.Value); - - return result; + return MetadataReference.CreateFromFile(Assembly.Load(assemblies.First(n => n.Name == name)).Location); } } } diff --git a/test/xunit.analyzers.tests/CodeFixProviderDiscovery.cs b/test/xunit.analyzers.tests/CodeFixProviderDiscovery.cs new file mode 100644 index 00000000..e8156a4e --- /dev/null +++ b/test/xunit.analyzers.tests/CodeFixProviderDiscovery.cs @@ -0,0 +1,55 @@ +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.CodeAnalysis.CodeFixes; +using Microsoft.VisualStudio.Composition; +using Xunit.Analyzers.FixProviders; + +namespace Xunit.Analyzers +{ + internal static class CodeFixProviderDiscovery + { + private static readonly Lazy ExportProviderFactory; + + static CodeFixProviderDiscovery() + { + ExportProviderFactory = new Lazy( + () => + { + var discovery = new AttributedPartDiscovery(Resolver.DefaultInstance, isNonPublicSupported: true); + var parts = Task.Run(() => discovery.CreatePartsAsync(typeof(ChangeMemberTypeFix).Assembly)).GetAwaiter().GetResult(); + var catalog = ComposableCatalog.Create(Resolver.DefaultInstance).AddParts(parts); + + var configuration = CompositionConfiguration.Create(catalog); + var runtimeComposition = RuntimeComposition.CreateRuntimeComposition(configuration); + return runtimeComposition.CreateExportProviderFactory(); + }, + LazyThreadSafetyMode.ExecutionAndPublication); + } + + public static IEnumerable GetCodeFixProviders(string language) + { + var exportProvider = ExportProviderFactory.Value.CreateExportProvider(); + var exports = exportProvider.GetExports(); + return exports.Where(export => export.Metadata.Languages.Contains(language)).Select(export => export.Value); + } + + private class LanguageMetadata + { + public LanguageMetadata(IDictionary data) + { + if (!data.TryGetValue(nameof(ExportCodeFixProviderAttribute.Languages), out var languages)) + { + languages = new string[0]; + } + + Languages = ((string[])languages).ToImmutableArray(); + } + + public ImmutableArray Languages { get; } + } + } +} diff --git a/test/xunit.analyzers.tests/DataAttributeShouldBeUsedOnATheoryTests.cs b/test/xunit.analyzers.tests/DataAttributeShouldBeUsedOnATheoryTests.cs index f8454ef9..907c3e07 100644 --- a/test/xunit.analyzers.tests/DataAttributeShouldBeUsedOnATheoryTests.cs +++ b/test/xunit.analyzers.tests/DataAttributeShouldBeUsedOnATheoryTests.cs @@ -1,17 +1,15 @@ -using Microsoft.CodeAnalysis.Diagnostics; +using Verify = Xunit.Analyzers.CSharpVerifier; namespace Xunit.Analyzers { public class DataAttributeShouldBeUsedOnATheoryTests { - readonly DiagnosticAnalyzer analyzer = new DataAttributeShouldBeUsedOnATheory(); - [Fact] public async void DoesNotFindErrorForFactMethodWithNoDataAttributes() { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, "public class TestClass { [Xunit.Fact] public void TestMethod() { } }"); + var source = "public class TestClass { [Xunit.Fact] public void TestMethod() { } }"; - Assert.Empty(diagnostics); + await Verify.VerifyAnalyzerAsync(source); } [Theory] @@ -20,10 +18,10 @@ public async void DoesNotFindErrorForFactMethodWithNoDataAttributes() [InlineData("ClassData(typeof(string))")] public async void DoesNotFindErrorForFactMethodWithDataAttributes(string dataAttribute) { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, - "public class TestClass { [Xunit.Fact, Xunit." + dataAttribute + "] public void TestMethod() { } }"); + var source = + "public class TestClass { [Xunit.Fact, Xunit." + dataAttribute + "] public void TestMethod() { } }"; - Assert.Empty(diagnostics); + await Verify.VerifyAnalyzerAsync(source); } [Theory] @@ -32,10 +30,10 @@ public async void DoesNotFindErrorForFactMethodWithDataAttributes(string dataAtt [InlineData("ClassData(typeof(string))")] public async void DoesNotFindErrorForTheoryMethodWithDataAttributes(string dataAttribute) { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, - "public class TestClass { [Xunit.Theory, Xunit." + dataAttribute + "] public void TestMethod() { } }"); + var source = + "public class TestClass { [Xunit.Theory, Xunit." + dataAttribute + "] public void TestMethod() { } }"; - Assert.Empty(diagnostics); + await Verify.VerifyAnalyzerAsync(source); } [Theory] @@ -44,15 +42,11 @@ public async void DoesNotFindErrorForTheoryMethodWithDataAttributes(string dataA [InlineData("ClassData(typeof(string))")] public async void FindsErrorForMethodsWithDataAttributesButNotFactOrTheory(string dataAttribute) { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, - "public class TestClass { [Xunit." + dataAttribute + "] public void TestMethod() { } }"); - - Assert.Collection(diagnostics, - d => - { - Assert.Equal("Test data attribute should only be used on a Theory", d.GetMessage()); - Assert.Equal("xUnit1008", d.Descriptor.Id); - }); + var source = + "public class TestClass { [Xunit." + dataAttribute + "] public void TestMethod() { } }"; + + var expected = Verify.Diagnostic().WithSpan(1, 47 + dataAttribute.Length, 1, 57 + dataAttribute.Length); + await Verify.VerifyAnalyzerAsync(source, expected); } } } diff --git a/test/xunit.analyzers.tests/FactMethodMustNotHaveParametersTests.cs b/test/xunit.analyzers.tests/FactMethodMustNotHaveParametersTests.cs index fcaabe34..d1ca5a2a 100644 --- a/test/xunit.analyzers.tests/FactMethodMustNotHaveParametersTests.cs +++ b/test/xunit.analyzers.tests/FactMethodMustNotHaveParametersTests.cs @@ -1,38 +1,32 @@ -using Microsoft.CodeAnalysis.Diagnostics; +using Verify = Xunit.Analyzers.CSharpVerifier; namespace Xunit.Analyzers { public class FactMethodMustNotHaveParametersTests { - readonly DiagnosticAnalyzer analyzer = new FactMethodMustNotHaveParameters(); - [Fact] public async void DoesNotFindErrorForFactWithNoParameters() { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, "public class TestClass { [Xunit.Fact] public void TestMethod() { } }"); + var source = "public class TestClass { [Xunit.Fact] public void TestMethod() { } }"; - Assert.Empty(diagnostics); + await Verify.VerifyAnalyzerAsync(source); } [Fact] public async void DoesNotFindErrorForTheoryWithParameters() { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, "public class TestClass { [Xunit.Theory] public void TestMethod(string p) { } }"); + var source = "public class TestClass { [Xunit.Theory] public void TestMethod(string p) { } }"; - Assert.Empty(diagnostics); + await Verify.VerifyAnalyzerAsync(source); } [Fact] public async void FindsErrorForPrivateClass() { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, "public class TestClass { [Xunit.Fact] public void TestMethod(string p) { } }"); + var source = "public class TestClass { [Xunit.Fact] public void TestMethod(string p) { } }"; - Assert.Collection(diagnostics, - d => - { - Assert.Equal("Fact methods cannot have parameters", d.GetMessage()); - Assert.Equal("xUnit1001", d.Descriptor.Id); - }); + var expected = Verify.Diagnostic().WithSpan(1, 51, 1, 61); + await Verify.VerifyAnalyzerAsync(source, expected); } } } diff --git a/test/xunit.analyzers.tests/FactMethodShouldNotHaveTestDataTests.cs b/test/xunit.analyzers.tests/FactMethodShouldNotHaveTestDataTests.cs index 1327c414..a3b858d7 100644 --- a/test/xunit.analyzers.tests/FactMethodShouldNotHaveTestDataTests.cs +++ b/test/xunit.analyzers.tests/FactMethodShouldNotHaveTestDataTests.cs @@ -1,17 +1,15 @@ -using Microsoft.CodeAnalysis.Diagnostics; +using Verify = Xunit.Analyzers.CSharpVerifier; namespace Xunit.Analyzers { public class FactMethodShouldNotHaveTestDataTests { - readonly DiagnosticAnalyzer analyzer = new FactMethodShouldNotHaveTestData(); - [Fact] public async void DoesNotFindErrorForFactMethodWithNoDataAttributes() { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, "public class TestClass { [Xunit.Fact] public void TestMethod() { } }"); + var source = "public class TestClass { [Xunit.Fact] public void TestMethod() { } }"; - Assert.Empty(diagnostics); + await Verify.VerifyAnalyzerAsync(source); } [Theory] @@ -20,10 +18,10 @@ public async void DoesNotFindErrorForFactMethodWithNoDataAttributes() [InlineData("ClassData(typeof(string))")] public async void DoesNotFindErrorForTheoryMethodWithDataAttributes(string dataAttribute) { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, - "public class TestClass { [Xunit.Theory, Xunit." + dataAttribute + "] public void TestMethod() { } }"); + var source = + "public class TestClass { [Xunit.Theory, Xunit." + dataAttribute + "] public void TestMethod() { } }"; - Assert.Empty(diagnostics); + await Verify.VerifyAnalyzerAsync(source); } [Theory] @@ -32,11 +30,17 @@ public async void DoesNotFindErrorForTheoryMethodWithDataAttributes(string dataA [InlineData("ClassData(typeof(string))")] public async void DoesNotFindErrorForDerviedFactMethodWithDataAttributes(string dataAttribute) { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, - "public class DerivedFactAttribute: Xunit.FactAttribute {}", - "public class TestClass { [DerivedFactAttribute, Xunit." + dataAttribute + "] public void TestMethod() { } }"); - - Assert.Empty(diagnostics); + await new Verify.Test + { + TestState = + { + Sources = + { + "public class DerivedFactAttribute: Xunit.FactAttribute {}", + "public class TestClass { [DerivedFactAttribute, Xunit." + dataAttribute + "] public void TestMethod() { } }", + }, + }, + }.RunAsync(); } [Theory] @@ -45,15 +49,11 @@ public async void DoesNotFindErrorForDerviedFactMethodWithDataAttributes(string [InlineData("ClassData(typeof(string))")] public async void FindsErrorForFactMethodsWithDataAttributes(string dataAttribute) { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, - "public class TestClass { [Xunit.Fact, Xunit." + dataAttribute + "] public void TestMethod() { } }"); + var source = + "public class TestClass { [Xunit.Fact, Xunit." + dataAttribute + "] public void TestMethod() { } }"; - Assert.Collection(diagnostics, - d => - { - Assert.Equal("Fact methods should not have test data", d.GetMessage()); - Assert.Equal("xUnit1005", d.Descriptor.Id); - }); + var expected = Verify.Diagnostic().WithSpan(1, 59 + dataAttribute.Length, 1, 69 + dataAttribute.Length); + await Verify.VerifyAnalyzerAsync(source, expected); } } } diff --git a/test/xunit.analyzers.tests/InlineDataMustMatchTheoryParametersTests.cs b/test/xunit.analyzers.tests/InlineDataMustMatchTheoryParametersTests.cs index 37e1696c..32815395 100644 --- a/test/xunit.analyzers.tests/InlineDataMustMatchTheoryParametersTests.cs +++ b/test/xunit.analyzers.tests/InlineDataMustMatchTheoryParametersTests.cs @@ -2,31 +2,33 @@ using System.Collections.Generic; using System.Linq; using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.Diagnostics; +using Microsoft.CodeAnalysis.Testing; +using Verify = Xunit.Analyzers.CSharpVerifier; +using Verify_2_3_1 = Xunit.Analyzers.CSharpVerifier; +using Verify_2_4 = Xunit.Analyzers.CSharpVerifier; +using Verify_2_5 = Xunit.Analyzers.CSharpVerifier; namespace Xunit.Analyzers { public abstract class InlineDataMustMatchTheoryParametersTests { - readonly DiagnosticAnalyzer analyzer = new InlineDataMustMatchTheoryParameters(); - public class ForFactMethod : InlineDataMustMatchTheoryParametersTests { [Fact] public async void DoesNotFindError_WhenNoDataAttributes() { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, "public class TestClass { [Xunit.Fact] public void TestMethod() { } }"); + var source = "public class TestClass { [Xunit.Fact] public void TestMethod() { } }"; - Assert.Empty(diagnostics); + await Verify.VerifyAnalyzerAsync(source); } [Fact] public async void DoesNotFindError_WithAttribute() { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, - "public class TestClass { [Xunit.Fact, Xunit.InlineData] public void TestMethod(string a) { } }"); + var source = + "public class TestClass { [Xunit.Fact, Xunit.InlineData] public void TestMethod(string a) { } }"; - Assert.Empty(diagnostics); + await Verify.VerifyAnalyzerAsync(source); } } @@ -35,91 +37,91 @@ public class ForTheoryWithArgumentMatch : InlineDataMustMatchTheoryParametersTes [Fact] public async void DoesNotFindErrorFor_MethodUsingParamsArgument() { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = "public class TestClass {" + " [Xunit.Theory, Xunit.InlineData(\"abc\", \"xyz\")]" + " public void TestMethod(params string[] args) { }" + - "}"); + "}"; - Assert.Empty(diagnostics); + await Verify.VerifyAnalyzerAsync(source); } [Fact] public async void DoesNotFindErrorFor_MethodUsingNormalAndParamsArgument() { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = "public class TestClass {" + " [Xunit.Theory, Xunit.InlineData(\"abc\", \"xyz\")]" + " public void TestMethod(string first, params string[] theRest) { }" + - "}"); + "}"; - Assert.Empty(diagnostics); + await Verify.VerifyAnalyzerAsync(source); } [Fact] public async void DoesNotFindErrorFor_MethodUsingNormalAndUnusedParamsArgument() { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = "public class TestClass {" + " [Xunit.Theory, Xunit.InlineData(\"abc\")]" + " public void TestMethod(string first, params string[] theRest) { }" + - "}"); + "}"; - Assert.Empty(diagnostics); + await Verify.VerifyAnalyzerAsync(source); } [Fact] public async void DoesNotFindErrorFor_UsingParameters() { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = "public class TestClass {" + " [Xunit.Theory, Xunit.InlineData(\"abc\", 1, null)]" + " public void TestMethod(string a, int b, object c) { }" + - "}"); + "}"; - Assert.Empty(diagnostics); + await Verify.VerifyAnalyzerAsync(source); } [Fact] public async void DoesNotFindErrorFor_UsingParametersWithDefaultValues() { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = "public class TestClass {" + " [Xunit.Theory, Xunit.InlineData(\"abc\")]" + " public void TestMethod(string a, string b = \"default\", string c = null) { }" + - "}"); + "}"; - Assert.Empty(diagnostics); + await Verify.VerifyAnalyzerAsync(source); } [Fact] public async void DoesNotFindErrorFor_UsingParametersWithDefaultValuesAndParamsArgument() { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = "public class TestClass {" + " [Xunit.Theory, Xunit.InlineData(\"abc\")]" + " public void TestMethod(string a, string b = \"default\", string c = null, params string[] d) { }" + - "}"); + "}"; - Assert.Empty(diagnostics); + await Verify.VerifyAnalyzerAsync(source); } [Fact] public async void DoesNotFindErrorFor_UsingParameterWithOptionalAttribute() { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = "public class TestClass {" + " [Xunit.Theory, Xunit.InlineData(\"abc\")]" + " public void TestMethod(string a, [System.Runtime.InteropServices.Optional] string b) { }" + - "}"); + "}"; - Assert.Empty(diagnostics); + await Verify.VerifyAnalyzerAsync(source); } - + [Fact] public async void DoesNotFindErrorFor_UsingMultipleParametersWithOptionalAttributes() { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = "public class TestClass {" + " [Xunit.Theory]" + " [Xunit.InlineData]" + @@ -127,69 +129,69 @@ public async void DoesNotFindErrorFor_UsingMultipleParametersWithOptionalAttribu " [Xunit.InlineData(\"abc\", \"def\")]" + " public void TestMethod([System.Runtime.InteropServices.Optional] string a," + " [System.Runtime.InteropServices.Optional] string b) { }" + - "}"); + "}"; - Assert.Empty(diagnostics); + await Verify.VerifyAnalyzerAsync(source); } [Fact] public async void DoesNotFindError_UsingExplicitArray() { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = "public class TestClass {" + " [Xunit.Theory, Xunit.InlineData(new object[] {\"abc\", 1, null})]" + " public void TestMethod(string a, int b, object c) { }" + - "}"); + "}"; - Assert.Empty(diagnostics); + await Verify.VerifyAnalyzerAsync(source); } [Fact] public async void DoesNotFindError_UsingExplicitNamedArray() { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = "public class TestClass {" + " [Xunit.Theory, Xunit.InlineData(data: new object[] {\"abc\", 1, null})]" + " public void TestMethod(string a, int b, object c) { }" + - "}"); + "}"; - Assert.Empty(diagnostics); + await Verify.VerifyAnalyzerAsync(source); } [Fact] public async void DoesNotFindError_UsingImplicitArray() { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = "public class TestClass {" + " [Xunit.Theory, Xunit.InlineData(new [] {(object)\"abc\", 1, null})]" + " public void TestMethod(string a, int b, object c) { }" + - "}"); + "}"; - Assert.Empty(diagnostics); + await Verify.VerifyAnalyzerAsync(source); } [Fact] public async void DoesNotFindError_UsingImplicitNamedArray() { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = "public class TestClass {" + " [Xunit.Theory, Xunit.InlineData(data: new [] {(object)\"abc\", 1, null})]" + " public void TestMethod(string a, int b, object c) { }" + - "}"); + "}"; - Assert.Empty(diagnostics); + await Verify.VerifyAnalyzerAsync(source); } [Fact] public async void DoesNotFindError_EmptyArray() { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = "public class TestClass {" + " [Xunit.Theory, Xunit.InlineData(new byte[0])]" + " public void TestMethod(byte[] input) { }" + - "}"); + "}"; - Assert.Empty(diagnostics); + await Verify.VerifyAnalyzerAsync(source); } } @@ -198,16 +200,11 @@ public class ForAttributeWithTooFewArguments : InlineDataMustMatchTheoryParamete [Fact] public async void FindsError() { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, - "public class TestClass { [Xunit.Theory, Xunit.InlineData(1)] public void TestMethod(int a, int b, string c) { } }"); + var source = + "public class TestClass { [Xunit.Theory, Xunit.InlineData(1)] public void TestMethod(int a, int b, string c) { } }"; - Assert.Collection(diagnostics, - d => - { - Assert.Equal("InlineData values must match the number of method parameters", d.GetMessage()); - Assert.Equal("xUnit1009", d.Descriptor.Id); - Assert.Equal(DiagnosticSeverity.Error, d.Severity); - }); + var expected = Verify.Diagnostic("xUnit1009").WithSpan(1, 41, 1, 60).WithSeverity(DiagnosticSeverity.Error); + await Verify.VerifyAnalyzerAsync(source, expected); } [Theory] @@ -215,34 +212,24 @@ public async void FindsError() [InlineData("Xunit.InlineData")] public async void FindsError_ForAttributeWithNoArguments(string attribute) { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = "public class TestClass {" + $" [Xunit.Theory, {attribute}]" + " public void TestMethod(int a) { }" + - "}"); + "}"; - Assert.Collection(diagnostics, - d => - { - Assert.Equal("InlineData values must match the number of method parameters", d.GetMessage()); - Assert.Equal("xUnit1009", d.Descriptor.Id); - Assert.Equal(DiagnosticSeverity.Error, d.Severity); - }); + var expected = Verify.Diagnostic("xUnit1009").WithSpan(1, 42, 1, 42 + attribute.Length).WithSeverity(DiagnosticSeverity.Error); + await Verify.VerifyAnalyzerAsync(source, expected); } [Fact] public async void FindsError_UsingParams() { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, - "public class TestClass { [Xunit.Theory, Xunit.InlineData(1)] public void TestMethod(int a, int b, params string[] value) { } }"); + var source = + "public class TestClass { [Xunit.Theory, Xunit.InlineData(1)] public void TestMethod(int a, int b, params string[] value) { } }"; - Assert.Collection(diagnostics, - d => - { - Assert.Equal("InlineData values must match the number of method parameters", d.GetMessage()); - Assert.Equal("xUnit1009", d.Descriptor.Id); - Assert.Equal(DiagnosticSeverity.Error, d.Severity); - }); + var expected = Verify.Diagnostic("xUnit1009").WithSpan(1, 41, 1, 60).WithSeverity(DiagnosticSeverity.Error); + await Verify.VerifyAnalyzerAsync(source, expected); } } @@ -251,22 +238,15 @@ public class ForAttributeWithTooManyArguments : InlineDataMustMatchTheoryParamet [Fact] public async void FindsError() { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, - "public class TestClass { [Xunit.Theory, Xunit.InlineData(1, 2, \"abc\")] public void TestMethod(int a) { } }"); - - Assert.Collection(diagnostics, - d => - { - Assert.Equal("There is no matching method parameter for value: 2.", d.GetMessage()); - Assert.Equal("xUnit1011", d.Descriptor.Id); - Assert.Equal(DiagnosticSeverity.Error, d.Severity); - }, - d => - { - Assert.Equal("There is no matching method parameter for value: \"abc\".", d.GetMessage()); - Assert.Equal("xUnit1011", d.Descriptor.Id); - Assert.Equal(DiagnosticSeverity.Error, d.Severity); - }); + var source = + "public class TestClass { [Xunit.Theory, Xunit.InlineData(1, 2, \"abc\")] public void TestMethod(int a) { } }"; + + DiagnosticResult[] expected = + { + Verify.Diagnostic("xUnit1011").WithSpan(1, 61, 1, 62).WithSeverity(DiagnosticSeverity.Error).WithArguments("2"), + Verify.Diagnostic("xUnit1011").WithSpan(1, 64, 1, 69).WithSeverity(DiagnosticSeverity.Error).WithArguments("\"abc\""), + }; + await Verify.VerifyAnalyzerAsync(source, expected); } } @@ -296,48 +276,36 @@ public class ForAttributeNullValue : InlineDataMustMatchTheoryParametersTests [InlineData("params int[]")] public async void FindsWarning_ForSingleNullValue(string type) { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, - "public class TestClass { [Xunit.Theory, Xunit.InlineData(null)] public void TestMethod(" + type + " a) { } }"); + var source = + "public class TestClass { [Xunit.Theory, Xunit.InlineData(null)] public void TestMethod(" + type + " a) { } }"; - Assert.Collection(diagnostics, - d => - { - Assert.Equal("Null should not be used for value type parameter 'a' of type 'int'.", d.GetMessage()); - Assert.Equal("xUnit1012", d.Descriptor.Id); - Assert.Equal(DiagnosticSeverity.Warning, d.Severity); - }); + var expected = Verify.Diagnostic("xUnit1012").WithSpan(1, 58, 1, 62).WithSeverity(DiagnosticSeverity.Warning).WithArguments("a", "int"); + await Verify.VerifyAnalyzerAsync(source, expected); } [Theory] [MemberData(nameof(ValueTypes))] public async void FindsWarning_ForValueTypeParameter(string type) { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, - "public class TestClass { [Xunit.Theory, Xunit.InlineData(1, null, null)] public void TestMethod(int a, " + type + " b, params " + type + "[] c) { } }"); + var source = + "public class TestClass { [Xunit.Theory, Xunit.InlineData(1, null, null)] public void TestMethod(int a, " + type + " b, params " + type + "[] c) { } }"; - Assert.Collection(diagnostics, - d => - { - Assert.Equal("Null should not be used for value type parameter 'b' of type '" + type + "'.", d.GetMessage()); - Assert.Equal("xUnit1012", d.Descriptor.Id); - Assert.Equal(DiagnosticSeverity.Warning, d.Severity); - }, - d => - { - Assert.Equal("Null should not be used for value type parameter 'c' of type '" + type + "'.", d.GetMessage()); - Assert.Equal("xUnit1012", d.Descriptor.Id); - Assert.Equal(DiagnosticSeverity.Warning, d.Severity); - }); + DiagnosticResult[] expected = + { + Verify.Diagnostic("xUnit1012").WithSpan(1, 61, 1, 65).WithSeverity(DiagnosticSeverity.Warning).WithArguments("b", type), + Verify.Diagnostic("xUnit1012").WithSpan(1, 67, 1, 71).WithSeverity(DiagnosticSeverity.Warning).WithArguments("c", type), + }; + await Verify.VerifyAnalyzerAsync(source, expected); } [Theory] [MemberData(nameof(ValueTypes))] public async void DoesNotFindWarning_ForNullableValueType(string type) { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, - "public class TestClass { [Xunit.Theory, Xunit.InlineData(1, null)] public void TestMethod(int a, " + type + "? b) { } }"); + var source = + "public class TestClass { [Xunit.Theory, Xunit.InlineData(1, null)] public void TestMethod(int a, " + type + "? b) { } }"; - Assert.Empty(diagnostics); + await Verify.VerifyAnalyzerAsync(source); } [Theory] @@ -346,10 +314,10 @@ public async void DoesNotFindWarning_ForNullableValueType(string type) [InlineData("System.Exception")] public async void DoesNotFindWarning_ForReferenceParameterType(string type) { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, - "public class TestClass { [Xunit.Theory, Xunit.InlineData(1, null)] public void TestMethod(int a, " + type + " b) { } }"); + var source = + "public class TestClass { [Xunit.Theory, Xunit.InlineData(1, null)] public void TestMethod(int a, " + type + " b) { } }"; - Assert.Empty(diagnostics); + await Verify.VerifyAnalyzerAsync(source); } } @@ -369,61 +337,52 @@ from type in NumericTypes [TupleMemberData(nameof(NumericValuesAndNumericTypes))] public async void DoesNotFindError_FromAnyOtherNumericType(string value, string type) { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, - "public class TestClass { [Xunit.Theory, Xunit.InlineData(" + value + ")] public void TestMethod(" + type + " a) { } }"); + var source = + "public class TestClass { [Xunit.Theory, Xunit.InlineData(" + value + ")] public void TestMethod(" + type + " a) { } }"; - Assert.Empty(diagnostics); + await Verify.VerifyAnalyzerAsync(source); } [Theory] [TupleMemberData(nameof(NumericValuesAndNumericTypes))] public async void DoesNotFindError_FromAnyOtherNumericType_ToNullable(string value, string type) { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, - "public class TestClass { [Xunit.Theory, Xunit.InlineData(" + value + ")] public void TestMethod(" + type + "? a) { } }"); + var source = + "public class TestClass { [Xunit.Theory, Xunit.InlineData(" + value + ")] public void TestMethod(" + type + "? a) { } }"; - Assert.Empty(diagnostics); + await Verify.VerifyAnalyzerAsync(source); } [Theory] [TupleMemberData(nameof(BoolValuesAndNumericTypes))] public async void FindsError_ForBoolArgument(string value, string type) { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, - "public class TestClass { [Xunit.Theory, Xunit.InlineData(" + value + ")] public void TestMethod(" + type + " a) { } }"); + var source = + "public class TestClass { [Xunit.Theory, Xunit.InlineData(" + value + ")] public void TestMethod(" + type + " a) { } }"; - Assert.Collection(diagnostics, - d => - { - Assert.Equal("The value is not convertible to the method parameter 'a' of type '" + type + "'.", d.GetMessage()); - Assert.Equal("xUnit1010", d.Descriptor.Id); - }); + var expected = Verify.Diagnostic("xUnit1010").WithSpan(1, 58, 1, 58 + value.Length).WithArguments("a", type); + await Verify.VerifyAnalyzerAsync(source, expected); } [Theory] [TupleMemberData(nameof(NumericTypes))] public async void DoesNotFindError_ForCharArgument(string type) { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, - "public class TestClass { [Xunit.Theory, Xunit.InlineData('a')] public void TestMethod(" + type + " a) { } }"); + var source = + "public class TestClass { [Xunit.Theory, Xunit.InlineData('a')] public void TestMethod(" + type + " a) { } }"; - Assert.Empty(diagnostics); + await Verify.VerifyAnalyzerAsync(source); } [Theory] [TupleMemberData(nameof(NumericTypes))] public async void FindsError_ForEnumArgument(string type) { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, - "public class TestClass { [Xunit.Theory, Xunit.InlineData(System.StringComparison.InvariantCulture)] public void TestMethod(" + type + " a) { } }"); + var source = + "public class TestClass { [Xunit.Theory, Xunit.InlineData(System.StringComparison.InvariantCulture)] public void TestMethod(" + type + " a) { } }"; - - Assert.Collection(diagnostics, - d => - { - Assert.Equal("The value is not convertible to the method parameter 'a' of type '" + type + "'.", d.GetMessage()); - Assert.Equal("xUnit1010", d.Descriptor.Id); - }); + var expected = Verify.Diagnostic("xUnit1010").WithSpan(1, 58, 1, 98).WithArguments("a", type); + await Verify.VerifyAnalyzerAsync(source, expected); } } @@ -433,20 +392,20 @@ public class ForConversionToBoolValue : InlineDataMustMatchTheoryParametersTests [TupleMemberData(nameof(BoolValues))] public async void DoesNotFindError_FromBoolType(string value) { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, - "public class TestClass { [Xunit.Theory, Xunit.InlineData(" + value + ")] public void TestMethod(bool a) { } }"); + var source = + "public class TestClass { [Xunit.Theory, Xunit.InlineData(" + value + ")] public void TestMethod(bool a) { } }"; - Assert.Empty(diagnostics); + await Verify.VerifyAnalyzerAsync(source); } [Theory] [TupleMemberData(nameof(BoolValues))] public async void DoesNotFindError_FromBoolType_ToNullable(string value) { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, - "public class TestClass { [Xunit.Theory, Xunit.InlineData(" + value + ")] public void TestMethod(bool? a) { } }"); + var source = + "public class TestClass { [Xunit.Theory, Xunit.InlineData(" + value + ")] public void TestMethod(bool? a) { } }"; - Assert.Empty(diagnostics); + await Verify.VerifyAnalyzerAsync(source); } [Theory] @@ -457,15 +416,11 @@ public async void DoesNotFindError_FromBoolType_ToNullable(string value) [InlineData("typeof(string)")] public async void FindsError_ForOtherArguments(string value) { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, - "public class TestClass { [Xunit.Theory, Xunit.InlineData(" + value + ")] public void TestMethod(bool a) { } }"); + var source = + "public class TestClass { [Xunit.Theory, Xunit.InlineData(" + value + ")] public void TestMethod(bool a) { } }"; - Assert.Collection(diagnostics, - d => - { - Assert.Equal("The value is not convertible to the method parameter 'a' of type 'bool'.", d.GetMessage()); - Assert.Equal("xUnit1010", d.Descriptor.Id); - }); + var expected = Verify.Diagnostic("xUnit1010").WithSpan(1, 58, 1, 58 + value.Length).WithArguments("a", "bool"); + await Verify.VerifyAnalyzerAsync(source, expected); } } @@ -476,10 +431,10 @@ public class ForConversionToCharValue : InlineDataMustMatchTheoryParametersTests [TupleMemberData(nameof(IntegerValues))] public async void DoesNotFindError_FromCharOrIntegerType(string value) { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, - "public class TestClass { [Xunit.Theory, Xunit.InlineData(" + value + ")] public void TestMethod(char a) { } }"); + var source = + "public class TestClass { [Xunit.Theory, Xunit.InlineData(" + value + ")] public void TestMethod(char a) { } }"; - Assert.Empty(diagnostics); + await Verify.VerifyAnalyzerAsync(source); } [Theory] @@ -487,10 +442,10 @@ public async void DoesNotFindError_FromCharOrIntegerType(string value) [TupleMemberData(nameof(IntegerValues))] public async void DoesNotFindError_FromCharType_ToNullable(string value) { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, - "public class TestClass { [Xunit.Theory, Xunit.InlineData(" + value + ")] public void TestMethod(char? a) { } }"); + var source = + "public class TestClass { [Xunit.Theory, Xunit.InlineData(" + value + ")] public void TestMethod(char? a) { } }"; - Assert.Empty(diagnostics); + await Verify.VerifyAnalyzerAsync(source); } [Theory] @@ -501,15 +456,11 @@ public async void DoesNotFindError_FromCharType_ToNullable(string value) [InlineData("typeof(string)")] public async void FindsError_ForOtherArguments(string value) { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, - "public class TestClass { [Xunit.Theory, Xunit.InlineData(" + value + ")] public void TestMethod(char a) { } }"); + var source = + "public class TestClass { [Xunit.Theory, Xunit.InlineData(" + value + ")] public void TestMethod(char a) { } }"; - Assert.Collection(diagnostics, - d => - { - Assert.Equal("The value is not convertible to the method parameter 'a' of type 'char'.", d.GetMessage()); - Assert.Equal("xUnit1010", d.Descriptor.Id); - }); + var expected = Verify.Diagnostic("xUnit1010").WithSpan(1, 58, 1, 58 + value.Length).WithArguments("a", "char"); + await Verify.VerifyAnalyzerAsync(source, expected); } } @@ -518,19 +469,19 @@ public class ForConversionToEnum : InlineDataMustMatchTheoryParametersTests [Fact] public async void DoesNotFindError_FromEnum() { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, - "public class TestClass { [Xunit.Theory, Xunit.InlineData(System.StringComparison.Ordinal)] public void TestMethod(System.StringComparison a) { } }"); + var source = + "public class TestClass { [Xunit.Theory, Xunit.InlineData(System.StringComparison.Ordinal)] public void TestMethod(System.StringComparison a) { } }"; - Assert.Empty(diagnostics); + await Verify.VerifyAnalyzerAsync(source); } [Fact] public async void DoesNotFindError_FromEnum_ToNullable() { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, - "public class TestClass { [Xunit.Theory, Xunit.InlineData(System.StringComparison.Ordinal)] public void TestMethod(System.StringComparison? a) { } }"); + var source = + "public class TestClass { [Xunit.Theory, Xunit.InlineData(System.StringComparison.Ordinal)] public void TestMethod(System.StringComparison? a) { } }"; - Assert.Empty(diagnostics); + await Verify.VerifyAnalyzerAsync(source); } [Theory] @@ -541,15 +492,11 @@ public async void DoesNotFindError_FromEnum_ToNullable() [InlineData("typeof(string)")] public async void FindsError_ForOtherArguments(string value) { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, - "public class TestClass { [Xunit.Theory, Xunit.InlineData(" + value + ")] public void TestMethod(System.StringComparison a) { } }"); + var source = + "public class TestClass { [Xunit.Theory, Xunit.InlineData(" + value + ")] public void TestMethod(System.StringComparison a) { } }"; - Assert.Collection(diagnostics, - d => - { - Assert.Equal("The value is not convertible to the method parameter 'a' of type 'System.StringComparison'.", d.GetMessage()); - Assert.Equal("xUnit1010", d.Descriptor.Id); - }); + var expected = Verify.Diagnostic("xUnit1010").WithSpan(1, 58, 1, 58 + value.Length).WithArguments("a", "System.StringComparison"); + await Verify.VerifyAnalyzerAsync(source, expected); } } @@ -560,10 +507,10 @@ public class ForConversionToType : InlineDataMustMatchTheoryParametersTests [InlineData("null")] public async void DoesNotFindError_FromType(string value) { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, - "public class TestClass { [Xunit.Theory, Xunit.InlineData(" + value + ")] public void TestMethod(System.Type a) { } }"); + var source = + "public class TestClass { [Xunit.Theory, Xunit.InlineData(" + value + ")] public void TestMethod(System.Type a) { } }"; - Assert.Empty(diagnostics); + await Verify.VerifyAnalyzerAsync(source); } [Theory] @@ -571,10 +518,10 @@ public async void DoesNotFindError_FromType(string value) [InlineData("null")] public async void DoesNotFindError_FromType_UsingParams(string value) { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, - "public class TestClass { [Xunit.Theory, Xunit.InlineData(" + value + ")] public void TestMethod(params System.Type[] a) { } }"); + var source = + "public class TestClass { [Xunit.Theory, Xunit.InlineData(" + value + ")] public void TestMethod(params System.Type[] a) { } }"; - Assert.Empty(diagnostics); + await Verify.VerifyAnalyzerAsync(source); } [Theory] @@ -585,15 +532,11 @@ public async void DoesNotFindError_FromType_UsingParams(string value) [InlineData("System.StringComparison.Ordinal")] public async void FindsError_ForOtherArguments(string value) { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, - "public class TestClass { [Xunit.Theory, Xunit.InlineData(" + value + ")] public void TestMethod(System.Type a) { } }"); + var source = + "public class TestClass { [Xunit.Theory, Xunit.InlineData(" + value + ")] public void TestMethod(System.Type a) { } }"; - Assert.Collection(diagnostics, - d => - { - Assert.Equal("The value is not convertible to the method parameter 'a' of type 'System.Type'.", d.GetMessage()); - Assert.Equal("xUnit1010", d.Descriptor.Id); - }); + var expected = Verify.Diagnostic("xUnit1010").WithSpan(1, 58, 1, 58 + value.Length).WithArguments("a", "System.Type"); + await Verify.VerifyAnalyzerAsync(source, expected); } [Theory] @@ -604,15 +547,11 @@ public async void FindsError_ForOtherArguments(string value) [InlineData("System.StringComparison.Ordinal")] public async void FindsError_ForOtherArguments_UsingParams(string value) { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, - "public class TestClass { [Xunit.Theory, Xunit.InlineData(" + value + ")] public void TestMethod(params System.Type[] a) { } }"); + var source = + "public class TestClass { [Xunit.Theory, Xunit.InlineData(" + value + ")] public void TestMethod(params System.Type[] a) { } }"; - Assert.Collection(diagnostics, - d => - { - Assert.Equal("The value is not convertible to the method parameter 'a' of type 'System.Type'.", d.GetMessage()); - Assert.Equal("xUnit1010", d.Descriptor.Id); - }); + var expected = Verify.Diagnostic("xUnit1010").WithSpan(1, 58, 1, 58 + value.Length).WithArguments("a", "System.Type"); + await Verify.VerifyAnalyzerAsync(source, expected); } } @@ -623,10 +562,10 @@ public class ForConversionToString : InlineDataMustMatchTheoryParametersTests [InlineData("null")] public async void DoesNotFindError_FromBoolType(string value) { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, - "public class TestClass { [Xunit.Theory, Xunit.InlineData(" + value + ")] public void TestMethod(string a) { } }"); + var source = + "public class TestClass { [Xunit.Theory, Xunit.InlineData(" + value + ")] public void TestMethod(string a) { } }"; - Assert.Empty(diagnostics); + await Verify.VerifyAnalyzerAsync(source); } [Theory] @@ -637,15 +576,11 @@ public async void DoesNotFindError_FromBoolType(string value) [InlineData("typeof(string)")] public async void FindsError_ForOtherArguments(string value) { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, - "public class TestClass { [Xunit.Theory, Xunit.InlineData(" + value + ")] public void TestMethod(string a) { } }"); + var source = + "public class TestClass { [Xunit.Theory, Xunit.InlineData(" + value + ")] public void TestMethod(string a) { } }"; - Assert.Collection(diagnostics, - d => - { - Assert.Equal("The value is not convertible to the method parameter 'a' of type 'string'.", d.GetMessage()); - Assert.Equal("xUnit1010", d.Descriptor.Id); - }); + var expected = Verify.Diagnostic("xUnit1010").WithSpan(1, 58, 1, 58 + value.Length).WithArguments("a", "string"); + await Verify.VerifyAnalyzerAsync(source, expected); } } @@ -657,10 +592,10 @@ public class ForConversionToInterface : InlineDataMustMatchTheoryParametersTests [InlineData("null")] public async void DoesNotFindError_FromTypesImplementingInterface(string value) { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, - "public class TestClass { [Xunit.Theory, Xunit.InlineData(" + value + ")] public void TestMethod(System.IFormattable a) { } }"); + var source = + "public class TestClass { [Xunit.Theory, Xunit.InlineData(" + value + ")] public void TestMethod(System.IFormattable a) { } }"; - Assert.Empty(diagnostics); + await Verify.VerifyAnalyzerAsync(source); } [Theory] @@ -670,15 +605,11 @@ public async void DoesNotFindError_FromTypesImplementingInterface(string value) [InlineData("typeof(string)")] public async void FindsError_ForOtherArguments(string value) { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, - "public class TestClass { [Xunit.Theory, Xunit.InlineData(" + value + ")] public void TestMethod(System.IFormattable a) { } }"); + var source = + "public class TestClass { [Xunit.Theory, Xunit.InlineData(" + value + ")] public void TestMethod(System.IFormattable a) { } }"; - Assert.Collection(diagnostics, - d => - { - Assert.Equal("The value is not convertible to the method parameter 'a' of type 'System.IFormattable'.", d.GetMessage()); - Assert.Equal("xUnit1010", d.Descriptor.Id); - }); + var expected = Verify.Diagnostic("xUnit1010").WithSpan(1, 58, 1, 58 + value.Length).WithArguments("a", "System.IFormattable"); + await Verify.VerifyAnalyzerAsync(source, expected); } } @@ -694,10 +625,10 @@ public class ForConversionToObject : InlineDataMustMatchTheoryParametersTests [InlineData("typeof(string)")] public async void DoesNotFindError_FromAnyValue(string value) { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, - "public class TestClass { [Xunit.Theory, Xunit.InlineData(" + value + ")] public void TestMethod(object a) { } }"); + var source = + "public class TestClass { [Xunit.Theory, Xunit.InlineData(" + value + ")] public void TestMethod(object a) { } }"; - Assert.Empty(diagnostics); + await Verify.VerifyAnalyzerAsync(source); } [Theory] @@ -710,10 +641,10 @@ public async void DoesNotFindError_FromAnyValue(string value) [InlineData("typeof(string)")] public async void DoesNotFindError_FromAnyValues_UsingParams(string value) { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, - "public class TestClass { [Xunit.Theory, Xunit.InlineData(" + value + ")] public void TestMethod(params object[] a) { } }"); + var source = + "public class TestClass { [Xunit.Theory, Xunit.InlineData(" + value + ")] public void TestMethod(params object[] a) { } }"; - Assert.Empty(diagnostics); + await Verify.VerifyAnalyzerAsync(source); } } @@ -729,10 +660,10 @@ public class ForConversionToGeneric : InlineDataMustMatchTheoryParametersTests [InlineData("typeof(string)")] public async void DoesNotFindError_FromAnyValue_WithNoConstraint(string value) { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, - "public class TestClass { [Xunit.Theory, Xunit.InlineData(" + value + ")] public void TestMethod(T a) { } }"); + var source = + "public class TestClass { [Xunit.Theory, Xunit.InlineData(" + value + ")] public void TestMethod(T a) { } }"; - Assert.Empty(diagnostics); + await Verify.VerifyAnalyzerAsync(source); } [Theory] @@ -742,10 +673,10 @@ public async void DoesNotFindError_FromAnyValue_WithNoConstraint(string value) [InlineData("'a'")] public async void DoesNotFindError_FromAnyValueType_WithStructConstraint(string value) { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, - "public class TestClass { [Xunit.Theory, Xunit.InlineData(" + value + ")] public void TestMethod(T a) where T: struct { } }"); + var source = + "public class TestClass { [Xunit.Theory, Xunit.InlineData(" + value + ")] public void TestMethod(T a) where T: struct { } }"; - Assert.Empty(diagnostics); + await Verify.VerifyAnalyzerAsync(source); } [Theory] @@ -753,15 +684,11 @@ public async void DoesNotFindError_FromAnyValueType_WithStructConstraint(string [InlineData("typeof(string)")] public async void FindsError_FromAnyReferenceType_WithStructConstraint(string value) { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, - "public class TestClass { [Xunit.Theory, Xunit.InlineData(" + value + ")] public void TestMethod(T a) where T: struct { } }"); + var source = + "public class TestClass { [Xunit.Theory, Xunit.InlineData(" + value + ")] public void TestMethod(T a) where T: struct { } }"; - Assert.Collection(diagnostics, - d => - { - Assert.Equal("The value is not convertible to the method parameter 'a' of type 'T'.", d.GetMessage()); - Assert.Equal("xUnit1010", d.Descriptor.Id); - }); + var expected = Verify.Diagnostic("xUnit1010").WithSpan(1, 58, 1, 58 + value.Length).WithArguments("a", "T"); + await Verify.VerifyAnalyzerAsync(source, expected); } [Theory] @@ -770,10 +697,10 @@ public async void FindsError_FromAnyReferenceType_WithStructConstraint(string va [InlineData("null")] public async void DoesNotFindError_FromAnyReferenceType_WithClassConstraint(string value) { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, - "public class TestClass { [Xunit.Theory, Xunit.InlineData(" + value + ")] public void TestMethod(T a) where T: class { } }"); + var source = + "public class TestClass { [Xunit.Theory, Xunit.InlineData(" + value + ")] public void TestMethod(T a) where T: class { } }"; - Assert.Empty(diagnostics); + await Verify.VerifyAnalyzerAsync(source); } [Theory] @@ -783,15 +710,11 @@ public async void DoesNotFindError_FromAnyReferenceType_WithClassConstraint(stri [InlineData("'a'")] public async void FindsError_FromAnyValueType_WithClassConstraint(string value) { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, - "public class TestClass { [Xunit.Theory, Xunit.InlineData(" + value + ")] public void TestMethod(T a) where T: class { } }"); + var source = + "public class TestClass { [Xunit.Theory, Xunit.InlineData(" + value + ")] public void TestMethod(T a) where T: class { } }"; - Assert.Collection(diagnostics, - d => - { - Assert.Equal("The value is not convertible to the method parameter 'a' of type 'T'.", d.GetMessage()); - Assert.Equal("xUnit1010", d.Descriptor.Id); - }); + var expected = Verify.Diagnostic("xUnit1010").WithSpan(1, 58, 1, 58 + value.Length).WithArguments("a", "T"); + await Verify.VerifyAnalyzerAsync(source, expected); } [Theory] @@ -800,29 +723,34 @@ public async void FindsError_FromAnyValueType_WithClassConstraint(string value) [TupleMemberData(nameof(NumericValues))] public async void DoesNotFindError_FromAnyMatchingType_WithTypeConstraint(string value) { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, - "public class TestClass { [Xunit.Theory, Xunit.InlineData(" + value + ")] public void TestMethod(T a) where T: System.IConvertible, System.IFormattable { } }"); + var source = + "public class TestClass { [Xunit.Theory, Xunit.InlineData(" + value + ")] public void TestMethod(T a) where T: System.IConvertible, System.IFormattable { } }"; - Assert.Empty(diagnostics); + await Verify.VerifyAnalyzerAsync(source); } [Theory] [InlineData("typeof(string)")] - [InlineData("new int[] { 1, 2, 3 }")] [InlineData("'a'")] [InlineData("\"abc\"")] [TupleMemberData(nameof(BoolValues))] public async void FindsError_FromNonMatchingType_WithTypeConstraint(string value) { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, - "public class TestClass { [Xunit.Theory, Xunit.InlineData(" + value + ")] public void TestMethod(T a) where T: System.IConvertible, System.IFormattable { } }"); + var source = + "public class TestClass { [Xunit.Theory, Xunit.InlineData(" + value + ")] public void TestMethod(T a) where T: System.IConvertible, System.IFormattable { } }"; + + var expected = Verify.Diagnostic("xUnit1010").WithSpan(1, 58, 1, 58 + value.Length).WithArguments("a", "T"); + await Verify.VerifyAnalyzerAsync(source, expected); + } + + [Fact] + public async void FindsError_FromNonMatchingArrayType_WithTypeConstraint() + { + var source = + "public class TestClass { [Xunit.Theory, Xunit.InlineData(new int[] { 1, 2, 3 })] public void TestMethod(T a) where T: System.IConvertible, System.IFormattable { } }"; - Assert.Collection(diagnostics, - d => - { - Assert.Equal("The value is not convertible to the method parameter 'a' of type 'T'.", d.GetMessage()); - Assert.Equal("xUnit1010", d.Descriptor.Id); - }); + var expected = Verify.Diagnostic("xUnit1010").WithSpan(1, 70, 1, 71).WithArguments("a", "T"); + await Verify.VerifyAnalyzerAsync(source, expected); } } @@ -865,15 +793,9 @@ public void TestMethod(" + parameterType + @" parameter) { } }"; - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, source); - Assert.Collection(diagnostics, - d => - { - Assert.Equal("The value is not convertible to the method parameter 'parameter' " + - $"of type '{parameterType}'.", d.GetMessage()); - Assert.Equal("xUnit1010", d.Descriptor.Id); - }); + var expected = Verify.Diagnostic("xUnit1010").WithSpan(6, 37, 6, 37 + inlineData.Length).WithArguments("parameter", parameterType); + await Verify.VerifyAnalyzerAsync(source, expected); } [Theory] @@ -881,9 +803,8 @@ public void TestMethod(" + parameterType + @" parameter) public async void DoesNotFindError_ForDateTime_FromString(string inlineData, string parameterType) { var source = CreateSourceWithStringConst(inlineData, parameterType); - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, source); - Assert.Empty(diagnostics); + await Verify.VerifyAnalyzerAsync(source); } [Theory] @@ -891,16 +812,9 @@ public async void DoesNotFindError_ForDateTime_FromString(string inlineData, str public async void FindsError_ForDateTimeOffsetAndAnalyzerLessThan_2_4_0v_FromString(string inlineData, string parameterType) { var source = CreateSourceWithStringConst(inlineData, parameterType); - var diagnosticAnalyzer = new InlineDataMustMatchTheoryParameters("2.3.1"); - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(diagnosticAnalyzer, source); - Assert.Collection(diagnostics, - d => - { - Assert.Equal("The value is not convertible to the method parameter 'parameter' " + - $"of type '{parameterType}'.", d.GetMessage()); - Assert.Equal("xUnit1010", d.Descriptor.Id); - }); + var expected = Verify_2_3_1.Diagnostic("xUnit1010").WithSpan(6, 37, 6, 37 + inlineData.Length).WithArguments("parameter", parameterType); + await Verify_2_3_1.VerifyAnalyzerAsync(source, expected); } [Theory] @@ -908,10 +822,8 @@ public async void FindsError_ForDateTimeOffsetAndAnalyzerLessThan_2_4_0v_FromStr public async void DoesNotFindError_ForDateTimeOffsetAndForAnalyzerGreaterThanEqual_2_4_0v_FromString(string inlineData, string parameterType) { var source = CreateSourceWithStringConst(inlineData, parameterType); - var diagnosticAnalyzer = new InlineDataMustMatchTheoryParameters("2.4.0"); - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(diagnosticAnalyzer, source); - Assert.Empty(diagnostics); + await Verify_2_4.VerifyAnalyzerAsync(source); } private static string CreateSourceWithStringConst(string inlineData, string parameterType) @@ -956,15 +868,9 @@ public void TestMethod(System.Guid parameter) { } }"; - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, source); - Assert.Collection(diagnostics, - d => - { - Assert.Equal("The value is not convertible to the method parameter 'parameter' " + - "of type 'System.Guid'.", d.GetMessage()); - Assert.Equal("xUnit1010", d.Descriptor.Id); - }); + var expected = Verify.Diagnostic("xUnit1010").WithSpan(6, 37, 6, 37 + inlineData.Length).WithArguments("parameter", "System.Guid"); + await Verify.VerifyAnalyzerAsync(source, expected); } [Theory] @@ -973,16 +879,8 @@ public async void FindsError__ForAnalyzerLessThan_2_4_0v_FromString(string inlin { var source = CreateSource(inlineData); - var diagnosticAnalyzer = new InlineDataMustMatchTheoryParameters("2.3.99"); - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(diagnosticAnalyzer, source); - - Assert.Collection(diagnostics, - d => - { - Assert.Equal("The value is not convertible to the method parameter 'parameter' " + - "of type 'System.Guid'.", d.GetMessage()); - Assert.Equal("xUnit1010", d.Descriptor.Id); - }); + var expected = Verify_2_3_1.Diagnostic("xUnit1010").WithSpan(4, 37, 4, 37 + inlineData.Length).WithArguments("parameter", "System.Guid"); + await Verify_2_3_1.VerifyAnalyzerAsync(source, expected); } [Theory] @@ -991,10 +889,7 @@ public async void DoesNotFindError_ForAnalyzerGreaterThanEqual_2_4_0v_FromString { var source = CreateSource(inlineData); - var diagnosticAnalyzer = new InlineDataMustMatchTheoryParameters("2.4.0"); - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(diagnosticAnalyzer, source); - - Assert.Empty(diagnostics); + await Verify_2_5.VerifyAnalyzerAsync(source); } private static string CreateSource(string inlineData) @@ -1020,5 +915,29 @@ public void TestMethod(System.Guid parameter) public static IEnumerable> BoolValues { get; } = new[] { "true", "false" }.Select(v => Tuple.Create(v)).ToArray(); public static IEnumerable> ValueTypedValues { get; } = NumericValues.Concat(BoolValues).Concat(new [] {"typeof(int)"}.Select(v => Tuple.Create(v))); + + internal class Analyzer_2_3_1 : InlineDataMustMatchTheoryParameters + { + public Analyzer_2_3_1() + : base("2.3.1") + { + } + } + + internal class Analyzer_2_4_0 : InlineDataMustMatchTheoryParameters + { + public Analyzer_2_4_0() + : base("2.4.0") + { + } + } + + internal class Analyzer_2_5_0 : InlineDataMustMatchTheoryParameters + { + public Analyzer_2_5_0() + : base("2.5.0") + { + } + } } } diff --git a/test/xunit.analyzers.tests/InlineDataShouldBeUniqueWithinTheoryTests.cs b/test/xunit.analyzers.tests/InlineDataShouldBeUniqueWithinTheoryTests.cs index cc3989a2..597eaefc 100644 --- a/test/xunit.analyzers.tests/InlineDataShouldBeUniqueWithinTheoryTests.cs +++ b/test/xunit.analyzers.tests/InlineDataShouldBeUniqueWithinTheoryTests.cs @@ -1,22 +1,21 @@ using System; using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.Diagnostics; +using Microsoft.CodeAnalysis.Testing; +using Verify = Xunit.Analyzers.CSharpVerifier; namespace Xunit.Analyzers { public abstract class InlineDataShouldBeUniqueWithinTheoryTests { - readonly DiagnosticAnalyzer analyzer = new InlineDataShouldBeUniqueWithinTheory(); - public class ForNonRelatedToInlineDataMethod : InlineDataShouldBeUniqueWithinTheoryTests { [Fact] public async void DoesNotFindError_WhenNoDataAttributes() { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, - "public class TestClass { [Xunit.Fact] public void TestMethod() { } }"); + var source = + "public class TestClass { [Xunit.Fact] public void TestMethod() { } }"; - Assert.Empty(diagnostics); + await Verify.VerifyAnalyzerAsync(source); } [Theory] @@ -25,13 +24,13 @@ public async void DoesNotFindError_WhenNoDataAttributes() public async void DoesNotFindError_WhenDataAttributesOtherThanInline( string dataAttribute) { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = "public class TestClass " + "{" + " [Xunit.Theory, Xunit." + dataAttribute + "] public void TestMethod() { } " + - "}"); + "}"; - Assert.Empty(diagnostics); + await Verify.VerifyAnalyzerAsync(source); } } @@ -40,66 +39,66 @@ public class ForUniqueInlineDataMethod : InlineDataShouldBeUniqueWithinTheoryTes [Fact] public async void DoesNotFindError_WhenNonTheorySingleInlineData() { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = "public class TestClass " + "{" + " [Xunit.Fact, Xunit.InlineData]" + " public void TestMethod(int x) { } " + - "}"); + "}"; - Assert.Empty(diagnostics); + await Verify.VerifyAnalyzerAsync(source); } [Fact] public async void DoesNotFindError_WhenNonTheoryDoubledInlineData() { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = "public class TestClass " + "{" + " [Xunit.Fact, Xunit.InlineData, Xunit.InlineData]" + " public void TestMethod(int x) { } " + - "}"); + "}"; - Assert.Empty(diagnostics); + await Verify.VerifyAnalyzerAsync(source); } [Fact] public async void DoesNotFindError_WhenSingleInlineDataContainingValue() { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = "public class TestClass " + "{" + " [Xunit.Theory, Xunit.InlineData(10)]" + " public void TestMethod(int x) { } " + - "}"); + "}"; - Assert.Empty(diagnostics); + await Verify.VerifyAnalyzerAsync(source); } [Fact] public async void DoesNotFindError_WhenInlineDataAttributesHaveDifferentParameterValues() { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = "public class TestClass " + "{" + " [Xunit.Theory, Xunit.InlineData(10), Xunit.InlineData(20)]" + " public void TestMethod(int x) { } " + - "}"); + "}"; - Assert.Empty(diagnostics); + await Verify.VerifyAnalyzerAsync(source); } [Fact] public async void DoesNotFindError_WhenInlineDataAttributesDifferAtLastParameterValue() { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = "public class TestClass " + "{ " + " [Xunit.Theory, Xunit.InlineData(10, \"foo\"), Xunit.InlineData(10, \"bar\")]" + " public void TestMethod(int x, string y) { }" + - "}"); + "}"; - Assert.Empty(diagnostics); + await Verify.VerifyAnalyzerAsync(source); } [Theory] @@ -109,40 +108,40 @@ public async void DoesNotFindError_WhenInlineDataAttributesDifferAtLastParameter [InlineData("data: new object[] { 1 }")] public async void DoesNotFindError_WhenUniquenessProvidedWithParamsInitializerValues(string secondInlineDataParams) { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = "public class TestClass " + "{ " + $" [Xunit.Theory, Xunit.InlineData(1, 2), Xunit.InlineData({secondInlineDataParams})]" + " public void TestMethod(params int[] args) { }" + - "}"); + "}"; - Assert.Empty(diagnostics); + await Verify.VerifyAnalyzerAsync(source); } [Fact] public async void DoesNotFindError_WhenUniquenessProvidedWithOverridingDefaultValues() { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = "public class TestClass " + "{ " + " [Xunit.Theory, Xunit.InlineData(1), Xunit.InlineData(1, \"non-default-val\")]" + " public void TestMethod(int x, string a = \"default-val\") { }" + - "}"); + "}"; - Assert.Empty(diagnostics); + await Verify.VerifyAnalyzerAsync(source); } [Fact] public async void DoesNotFindError_WhenNullAndEmptyInlineDataAttributes() { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = "public class TestClass " + "{ " + " [Xunit.Theory, Xunit.InlineData(null), Xunit.InlineData]" + " public void TestMethod(string s) { }" + - "}"); + "}"; - Assert.Empty(diagnostics); + await Verify.VerifyAnalyzerAsync(source); } } @@ -151,54 +150,58 @@ public class ForDuplicatedInlineDataMethod : InlineDataShouldBeUniqueWithinTheor [Fact] public async void FindsError_WhenEmptyInlineDataRepeatedTwice() { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = "public class TestClass " + "{" + " [Xunit.Theory, Xunit.InlineData, Xunit.InlineData]" + " public void TestMethod(int x) { }" + - "}"); + "}"; - Assert.Collection(diagnostics, VerifyDiagnostic); + var expected = Verify.Diagnostic().WithSpan(1, 61, 1, 77).WithSeverity(DiagnosticSeverity.Warning).WithArguments("TestMethod", "TestClass"); + await Verify.VerifyAnalyzerAsync(source, expected); } [Fact] public async void FindsError_WhenNullInlineDataRepeatedTwice() { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = "public class TestClass " + "{" + " [Xunit.Theory, Xunit.InlineData(null), Xunit.InlineData(null)]" + " public void TestMethod(string x) { }" + - "}"); + "}"; - Assert.Collection(diagnostics, VerifyDiagnostic); + var expected = Verify.Diagnostic().WithSpan(1, 67, 1, 89).WithSeverity(DiagnosticSeverity.Warning).WithArguments("TestMethod", "TestClass"); + await Verify.VerifyAnalyzerAsync(source, expected); } [Fact] public async void FindsError_WhenInlineDataAttributesHaveExactlySameDeclarations() { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = "public class TestClass " + "{" + " [Xunit.Theory, Xunit.InlineData(10), Xunit.InlineData(10)]" + " public void TestMethod(int x) { }" + - "}"); + "}"; - Assert.Collection(diagnostics, VerifyDiagnostic); + var expected = Verify.Diagnostic().WithSpan(1, 65, 1, 85).WithSeverity(DiagnosticSeverity.Warning).WithArguments("TestMethod", "TestClass"); + await Verify.VerifyAnalyzerAsync(source, expected); } [Fact] public async void FindsError_WhenInlineDataAttributesHaveSameCompilationTimeEvaluation() { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = "public class TestClass" + "{" + " private const int X = 10; " + " [Xunit.Theory, Xunit.InlineData(10), Xunit.InlineData(X)]" + " public void TestMethod(int x) { }" + - "}"); + "}"; - Assert.Collection(diagnostics, VerifyDiagnostic); + var expected = Verify.Diagnostic().WithSpan(1, 93, 1, 112).WithSeverity(DiagnosticSeverity.Warning).WithArguments("TestMethod", "TestClass"); + await Verify.VerifyAnalyzerAsync(source, expected); } [Theory] @@ -207,14 +210,15 @@ public async void FindsError_WhenInlineDataAttributesHaveSameCompilationTimeEval public async void FindsError_WhenInlineDataHaveSameParameterValuesButDeclaredArrayCollectionOfArguments( string secondInlineDataArguments) { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = "public class TestClass " + "{" + $" [Xunit.Theory, Xunit.InlineData(10, 20), Xunit.InlineData({secondInlineDataArguments})]" + " public void TestMethod(int x, int y) { } " + - "}"); + "}"; - Assert.Collection(diagnostics, VerifyDiagnostic); + var expected = Verify.Diagnostic().WithSpan(1, 69, 1, 87 + secondInlineDataArguments.Length).WithSeverity(DiagnosticSeverity.Warning).WithArguments("TestMethod", "TestClass"); + await Verify.VerifyAnalyzerAsync(source, expected); } [Theory] @@ -222,48 +226,51 @@ public async void FindsError_WhenInlineDataHaveSameParameterValuesButDeclaredArr [InlineData("data: new object[] { 10, 20 }")] public async void FindsError_WhenTestMethodIsDefinedWithParamsArrayOfArguments(string secondInlineDataArguments) { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = "public class TestClass" + "{" + $" [Xunit.Theory, Xunit.InlineData(10, 20), Xunit.InlineData({secondInlineDataArguments})]" + " public void TestMethod(params int[] args) { }" + - "}"); + "}"; - Assert.Collection(diagnostics, VerifyDiagnostic); + var expected = Verify.Diagnostic().WithSpan(1, 68, 1, 86 + secondInlineDataArguments.Length).WithSeverity(DiagnosticSeverity.Warning).WithArguments("TestMethod", "TestClass"); + await Verify.VerifyAnalyzerAsync(source, expected); } [Fact] public async void FindsError_WhenBothInlineDataHaveObjectArrayCollectionOfArguments() { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = "public class TestClass" + "{" + " [Xunit.Theory, Xunit.InlineData(new object[] {10, 20}), Xunit.InlineData(new object[] {10, 20})]" + " public void TestMethod(int x, int y) { }" + - "}"); + "}"; - Assert.Collection(diagnostics, VerifyDiagnostic); + var expected = Verify.Diagnostic().WithSpan(1, 83, 1, 122).WithSeverity(DiagnosticSeverity.Warning).WithArguments("TestMethod", "TestClass"); + await Verify.VerifyAnalyzerAsync(source, expected); } [Fact] public async void FindsError_WhenArgumentsAreArrayOfValues() { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = "public class TestClass" + "{" + " [Xunit.Theory]" + " [Xunit.InlineData(new object[] {10, new object[] { new object[] {20}, 30}})]" + " [Xunit.InlineData(new object[] {10, new object[] { new object[] {20}, 30}})]" + " public void TestMethod(object x, object y) { }" + - "}"); + "}"; - Assert.Collection(diagnostics, VerifyDiagnostic); + var expected = Verify.Diagnostic().WithSpan(1, 124, 1, 198).WithSeverity(DiagnosticSeverity.Warning).WithArguments("TestMethod", "TestClass"); + await Verify.VerifyAnalyzerAsync(source, expected); } [Fact] public async void FindsError_WhenArgumentsAreArrayOfValuesAndTestMethodOffersDefaultParameterValues() { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = "public class TestClass" + "{" + " [Xunit.Theory]" + @@ -272,23 +279,24 @@ public async void FindsError_WhenArgumentsAreArrayOfValuesAndTestMethodOffersDef " [Xunit.InlineData(new object[] {10, new object[] { new object[] {20}, 30}, 50})]" + Environment.NewLine + " [Xunit.InlineData(new object[] {10, new object[] { new object[] {90}, 30}, 40})]" + Environment.NewLine + " public void TestMethod(object x, object y, int z = 40) { }" + - "}"); + "}"; - Assert.Collection(diagnostics, VerifyDiagnostic); - Assert.Collection(diagnostics, d => Assert.Equal(1, d.Location.GetLineSpan().StartLinePosition.Line)); + var expected = Verify.Diagnostic().WithSpan(2, 5, 2, 79).WithSeverity(DiagnosticSeverity.Warning).WithArguments("TestMethod", "TestClass"); + await Verify.VerifyAnalyzerAsync(source, expected); } [Fact] public async void FindsError_WhenDuplicatedByDefaultValueOfParameter() { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = "public class TestClass" + "{" + " [Xunit.Theory, Xunit.InlineData(10, 1), Xunit.InlineData(10)]" + " public void TestMethod(int x, int y = 1) { }" + - "}"); + "}"; - Assert.Collection(diagnostics, VerifyDiagnostic); + var expected = Verify.Diagnostic().WithSpan(1, 67, 1, 87).WithSeverity(DiagnosticSeverity.Warning).WithArguments("TestMethod", "TestClass"); + await Verify.VerifyAnalyzerAsync(source, expected); } [Theory] @@ -298,27 +306,29 @@ public async void FindsError_WhenDuplicatedByDefaultValueOfParameter() [InlineData("", "")] public async void FindsError_WhenBothNullEntirelyOrBySingleDefaultParameterNullValue(string firstArg, string secondArg) { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = "public class TestClass " + "{" + $" [Xunit.Theory, Xunit.InlineData({firstArg}), Xunit.InlineData({secondArg})]" + " public void TestMethod(string x = null) { }" + - "}"); + "}"; - Assert.Collection(diagnostics, VerifyDiagnostic); + var expected = Verify.Diagnostic().WithSpan(1, 63 + firstArg.Length, 1, 81 + firstArg.Length + secondArg.Length).WithSeverity(DiagnosticSeverity.Warning).WithArguments("TestMethod", "TestClass"); + await Verify.VerifyAnalyzerAsync(source, expected); } [Fact] public async void FindsError_WhenDuplicateContainsNulls() { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = "public class TestClass" + "{" + " [Xunit.Theory, Xunit.InlineData(1, null), Xunit.InlineData(new object[] {1, null})]" + " public void TestMethod(object x, object y) { }" + - "}"); + "}"; - Assert.Collection(diagnostics, VerifyDiagnostic); + var expected = Verify.Diagnostic().WithSpan(1, 69, 1, 109).WithSeverity(DiagnosticSeverity.Warning).WithArguments("TestMethod", "TestClass"); + await Verify.VerifyAnalyzerAsync(source, expected); } [Theory] @@ -329,16 +339,17 @@ public async void FindsError_WhenDuplicateContainsNulls() public async void FindsError_WhenDuplicateContainsDefaultOfStruct(string firstDefaultOverride, string secondDefaultOverride) { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = "public class TestClass" + "{" + " [Xunit.Theory]" + $" [Xunit.InlineData(1 {firstDefaultOverride})]" + $" [Xunit.InlineData(1 {secondDefaultOverride})]" + " public void TestMethod(int x, System.DateTime date = default(System.DateTime)) { }" + - "}"); + "}"; - Assert.Collection(diagnostics, VerifyDiagnostic); + var expected = Verify.Diagnostic().WithSpan(1, 70 + firstDefaultOverride.Length, 1, 90 + firstDefaultOverride.Length + secondDefaultOverride.Length).WithSeverity(DiagnosticSeverity.Warning).WithArguments("TestMethod", "TestClass"); + await Verify.VerifyAnalyzerAsync(source, expected); } [Theory] @@ -349,37 +360,39 @@ public async void FindsError_WhenDuplicateContainsDefaultOfStruct(string firstDe public async void FindsError_WhenDuplicateContainsDefaultOfString(string firstDefaultOverride, string secondDefaultOverride) { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = "public class TestClass" + "{" + " [Xunit.Theory]" + $" [Xunit.InlineData(1 {firstDefaultOverride})]" + $" [Xunit.InlineData(1 {secondDefaultOverride})]" + " public void TestMethod(int x, string y = null) { }" + - "}"); + "}"; - Assert.Collection(diagnostics, VerifyDiagnostic); + var expected = Verify.Diagnostic().WithSpan(1, 70 + firstDefaultOverride.Length, 1, 90 + firstDefaultOverride.Length + secondDefaultOverride.Length).WithSeverity(DiagnosticSeverity.Warning).WithArguments("TestMethod", "TestClass"); + await Verify.VerifyAnalyzerAsync(source, expected); } [Fact] public async void FindsError_WhenInlineDataDuplicateAndOriginalAreItemsOfDistinctAttributesLists() { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = "public class TestClass" + "{" + " [Xunit.Theory]" + " [Xunit.InlineData(10, 20), Xunit.InlineData(30, 40)]" + Environment.NewLine + " [Xunit.InlineData(50, 60), Xunit.InlineData(10, 20)]" + " public void TestMethod(int x, int y) { } " + - "}"); + "}"; - Assert.Collection(diagnostics, VerifyDiagnostic); + var expected = Verify.Diagnostic().WithSpan(2, 31, 2, 55).WithSeverity(DiagnosticSeverity.Warning).WithArguments("TestMethod", "TestClass"); + await Verify.VerifyAnalyzerAsync(source, expected); } [Fact] public async void FindsErrorsTwiceOnCorrectLinesReferringToInitialOccurence_WhenThreeInlineDataAttributesConstituteDuplication() { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = "public class TestClass" + "{" + " [Xunit.Theory]" + @@ -387,18 +400,20 @@ public async void FindsErrorsTwiceOnCorrectLinesReferringToInitialOccurence_When " [Xunit.InlineData(10)]" + Environment.NewLine + " [Xunit.InlineData(10)]" + " public void TestMethod(int x) { } " + - "}"); - - Assert.All(diagnostics, VerifyDiagnostic); - Assert.Collection(diagnostics, - d => Assert.Equal(1, d.Location.GetLineSpan().StartLinePosition.Line), - d => Assert.Equal(2, d.Location.GetLineSpan().StartLinePosition.Line)); + "}"; + + DiagnosticResult[] expected = + { + Verify.Diagnostic().WithSpan(2, 5, 2, 25).WithSeverity(DiagnosticSeverity.Warning).WithArguments("TestMethod", "TestClass"), + Verify.Diagnostic().WithSpan(3, 5, 3, 25).WithSeverity(DiagnosticSeverity.Warning).WithArguments("TestMethod", "TestClass"), + }; + await Verify.VerifyAnalyzerAsync(source, expected); } [Fact] public async void FindsErrorOnCorrectLineReferringToInitialOccurence_WhenDuplicateIsSeparatedByOtherNonDuplicateData() { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = "public class TestClass" + "{" + " [Xunit.Theory]" + @@ -406,16 +421,16 @@ public async void FindsErrorOnCorrectLineReferringToInitialOccurence_WhenDuplica " [Xunit.InlineData(50)]" + Environment.NewLine + " [Xunit.InlineData(10)]" + " public void TestMethod(int x) { } " + - "}"); + "}"; - Assert.Collection(diagnostics, VerifyDiagnostic); - Assert.Collection(diagnostics, d => Assert.Equal(2, d.Location.GetLineSpan().StartLinePosition.Line)); + var expected = Verify.Diagnostic().WithSpan(3, 5, 3, 25).WithSeverity(DiagnosticSeverity.Warning).WithArguments("TestMethod", "TestClass"); + await Verify.VerifyAnalyzerAsync(source, expected); } [Fact] public async void FindsErrorOnCorrectLineReferringToInitialOccurence_WhenTwoDuplicationEquivalenceSetsExistWithinTheory() { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = "public class TestClass" + "{" + " [Xunit.Theory]" + @@ -424,20 +439,15 @@ public async void FindsErrorOnCorrectLineReferringToInitialOccurence_WhenTwoDupl " [Xunit.InlineData(10)]" + Environment.NewLine + " [Xunit.InlineData(20)]" + Environment.NewLine + " public void TestMethod(int x) { }" + - "}"); - - Assert.All(diagnostics, VerifyDiagnostic); - Assert.Collection(diagnostics, - d => Assert.Equal(2, d.Location.GetLineSpan().StartLinePosition.Line), - d => Assert.Equal(3, d.Location.GetLineSpan().StartLinePosition.Line)); + "}"; + + DiagnosticResult[] expected = + { + Verify.Diagnostic().WithSpan(3, 5, 3, 25).WithSeverity(DiagnosticSeverity.Warning).WithArguments("TestMethod", "TestClass"), + Verify.Diagnostic().WithSpan(4, 5, 4, 25).WithSeverity(DiagnosticSeverity.Warning).WithArguments("TestMethod", "TestClass"), + }; + await Verify.VerifyAnalyzerAsync(source, expected); } } - - public static void VerifyDiagnostic(Diagnostic diagnostic) - { - Assert.Equal("Theory method 'TestMethod' on test class 'TestClass' has InlineData duplicate(s).", diagnostic.GetMessage()); - Assert.Equal("xUnit1025", diagnostic.Descriptor.Id); - Assert.Equal(DiagnosticSeverity.Warning, diagnostic.Severity); - } } } diff --git a/test/xunit.analyzers.tests/MemberDataShouldReferenceValidMemberTests.cs b/test/xunit.analyzers.tests/MemberDataShouldReferenceValidMemberTests.cs index e92a20b4..a024a245 100644 --- a/test/xunit.analyzers.tests/MemberDataShouldReferenceValidMemberTests.cs +++ b/test/xunit.analyzers.tests/MemberDataShouldReferenceValidMemberTests.cs @@ -1,12 +1,11 @@ -using Microsoft.CodeAnalysis.Diagnostics; -using System.Linq; -using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.Testing; +using Verify = Xunit.Analyzers.CSharpVerifier; namespace Xunit.Analyzers { public class MemberDataShouldReferenceValidMemberTests { - readonly DiagnosticAnalyzer analyzer = new MemberDataShouldReferenceValidMember(); static readonly string sharedCode = @"public partial class TestClass { public static System.Collections.Generic.IEnumerable Data { get;set; } } public class OtherClass { public static System.Collections.Generic.IEnumerable OtherData { get;set; } } @@ -15,121 +14,125 @@ public class OtherClass { public static System.Collections.Generic.IEnumerable + await new Verify.Test + { + TestState = { - Assert.Equal("MemberData should use nameof operator to reference member 'Data' on type 'TestClass'.", d.GetMessage()); - Assert.Equal("xUnit1014", d.Descriptor.Id); - }); + Sources = { source, sharedCode }, + ExpectedDiagnostics = { Verify.Diagnostic("xUnit1014").WithSpan(1, 52, 1, 58).WithArguments("Data", "TestClass") }, + }, + }.RunAsync(); } [Fact] public async void FindsError_ForStringReferenceOnOtherClass() { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, - sharedCode, - "public partial class TestClass { [Xunit.MemberData(\"OtherData\", MemberType = typeof(OtherClass))] public void TestMethod() { } }"); + var source = + "public partial class TestClass { [Xunit.MemberData(\"OtherData\", MemberType = typeof(OtherClass))] public void TestMethod() { } }"; - Assert.Collection(diagnostics, - d => + await new Verify.Test + { + TestState = { - Assert.Equal("MemberData should use nameof operator to reference member 'OtherData' on type 'OtherClass'.", d.GetMessage()); - Assert.Equal("xUnit1014", d.Descriptor.Id); - }); + Sources = { source, sharedCode }, + ExpectedDiagnostics = { Verify.Diagnostic("xUnit1014").WithSpan(1, 52, 1, 63).WithArguments("OtherData", "OtherClass") }, + }, + }.RunAsync(); } [Fact] public async void FindsError_ForInvalidNameString() { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = "public class TestClass {" + " [Xunit.MemberData(\"BogusName\")] public void TestMethod() { }" + - "}"); + "}"; - Assert.Collection(diagnostics, - d => - { - Assert.Equal("MemberData must reference an existing member 'BogusName' on type 'TestClass'.", d.GetMessage()); - Assert.Equal("xUnit1015", d.Descriptor.Id); - Assert.Equal(DiagnosticSeverity.Error, d.Severity); - }); + var expected = Verify.Diagnostic("xUnit1015").WithSpan(1, 29, 1, 58).WithSeverity(DiagnosticSeverity.Error).WithArguments("BogusName", "TestClass"); + await Verify.VerifyAnalyzerAsync(source, expected); } [Fact] public async void FindsError_ForInvalidNameString_UsingMemberType() { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = "public class TestClass {" + " [Xunit.MemberData(\"BogusName\", MemberType = typeof(TestClass))] public void TestMethod() { }" + - "}"); + "}"; - Assert.Collection(diagnostics, - d => - { - Assert.Equal("MemberData must reference an existing member 'BogusName' on type 'TestClass'.", d.GetMessage()); - Assert.Equal("xUnit1015", d.Descriptor.Id); - Assert.Equal(DiagnosticSeverity.Error, d.Severity); - }); + var expected = Verify.Diagnostic("xUnit1015").WithSpan(1, 29, 1, 90).WithSeverity(DiagnosticSeverity.Error).WithArguments("BogusName", "TestClass"); + await Verify.VerifyAnalyzerAsync(source, expected); } [Fact] public async void FindsError_ForInvalidNameString_UsingMemberTypeWithOtherType() { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, - "public class OtherClass {}", - "public class TestClass {" + - " [Xunit.MemberData(\"BogusName\", MemberType = typeof(OtherClass))] public void TestMethod() { }" + - "}"); - - Assert.Collection(diagnostics, - d => + await new Verify.Test + { + TestState = + { + Sources = + { + "public class TestClass {" + + " [Xunit.MemberData(\"BogusName\", MemberType = typeof(OtherClass))] public void TestMethod() { }" + + "}", + "public class OtherClass {}", + }, + }, + ExpectedDiagnostics = { - Assert.Equal("MemberData must reference an existing member 'BogusName' on type 'OtherClass'.", d.GetMessage()); - Assert.Equal("xUnit1015", d.Descriptor.Id); - Assert.Equal(DiagnosticSeverity.Error, d.Severity); - }); + Verify.Diagnostic("xUnit1015").WithSpan(1, 29, 1, 91).WithSeverity(DiagnosticSeverity.Error).WithArguments("BogusName", "OtherClass"), + }, + }.RunAsync(); } [Fact] public async void FindsError_ForValidNameofExpression_UsingMemberTypeSpecifyingOtherType() { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, - "public class OtherClass {}", - "public class TestClass {" + - " [Xunit.MemberData(nameof(TestClass.TestMethod), MemberType = typeof(OtherClass))] public void TestMethod() { }" + - "}"); - - Assert.Collection(diagnostics, - d => + await new Verify.Test + { + TestState = { - Assert.Equal("MemberData must reference an existing member 'TestMethod' on type 'OtherClass'.", d.GetMessage()); - Assert.Equal("xUnit1015", d.Descriptor.Id); - Assert.Equal(DiagnosticSeverity.Error, d.Severity); - }); + Sources = + { + "public class TestClass {" + + " [Xunit.MemberData(nameof(TestClass.TestMethod), MemberType = typeof(OtherClass))] public void TestMethod() { }" + + "}", + "public class OtherClass {}", + }, + }, + ExpectedDiagnostics = + { + Verify.Diagnostic("xUnit1015").WithSpan(1, 29, 1, 108).WithSeverity(DiagnosticSeverity.Error).WithArguments("TestMethod", "OtherClass"), + }, + }.RunAsync(); } [Theory] @@ -140,35 +143,30 @@ public async void FindsError_ForValidNameofExpression_UsingMemberTypeSpecifyingO [InlineData("protected internal")] public async void FindsError_ForNonPublicMember(string accessModifier) { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = "public class TestClass {" + $" {accessModifier} static System.Collections.Generic.IEnumerable Data = null;" + " [Xunit.MemberData(nameof(Data))] public void TestMethod() { }" + - "}"); + "}"; - Assert.Collection(diagnostics, - d => - { - Assert.Equal("MemberData must reference a public member", d.GetMessage()); - Assert.Equal("xUnit1016", d.Descriptor.Id); - Assert.Equal(DiagnosticSeverity.Error, d.Severity); - }); + var expected = Verify.Diagnostic("xUnit1016").WithSpan(1, 100 + accessModifier.Length, 1, 130 + accessModifier.Length).WithSeverity(DiagnosticSeverity.Error); + await Verify.VerifyAnalyzerAsync(source, expected); } [Fact] public async void DoesNotFindError_ForPublicMember() { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = "public class TestClass {" + " public static System.Collections.Generic.IEnumerable Data = null;" + " [Xunit.MemberData(nameof(Data))] public void TestMethod() { }" + - "}"); + "}"; - Assert.Empty(diagnostics); + await Verify.VerifyAnalyzerAsync(source); } [Theory] - [InlineData("\"Data\"")] + [InlineData("{|xUnit1014:\"Data\"|}")] [InlineData("DataNameConst")] [InlineData("DataNameofConst")] [InlineData("nameof(Data)")] @@ -177,52 +175,54 @@ public async void DoesNotFindError_ForPublicMember() [InlineData("nameof(OtherClass.Data)")] public async void FindsError_ForNameExpressions(string dataNameExpression) { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, - "public static class OtherClass { public const string Data = \"Data\"; }", - "public class TestClass {" + - " const string DataNameConst = \"Data\";" + - " const string DataNameofConst = nameof(Data);" + - $" private static System.Collections.Generic.IEnumerable Data = null;" + - " [Xunit.MemberData(" + dataNameExpression + ")] public void TestMethod() { }" + - "}"); - - Assert.Collection(diagnostics.Where(d => d.Id != "xUnit1014"), - d => + TestFileMarkupParser.GetPositionsAndSpans(dataNameExpression, out var parsedDataNameExpression, out _, out _); + var dataNameExpressionLength = parsedDataNameExpression.Length; + + await new Verify.Test + { + TestState = + { + Sources = + { + "public class TestClass {" + + " const string DataNameConst = \"Data\";" + + " const string DataNameofConst = nameof(Data);" + + " private static System.Collections.Generic.IEnumerable Data = null;" + + " [Xunit.MemberData(" + dataNameExpression + ")] public void TestMethod() { }" + + "}", + "public static class OtherClass { public const string Data = \"Data\"; }", + }, + }, + ExpectedDiagnostics = { - Assert.Equal("MemberData must reference a public member", d.GetMessage()); - Assert.Equal("xUnit1016", d.Descriptor.Id); - Assert.Equal(DiagnosticSeverity.Error, d.Severity); - }); + Verify.Diagnostic("xUnit1016").WithSpan(1, 193, 1, 211 + dataNameExpressionLength).WithSeverity(DiagnosticSeverity.Error), + }, + }.RunAsync(); } [Fact] public async void FindsError_ForInstanceMember() { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = "public class TestClass {" + " public System.Collections.Generic.IEnumerable Data = null;" + " [Xunit.MemberData(nameof(Data))] public void TestMethod() { }" + - "}"); + "}"; - Assert.Collection(diagnostics, - d => - { - Assert.Equal("MemberData must reference a static member", d.GetMessage()); - Assert.Equal("xUnit1017", d.Descriptor.Id); - Assert.Equal(DiagnosticSeverity.Error, d.Severity); - }); + var expected = Verify.Diagnostic("xUnit1017").WithSpan(1, 100, 1, 130).WithSeverity(DiagnosticSeverity.Error); + await Verify.VerifyAnalyzerAsync(source, expected); } [Fact] public async void DoesNotFindError_ForStaticMember() { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = "public class TestClass {" + " public static System.Collections.Generic.IEnumerable Data = null;" + " [Xunit.MemberData(nameof(Data))] public void TestMethod() { }" + - "}"); + "}"; - Assert.Empty(diagnostics); + await Verify.VerifyAnalyzerAsync(source); } [Theory] @@ -231,19 +231,14 @@ public async void DoesNotFindError_ForStaticMember() [InlineData("public static event System.EventHandler Data;")] public async void FindsError_ForInvalidMemberKind(string member) { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = "public class TestClass {" + member + " [Xunit.MemberData(nameof(Data))] public void TestMethod() { }" + - "}"); + "}"; - Assert.Collection(diagnostics, - d => - { - Assert.Equal("xUnit1018", d.Descriptor.Id); - Assert.Equal("MemberData must reference a property, field, or method", d.GetMessage()); - Assert.Equal(DiagnosticSeverity.Error, d.Severity); - }); + var expected = Verify.Diagnostic("xUnit1018").WithSpan(1, 29 + member.Length, 1, 59 + member.Length).WithSeverity(DiagnosticSeverity.Error); + await Verify.VerifyAnalyzerAsync(source, expected); } [Theory] @@ -252,13 +247,13 @@ public async void FindsError_ForInvalidMemberKind(string member) [InlineData("public static System.Collections.Generic.IEnumerable Data() { return null; }")] public async void DoesNotFindError_ForValidMemberKind(string member) { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = "public class TestClass {" + member + " [Xunit.MemberData(nameof(Data))] public void TestMethod() { }" + - "}"); + "}"; - Assert.Empty(diagnostics); + await Verify.VerifyAnalyzerAsync(source); } [Theory] @@ -269,19 +264,14 @@ public async void DoesNotFindError_ForValidMemberKind(string member) [InlineData("System.Tuple[]")] public async void FindsError_ForInvalidMemberType(string memberType) { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = "public class TestClass {" + $"public static {memberType} Data;" + " [Xunit.MemberData(nameof(Data))] public void TestMethod() { }" + - "}"); + "}"; - Assert.Collection(diagnostics, - d => - { - Assert.Equal("xUnit1019", d.Descriptor.Id); - Assert.Equal("MemberData must reference a data type assignable to 'System.Collections.Generic.IEnumerable'. The referenced type '" + memberType + "' is not valid.", d.GetMessage()); - Assert.Equal(DiagnosticSeverity.Error, d.Severity); - }); + var expected = Verify.Diagnostic("xUnit1019").WithSpan(1, 49 + memberType.Length, 1, 79 + memberType.Length).WithSeverity(DiagnosticSeverity.Error).WithArguments("System.Collections.Generic.IEnumerable", memberType); + await Verify.VerifyAnalyzerAsync(source, expected); } [Theory] @@ -290,31 +280,26 @@ public async void FindsError_ForInvalidMemberType(string memberType) [InlineData("Xunit.TheoryData")] public async void DoesNotFindError_ForCompatibleMemberType(string memberType) { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = "public class TestClass {" + $"public static {memberType} Data;" + " [Xunit.MemberData(nameof(Data))] public void TestMethod() { }" + - "}"); + "}"; - Assert.Empty(diagnostics); + await Verify.VerifyAnalyzerAsync(source); } [Fact] public async void FindsError_ForMemberPropertyWithoutGetter() { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = "public class TestClass {" + " public static System.Collections.Generic.IEnumerable Data { set { } }" + " [Xunit.MemberData(nameof(Data))] public void TestMethod() { }" + - "}"); + "}"; - Assert.Collection(diagnostics, - d => - { - Assert.Equal("xUnit1020", d.Descriptor.Id); - Assert.Equal("MemberData must reference a property with a getter", d.GetMessage()); - Assert.Equal(DiagnosticSeverity.Error, d.Severity); - }); + var expected = Verify.Diagnostic("xUnit1020").WithSpan(1, 111, 1, 141).WithSeverity(DiagnosticSeverity.Error); + await Verify.VerifyAnalyzerAsync(source, expected); } [Theory] @@ -323,19 +308,14 @@ public async void FindsError_ForMemberPropertyWithoutGetter() [InlineData("parameters: new object[] { 'a', 123 }")] public async void FindsWarning_ForMemberDataParametersForFieldMember(string paramsArgument) { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = "public class TestClass {" + " public static System.Collections.Generic.IEnumerable Data;" + " [Xunit.MemberData(nameof(Data), " + paramsArgument + ", MemberType = typeof(TestClass))] public void TestMethod() { }" + - "}"); + "}"; - Assert.Collection(diagnostics, - d => - { - Assert.Equal("xUnit1021", d.Descriptor.Id); - Assert.Equal("MemberData should not have parameters if the referenced member is not a method", d.GetMessage()); - Assert.Equal(DiagnosticSeverity.Warning, d.Severity); - }); + var expected = Verify.Diagnostic("xUnit1021").WithSpan(1, 131, 1, 131 + paramsArgument.Length).WithSeverity(DiagnosticSeverity.Warning); + await Verify.VerifyAnalyzerAsync(source, expected); } [Theory] @@ -344,31 +324,26 @@ public async void FindsWarning_ForMemberDataParametersForFieldMember(string para [InlineData("parameters: new object[] { 'a', 123 }")] public async void FindsWarning_ForMemberDataParametersForPropertyMember(string paramsArgument) { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = "public class TestClass {" + " public static System.Collections.Generic.IEnumerable Data { get; set; }" + " [Xunit.MemberData(nameof(Data), " + paramsArgument + ", MemberType = typeof(TestClass))] public void TestMethod() { }" + - "}"); + "}"; - Assert.Collection(diagnostics, - d => - { - Assert.Equal("xUnit1021", d.Descriptor.Id); - Assert.Equal("MemberData should not have parameters if the referenced member is not a method", d.GetMessage()); - Assert.Equal(DiagnosticSeverity.Warning, d.Severity); - }); + var expected = Verify.Diagnostic("xUnit1021").WithSpan(1, 144, 1, 144 + paramsArgument.Length).WithSeverity(DiagnosticSeverity.Warning); + await Verify.VerifyAnalyzerAsync(source, expected); } [Fact] public async void DoesNotFindWarning_ForMemberDataAttributeWithNamedParameter() { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = "public class TestClass {" + " public static System.Collections.Generic.IEnumerable Data;" + " [Xunit.MemberData(nameof(Data), MemberType = typeof(TestClass))] public void TestMethod() { }" + - "}"); + "}"; - Assert.Empty(diagnostics); + await Verify.VerifyAnalyzerAsync(source); } } } diff --git a/test/xunit.analyzers.tests/PublicMethodShouldBeMarkedAsTestTests.cs b/test/xunit.analyzers.tests/PublicMethodShouldBeMarkedAsTestTests.cs index 97d2c605..8a4b2b89 100644 --- a/test/xunit.analyzers.tests/PublicMethodShouldBeMarkedAsTestTests.cs +++ b/test/xunit.analyzers.tests/PublicMethodShouldBeMarkedAsTestTests.cs @@ -1,19 +1,16 @@ -using System; -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.Diagnostics; +using Microsoft.CodeAnalysis; +using Verify = Xunit.Analyzers.CSharpVerifier; namespace Xunit.Analyzers { public class PublicMethodShouldBeMarkedAsTestTests { - readonly DiagnosticAnalyzer analyzer = new PublicMethodShouldBeMarkedAsTest(); - [Fact] public async void DoesNotFindErrorForPublicMethodInNonTestClass() { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, "public class TestClass { public void TestMethod() { } }"); + var source = "public class TestClass { public void TestMethod() { } }"; - Assert.Empty(diagnostics); + await Verify.VerifyAnalyzerAsync(source); } [Theory] @@ -21,80 +18,80 @@ public async void DoesNotFindErrorForPublicMethodInNonTestClass() [InlineData("Xunit.Theory")] public async void DoesNotFindErrorForTestMethods(string attribute) { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, "public class TestClass { [" + attribute + "] public void TestMethod() { } }"); + var source = "public class TestClass { [" + attribute + "] public void TestMethod() { } }"; - Assert.Empty(diagnostics); + await Verify.VerifyAnalyzerAsync(source); } [Fact] public async void DoesNotFindErrorForIDisposableDisposeMethod() { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = @"public class TestClass : System.IDisposable { [Xunit.Fact] public void TestMethod() { } public void Dispose() { } -}"); +}"; - Assert.Empty(diagnostics); + await Verify.VerifyAnalyzerAsync(source); } [Fact] public async void DoesNotFindErrorForPublicAbstractMethod() { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = @"public abstract class TestClass { [Xunit.Fact] public void TestMethod() { } public abstract void AbstractMethod(); -}"); +}"; - Assert.Empty(diagnostics); + await Verify.VerifyAnalyzerAsync(source); } [Fact] public async void DoesNotFindErrorForPublicAbstractMethodMarkedWithFact() { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = @"public abstract class TestClass { [Xunit.Fact] public void TestMethod() { } [Xunit.Fact] public abstract void AbstractMethod(); -}"); - Assert.Empty(diagnostics); +}"; + await Verify.VerifyAnalyzerAsync(source); } [Fact] public async void DoesNotFindErrorForIDisposableDisposeMethodOverrideFromParentClass() { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = @"public class BaseClass : System.IDisposable { public virtual void Dispose() { } } public class TestClass : BaseClass { [Xunit.Fact] public void TestMethod() { } public override void Dispose() { } -}"); +}"; - Assert.Empty(diagnostics); + await Verify.VerifyAnalyzerAsync(source); } [Fact] public async void DoesNotFindErrorForIDisposableDisposeMethodOverrideFromParentClassWithRepeatedInterfaceDeclaration() { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = @"public class BaseClass : System.IDisposable { public virtual void Dispose() { } } public class TestClass : BaseClass, System.IDisposable { [Xunit.Fact] public void TestMethod() { } public override void Dispose() { } -}"); +}"; - Assert.Empty(diagnostics); + await Verify.VerifyAnalyzerAsync(source); } [Fact] public async void DoesNotFindErrorForIDisposableDisposeMethodOverrideFromGrandParentClass() { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = @"public abstract class BaseClass : System.IDisposable { public abstract void Dispose(); } @@ -103,15 +100,15 @@ public abstract class IntermediateClass : BaseClass { public class TestClass : IntermediateClass { [Xunit.Fact] public void TestMethod() { } public override void Dispose() { } -}"); +}"; - Assert.Empty(diagnostics); + await Verify.VerifyAnalyzerAsync(source); } [Fact] public async void DoesNotFindErrorForIAsyncLifetimeMethods() { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = @"public class TestClass : Xunit.IAsyncLifetime { [Xunit.Fact] public void TestMethod() { } public System.Threading.Tasks.Task DisposeAsync() @@ -122,29 +119,29 @@ public System.Threading.Tasks.Task InitializeAsync() { throw new System.NotImplementedException(); } -}"); +}"; - Assert.Empty(diagnostics); + await Verify.VerifyAnalyzerAsync(source); } [Fact] public async void DoesNotFindErrorForPublicMethodMarkedWithAttributeWhichIsMarkedWithIgnoreXunitAnalyzersRule1013() { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = @"public class IgnoreXunitAnalyzersRule1013Attribute : System.Attribute { } [IgnoreXunitAnalyzersRule1013] public class CustomTestTypeAttribute : System.Attribute { } -public class TestClass { [Xunit.Fact] public void TestMethod() { } [CustomTestType] public void CustomTestMethod() {} }"); +public class TestClass { [Xunit.Fact] public void TestMethod() { } [CustomTestType] public void CustomTestMethod() {} }"; - Assert.Empty(diagnostics); + await Verify.VerifyAnalyzerAsync(source); } [Fact] public async void FindsWarningForPublicMethodMarkedWithAttributeWhichInheritsFromAttributeMarkedWithIgnoreXunitAnalyzersRule1013() { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = @"public class IgnoreXunitAnalyzersRule1013Attribute : System.Attribute { } [IgnoreXunitAnalyzersRule1013] @@ -152,15 +149,10 @@ public class BaseCustomTestTypeAttribute : System.Attribute { } public class DerivedCustomTestTypeAttribute : BaseCustomTestTypeAttribute { } -public class TestClass { [Xunit.Fact] public void TestMethod() { } [DerivedCustomTestType] public void CustomTestMethod() {} }"); +public class TestClass { [Xunit.Fact] public void TestMethod() { } [DerivedCustomTestType] public void CustomTestMethod() {} }"; - Assert.Collection(diagnostics, - d => - { - Assert.Equal("Public method 'CustomTestMethod' on test class 'TestClass' should be marked as a Fact.", d.GetMessage()); - Assert.Equal("xUnit1013", d.Id); - Assert.Equal(DiagnosticSeverity.Warning, d.Severity); - }); + var expected = Verify.Diagnostic().WithSpan(8, 104, 8, 120).WithSeverity(DiagnosticSeverity.Warning).WithArguments("CustomTestMethod", "TestClass", "Fact"); + await Verify.VerifyAnalyzerAsync(source, expected); } [Theory] @@ -169,16 +161,11 @@ public class TestClass { [Xunit.Fact] public void TestMethod() { } [DerivedCusto public async void FindsWarningForPublicMethodWithoutParametersInTestClass(string attribute) { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, - "public class TestClass { [" + attribute + "] public void TestMethod() { } public void Method() {} }"); - - Assert.Collection(diagnostics, - d => - { - Assert.Equal("Public method 'Method' on test class 'TestClass' should be marked as a Fact.", d.GetMessage()); - Assert.Equal("xUnit1013", d.Id); - Assert.Equal(DiagnosticSeverity.Warning, d.Severity); - }); + var source = + "public class TestClass { [" + attribute + "] public void TestMethod() { } public void Method() {} }"; + + var expected = Verify.Diagnostic().WithSpan(1, 70 + attribute.Length, 1, 76 + attribute.Length).WithSeverity(DiagnosticSeverity.Warning).WithArguments("Method", "TestClass", "Fact"); + await Verify.VerifyAnalyzerAsync(source, expected); } [Theory] @@ -187,16 +174,11 @@ public async void FindsWarningForPublicMethodWithoutParametersInTestClass(string public async void FindsWarningForPublicMethodWithParametersInTestClass(string attribute) { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, - "public class TestClass { [" + attribute + "] public void TestMethod() { } public void Method(int a) {} }"); - - Assert.Collection(diagnostics, - d => - { - Assert.Equal("Public method 'Method' on test class 'TestClass' should be marked as a Theory.", d.GetMessage()); - Assert.Equal("xUnit1013", d.Id); - Assert.Equal(DiagnosticSeverity.Warning, d.Severity); - }); + var source = + "public class TestClass { [" + attribute + "] public void TestMethod() { } public void Method(int a) {} }"; + + var expected = Verify.Diagnostic().WithSpan(1, 70 + attribute.Length, 1, 76 + attribute.Length).WithSeverity(DiagnosticSeverity.Warning).WithArguments("Method", "TestClass", "Theory"); + await Verify.VerifyAnalyzerAsync(source, expected); } [Theory] @@ -205,10 +187,11 @@ public async void FindsWarningForPublicMethodWithParametersInTestClass(string at public async void DoesNotFindErrorForOverridenMethod(string attribute) { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, CompilationReporting.IgnoreErrors, - "public class TestClass { [" + attribute + "] public void TestMethod() { } public override void Method() {} }"); + var source = + "public class TestClass { [" + attribute + "] public void TestMethod() { } public override void Method() {} }"; - Assert.Empty(diagnostics); + var expected = Verify.CompilerError("CS0115").WithSpan(1, 79 + attribute.Length, 1, 85 + attribute.Length).WithMessage("'TestClass.Method()': no suitable method found to override"); + await Verify.VerifyAnalyzerAsync(source, expected); } } } diff --git a/test/xunit.analyzers.tests/SerializableClassMustHaveParameterlessConstructorFixerTests.cs b/test/xunit.analyzers.tests/SerializableClassMustHaveParameterlessConstructorFixerTests.cs index d80d3cc0..1090865c 100644 --- a/test/xunit.analyzers.tests/SerializableClassMustHaveParameterlessConstructorFixerTests.cs +++ b/test/xunit.analyzers.tests/SerializableClassMustHaveParameterlessConstructorFixerTests.cs @@ -1,31 +1,25 @@ -using Microsoft.CodeAnalysis.CodeFixes; -using Microsoft.CodeAnalysis.Diagnostics; +using Verify = Xunit.Analyzers.CSharpVerifier; namespace Xunit.Analyzers { public class SerializableClassMustHaveParameterlessConstructorFixerTests { - readonly DiagnosticAnalyzer analyzer = new SerializableClassMustHaveParameterlessConstructor(); - readonly CodeFixProvider fixer = new SerializableClassMustHaveParameterlessConstructorFixer(); - [Fact] public async void WithNonPublicParameterlessConstructor_ChangesVisibility_WithoutUsing() { var code = -@"public class MyTestCase : Xunit.Abstractions.IXunitSerializable +@"public class [|MyTestCase|] : {|CS0535:{|CS0535:Xunit.Abstractions.IXunitSerializable|}|} { protected MyTestCase() { throw new System.DivideByZeroException(); } }"; var expected = -@"public class MyTestCase : Xunit.Abstractions.IXunitSerializable +@"public class MyTestCase : {|CS0535:{|CS0535:Xunit.Abstractions.IXunitSerializable|}|} { [System.Obsolete(""Called by the de-serializer; should only be called by deriving classes for de-serialization purposes"")] public MyTestCase() { throw new System.DivideByZeroException(); } }"; - var result = await CodeAnalyzerHelper.GetFixedCodeAsync(analyzer, fixer, code, CompilationReporting.IgnoreErrors); - - Assert.Equal(expected, result, ignoreLineEndingDifferences: true); + await Verify.VerifyCodeFixAsync(code, expected); } [Fact] @@ -35,7 +29,7 @@ public async void WithNonPublicParameterlessConstructor_ChangesVisibility_WithUs @"using System; using Xunit.Abstractions; -public class MyTestCase : IXunitSerializable +public class [|MyTestCase|] : {|CS0535:{|CS0535:IXunitSerializable|}|} { protected MyTestCase() { throw new DivideByZeroException(); } }"; @@ -43,15 +37,13 @@ public class MyTestCase : IXunitSerializable @"using System; using Xunit.Abstractions; -public class MyTestCase : IXunitSerializable +public class MyTestCase : {|CS0535:{|CS0535:IXunitSerializable|}|} { [Obsolete(""Called by the de-serializer; should only be called by deriving classes for de-serialization purposes"")] public MyTestCase() { throw new DivideByZeroException(); } }"; - var result = await CodeAnalyzerHelper.GetFixedCodeAsync(analyzer, fixer, code, CompilationReporting.IgnoreErrors); - - Assert.Equal(expected, result, ignoreLineEndingDifferences: true); + await Verify.VerifyCodeFixAsync(code, expected); } [Fact] @@ -60,7 +52,7 @@ public async void PreservesExistingObsoleteAttribute() var code = @"using obo = System.ObsoleteAttribute; -public class MyTestCase : Xunit.Abstractions.IXunitSerializable +public class [|MyTestCase|] : {|CS0535:{|CS0535:Xunit.Abstractions.IXunitSerializable|}|} { [obo(""This is my custom obsolete message"")] protected MyTestCase() { throw new System.DivideByZeroException(); } @@ -68,15 +60,13 @@ public class MyTestCase : Xunit.Abstractions.IXunitSerializable var expected = @"using obo = System.ObsoleteAttribute; -public class MyTestCase : Xunit.Abstractions.IXunitSerializable +public class MyTestCase : {|CS0535:{|CS0535:Xunit.Abstractions.IXunitSerializable|}|} { [obo(""This is my custom obsolete message"")] public MyTestCase() { throw new System.DivideByZeroException(); } }"; - var result = await CodeAnalyzerHelper.GetFixedCodeAsync(analyzer, fixer, code, CompilationReporting.IgnoreErrors); - - Assert.Equal(expected, result, ignoreLineEndingDifferences: true); + await Verify.VerifyCodeFixAsync(code, expected); } } } diff --git a/test/xunit.analyzers.tests/SerializableClassMustHaveParameterlessConstructorTests.cs b/test/xunit.analyzers.tests/SerializableClassMustHaveParameterlessConstructorTests.cs index dc83e3b9..b5ec12e6 100644 --- a/test/xunit.analyzers.tests/SerializableClassMustHaveParameterlessConstructorTests.cs +++ b/test/xunit.analyzers.tests/SerializableClassMustHaveParameterlessConstructorTests.cs @@ -1,11 +1,9 @@ -using Microsoft.CodeAnalysis.Diagnostics; +using Verify = Xunit.Analyzers.CSharpVerifier; namespace Xunit.Analyzers { public class SerializableClassMustHaveParameterlessConstructorTests { - readonly DiagnosticAnalyzer analyzer = new SerializableClassMustHaveParameterlessConstructor(); - static readonly string Template = @" using Xunit.Abstractions; @@ -23,56 +21,34 @@ public void Serialize(IXunitSerializationInfo info) {{ }} [MemberData(nameof(Interfaces))] public async void ImplicitConstructors_NoDiagnostics(string @interface) { - var code = string.Format(Template, @interface, ""); - - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, code); - - Assert.Empty(diagnostics); + var source = string.Format(Template, @interface, ""); + await Verify.VerifyAnalyzerAsync(source); } [Theory] [MemberData(nameof(Interfaces))] public async void WrongConstructor_ReturnsError(string @interface) { - var code = string.Format(Template, @interface, "public Foo(int x) { }"); - - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, code); - - Assert.Collection(diagnostics, - d => - { - Assert.Equal("Class Foo must have a public parameterless constructor to support Xunit.Abstractions.IXunitSerializable", d.GetMessage()); - Assert.Equal("xUnit3001", d.Descriptor.Id); - } - ); + var source = string.Format(Template, @interface, "public Foo(int x) { }"); + var expected = Verify.Diagnostic().WithSpan(5, 14, 5, 17).WithArguments("Foo"); + await Verify.VerifyAnalyzerAsync(source, expected); } [Theory] [MemberData(nameof(Interfaces))] public async void NonPublicConstructor_ReturnsError(string @interface) { - var code = string.Format(Template, @interface, "protected Foo() { }"); - - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, code); - - Assert.Collection(diagnostics, - d => - { - Assert.Equal("Class Foo must have a public parameterless constructor to support Xunit.Abstractions.IXunitSerializable", d.GetMessage()); - Assert.Equal("xUnit3001", d.Descriptor.Id); - } - ); + var source = string.Format(Template, @interface, "protected Foo() { }"); + var expected = Verify.Diagnostic().WithSpan(5, 14, 5, 17).WithArguments("Foo"); + await Verify.VerifyAnalyzerAsync(source, expected); } [Theory] [MemberData(nameof(Interfaces))] public async void PublicParameterlessConstructor_NoDiagnostics(string @interface) { - var code = string.Format(Template, @interface, "public Foo() { }"); - - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, code); - - Assert.Empty(diagnostics); + var source = string.Format(Template, @interface, "public Foo() { }"); + await Verify.VerifyAnalyzerAsync(source); } } } diff --git a/test/xunit.analyzers.tests/TestCaseMustBeLongLivedMarshalByRefObjectFixerTests.cs b/test/xunit.analyzers.tests/TestCaseMustBeLongLivedMarshalByRefObjectFixerTests.cs index 29852305..82552fb4 100644 --- a/test/xunit.analyzers.tests/TestCaseMustBeLongLivedMarshalByRefObjectFixerTests.cs +++ b/test/xunit.analyzers.tests/TestCaseMustBeLongLivedMarshalByRefObjectFixerTests.cs @@ -1,51 +1,75 @@ -using Microsoft.CodeAnalysis.CodeFixes; -using Microsoft.CodeAnalysis.Diagnostics; +using Verify = Xunit.Analyzers.CSharpVerifier; namespace Xunit.Analyzers { public class TestCaseMustBeLongLivedMarshalByRefObjectFixerTests { - readonly DiagnosticAnalyzer analyzer = new TestCaseMustBeLongLivedMarshalByRefObject(); - readonly CodeFixProvider fixer = new TestCaseMustBeLongLivedMarshalByRefObjectFixer(); - [Fact] public async void WithNoBaseClass_WithoutUsing_AddsBaseClass() { - var code = "public class MyTestCase : Xunit.Abstractions.ITestCase { }"; - - var result = await CodeAnalyzerHelper.GetFixedCodeAsync(analyzer, fixer, code, CompilationReporting.IgnoreErrors, XunitReferences.PkgExecutionExtensibility); + var source = "public class [|MyTestCase|] : {|CS0535:{|CS0535:{|CS0535:{|CS0535:{|CS0535:{|CS0535:{|CS0535:{|CS0535:{|CS0535:Xunit.Abstractions.ITestCase|}|}|}|}|}|}|}|}|} { }"; + var fixedSource = "public class MyTestCase : Xunit.LongLivedMarshalByRefObject, {|CS0535:{|CS0535:{|CS0535:{|CS0535:{|CS0535:{|CS0535:{|CS0535:{|CS0535:{|CS0535:Xunit.Abstractions.ITestCase|}|}|}|}|}|}|}|}|} { }"; - Assert.Equal("public class MyTestCase : Xunit.LongLivedMarshalByRefObject, Xunit.Abstractions.ITestCase { }", result); + await new Verify.Test + { + TestState = + { + Sources = { source }, + AdditionalReferences = { CodeAnalyzerHelper.XunitExecutionReference }, + }, + FixedState = { Sources = { fixedSource } }, + }.RunAsync(); } [Fact] public async void WithNoBaseClass_WithUsing_AddsBaseClass() { - var code = "using Xunit; using Xunit.Abstractions; public class MyTestCase : ITestCase { }"; - - var result = await CodeAnalyzerHelper.GetFixedCodeAsync(analyzer, fixer, code, CompilationReporting.IgnoreErrors, XunitReferences.PkgExecutionExtensibility); + var source = "using Xunit; using Xunit.Abstractions; public class [|MyTestCase|] : {|CS0535:{|CS0535:{|CS0535:{|CS0535:{|CS0535:{|CS0535:{|CS0535:{|CS0535:{|CS0535:ITestCase|}|}|}|}|}|}|}|}|} { }"; + var fixedSource = "using Xunit; using Xunit.Abstractions; public class MyTestCase : LongLivedMarshalByRefObject, {|CS0535:{|CS0535:{|CS0535:{|CS0535:{|CS0535:{|CS0535:{|CS0535:{|CS0535:{|CS0535:ITestCase|}|}|}|}|}|}|}|}|} { }"; - Assert.Equal("using Xunit; using Xunit.Abstractions; public class MyTestCase : LongLivedMarshalByRefObject, ITestCase { }", result); + await new Verify.Test + { + TestState = + { + Sources = { source }, + AdditionalReferences = { CodeAnalyzerHelper.XunitExecutionReference }, + }, + FixedState = { Sources = { fixedSource } }, + }.RunAsync(); } [Fact] public async void WithBadBaseClass_WithoutUsing_ReplacesBaseClass() { - var code = "public class Foo { } public class MyTestCase : Foo, Xunit.Abstractions.ITestCase { }"; + var source = "public class Foo { } public class [|MyTestCase|] : Foo, {|CS0535:{|CS0535:{|CS0535:{|CS0535:{|CS0535:{|CS0535:{|CS0535:{|CS0535:{|CS0535:Xunit.Abstractions.ITestCase|}|}|}|}|}|}|}|}|} { }"; + var fixedSource = "public class Foo { } public class MyTestCase : Xunit.LongLivedMarshalByRefObject, {|CS0535:{|CS0535:{|CS0535:{|CS0535:{|CS0535:{|CS0535:{|CS0535:{|CS0535:{|CS0535:Xunit.Abstractions.ITestCase|}|}|}|}|}|}|}|}|} { }"; - var result = await CodeAnalyzerHelper.GetFixedCodeAsync(analyzer, fixer, code, CompilationReporting.IgnoreErrors, XunitReferences.PkgExecutionExtensibility); - - Assert.Equal("public class Foo { } public class MyTestCase : Xunit.LongLivedMarshalByRefObject, Xunit.Abstractions.ITestCase { }", result); + await new Verify.Test + { + TestState = + { + Sources = { source }, + AdditionalReferences = { CodeAnalyzerHelper.XunitExecutionReference }, + }, + FixedState = { Sources = { fixedSource } }, + }.RunAsync(); } [Fact] public async void WithBadBaseClass_WithUsing_ReplacesBaseClass() { - var code = "using Xunit; using Xunit.Abstractions; public class Foo { } public class MyTestCase : Foo, ITestCase { }"; - - var result = await CodeAnalyzerHelper.GetFixedCodeAsync(analyzer, fixer, code, CompilationReporting.IgnoreErrors, XunitReferences.PkgExecutionExtensibility); + var source = "using Xunit; using Xunit.Abstractions; public class Foo { } public class [|MyTestCase|] : Foo, {|CS0535:{|CS0535:{|CS0535:{|CS0535:{|CS0535:{|CS0535:{|CS0535:{|CS0535:{|CS0535:ITestCase|}|}|}|}|}|}|}|}|} { }"; + var fixedSource = "using Xunit; using Xunit.Abstractions; public class Foo { } public class MyTestCase : LongLivedMarshalByRefObject, {|CS0535:{|CS0535:{|CS0535:{|CS0535:{|CS0535:{|CS0535:{|CS0535:{|CS0535:{|CS0535:ITestCase|}|}|}|}|}|}|}|}|} { }"; - Assert.Equal("using Xunit; using Xunit.Abstractions; public class Foo { } public class MyTestCase : LongLivedMarshalByRefObject, ITestCase { }", result); + await new Verify.Test + { + TestState = + { + Sources = { source }, + AdditionalReferences = { CodeAnalyzerHelper.XunitExecutionReference }, + }, + FixedState = { Sources = { fixedSource } }, + }.RunAsync(); } } } diff --git a/test/xunit.analyzers.tests/TestCaseMustBeLongLivedMarshalByRefObjectTests.cs b/test/xunit.analyzers.tests/TestCaseMustBeLongLivedMarshalByRefObjectTests.cs index c5740046..9ad17c21 100644 --- a/test/xunit.analyzers.tests/TestCaseMustBeLongLivedMarshalByRefObjectTests.cs +++ b/test/xunit.analyzers.tests/TestCaseMustBeLongLivedMarshalByRefObjectTests.cs @@ -1,19 +1,23 @@ using System.Linq; -using Microsoft.CodeAnalysis.Diagnostics; +using Microsoft.CodeAnalysis.Testing; +using Verify = Xunit.Analyzers.CSharpVerifier; namespace Xunit.Analyzers { public class TestCaseMustBeLongLivedMarshalByRefObjectTests { - readonly DiagnosticAnalyzer analyzer = new TestCaseMustBeLongLivedMarshalByRefObject(); - readonly static string Template = @" public class Foo {{ }} public class MyLLMBRO: Xunit.LongLivedMarshalByRefObject {{ }} public class MyTestCase: {0} {{ }} "; - public static TheoryData Interfaces = new TheoryData { "Xunit.Abstractions.ITestCase", "Xunit.Sdk.IXunitTestCase" }; + public static TheoryData Interfaces = + new TheoryData + { + "{|CS0535:{|CS0535:{|CS0535:{|CS0535:{|CS0535:{|CS0535:{|CS0535:{|CS0535:{|CS0535:Xunit.Abstractions.ITestCase|}|}|}|}|}|}|}|}|}", + "{|CS0535:{|CS0535:{|CS0535:{|CS0535:{|CS0535:{|CS0535:{|CS0535:{|CS0535:{|CS0535:{|CS0535:{|CS0535:{|CS0535:{|CS0535:Xunit.Sdk.IXunitTestCase|}|}|}|}|}|}|}|}|}|}|}|}|}", + }; public static TheoryData InterfacesWithBaseClasses { @@ -34,62 +38,73 @@ public static TheoryData InterfacesWithBaseClasses [Fact] public async void NonTestCase_NoDiagnostics() { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, "public class Foo { }"); + var source = "public class Foo { }"; - Assert.Empty(diagnostics); + await Verify.VerifyAnalyzerAsync(source); } [Fact] public async void XunitTestCase_NoDiagnostics() { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, XunitReferences.PkgExecutionExtensibility, "public class MyTestCase : Xunit.Sdk.XunitTestCase { }"); + var source = "public class MyTestCase : Xunit.Sdk.XunitTestCase { }"; - Assert.Empty(diagnostics); + await new Verify.Test + { + TestState = + { + Sources = { source }, + AdditionalReferences = { CodeAnalyzerHelper.XunitExecutionReference }, + }, + }.RunAsync(); } [Theory] [MemberData(nameof(InterfacesWithBaseClasses))] public async void InterfaceWithProperBaseClass_NoDiagnostics(string @interface, string baseClass) { - var code = string.Format(Template, $"{baseClass}, {@interface}"); - - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, CompilationReporting.IgnoreErrors, XunitReferences.PkgExecutionExtensibility, code); - - Assert.Empty(diagnostics); + var source = string.Format(Template, $"{baseClass}, {@interface}"); + await new Verify.Test + { + TestState = + { + Sources = { source }, + AdditionalReferences = { CodeAnalyzerHelper.XunitExecutionReference }, + }, + }.RunAsync(); } [Theory] [MemberData(nameof(Interfaces))] public async void InterfaceWithoutBaseClass_ReturnsError(string @interface) { - var code = string.Format(Template, @interface); - - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, CompilationReporting.IgnoreErrors, XunitReferences.PkgExecutionExtensibility, code); + var source = string.Format(Template, @interface); - Assert.Collection(diagnostics, - d => + await new Verify.Test + { + TestState = { - Assert.Equal("Test case class MyTestCase must derive directly or indirectly from Xunit.LongLivedMarshalByRefObject", d.GetMessage()); - Assert.Equal("xUnit3000", d.Descriptor.Id); - } - ); + Sources = { source }, + AdditionalReferences = { CodeAnalyzerHelper.XunitExecutionReference }, + ExpectedDiagnostics = { Verify.Diagnostic().WithLocation(4, 14).WithArguments("MyTestCase") }, + }, + }.RunAsync(); } [Theory] [MemberData(nameof(Interfaces))] public async void InterfaceWithBadBaseClass_ReturnsError(string @interface) { - var code = string.Format(Template, $"Foo, {@interface}"); + var source = string.Format(Template, $"Foo, {@interface}"); - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, CompilationReporting.IgnoreErrors, XunitReferences.PkgExecutionExtensibility, code); - - Assert.Collection(diagnostics, - d => + await new Verify.Test + { + TestState = { - Assert.Equal("Test case class MyTestCase must derive directly or indirectly from Xunit.LongLivedMarshalByRefObject", d.GetMessage()); - Assert.Equal("xUnit3000", d.Descriptor.Id); - } - ); + Sources = { source }, + AdditionalReferences = { CodeAnalyzerHelper.XunitExecutionReference }, + ExpectedDiagnostics = { Verify.Diagnostic().WithLocation(4, 14).WithArguments("MyTestCase") }, + }, + }.RunAsync(); } } } diff --git a/test/xunit.analyzers.tests/TestClassMustBePublicFixerTests.cs b/test/xunit.analyzers.tests/TestClassMustBePublicFixerTests.cs index 5bae4d30..f99f8b4c 100644 --- a/test/xunit.analyzers.tests/TestClassMustBePublicFixerTests.cs +++ b/test/xunit.analyzers.tests/TestClassMustBePublicFixerTests.cs @@ -1,32 +1,26 @@ -using Microsoft.CodeAnalysis.CodeFixes; -using Microsoft.CodeAnalysis.Diagnostics; +using Verify = Xunit.Analyzers.CSharpVerifier; namespace Xunit.Analyzers { public class TestClassMustBePublicFixerTests { - readonly DiagnosticAnalyzer analyzer = new TestClassMustBePublic(); - readonly CodeFixProvider fixer = new TestClassMustBePublicFixer(); - [Theory] [InlineData("")] [InlineData("internal")] public async void MakesClassPublic(string nonPublicAccessModifier) { - var source = $"{nonPublicAccessModifier} class TestClass {{ [Xunit.Fact] public void TestMethod() {{ }} }}"; - - var expected = "public class TestClass { [Xunit.Fact] public void TestMethod() { } }"; + var source = $"{nonPublicAccessModifier} class [|TestClass|] {{ [Xunit.Fact] public void TestMethod() {{ }} }}"; - var actual = await CodeAnalyzerHelper.GetFixedCodeAsync(analyzer, fixer, source); + var fixedSource = "public class TestClass { [Xunit.Fact] public void TestMethod() { } }"; - Assert.Equal(expected, actual); + await Verify.VerifyCodeFixAsync(source, fixedSource); } [Fact] public async void ForPartialClassDeclarations_MakesSingleDeclarationPublic() { var source = @" -partial class TestClass +partial class [|TestClass|] { [Xunit.Fact] public void TestMethod1() {} @@ -38,7 +32,7 @@ partial class TestClass public void TestMethod2() {} }"; - var expected = @" + var fixedSource = @" public partial class TestClass { [Xunit.Fact] @@ -51,10 +45,7 @@ partial class TestClass public void TestMethod2() {} }"; - var actual = await CodeAnalyzerHelper.GetFixedCodeAsync(analyzer, fixer, source); - - Assert.Equal(expected, actual); + await Verify.VerifyCodeFixAsync(source, fixedSource); } - } } diff --git a/test/xunit.analyzers.tests/TestClassMustBePublicTests.cs b/test/xunit.analyzers.tests/TestClassMustBePublicTests.cs index f591063b..5083b8d5 100644 --- a/test/xunit.analyzers.tests/TestClassMustBePublicTests.cs +++ b/test/xunit.analyzers.tests/TestClassMustBePublicTests.cs @@ -1,12 +1,10 @@ using System.Collections.Generic; -using Microsoft.CodeAnalysis.Diagnostics; +using Verify = Xunit.Analyzers.CSharpVerifier; namespace Xunit.Analyzers { public class TestClassMustBePublicTests { - private readonly DiagnosticAnalyzer analyzer = new TestClassMustBePublic(); - private static IEnumerable CreateFactsInNonPublicClassCases() { foreach (var factAttribute in new[] {"Xunit.Fact", "Xunit.Theory"}) @@ -23,9 +21,7 @@ public async void ForPublicClass_DoesNotFindError() { var source = "public class TestClass { [Xunit.Fact] public void TestMethod() { } }"; - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, source); - - Assert.Empty(diagnostics); + await Verify.VerifyAnalyzerAsync(source); } [Theory] @@ -40,14 +36,8 @@ public async void ForFriendOrInternalClass_FindsError( [" + factRelatedAttribute + @"] public void TestMethod() { } }"; - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, source); - - Assert.Collection(diagnostics, - d => - { - Assert.Equal("Test classes must be public", d.GetMessage()); - Assert.Equal("xUnit1000", d.Descriptor.Id); - }); + var expected = Verify.Diagnostic().WithSpan(2, 8 + classAccessModifier.Length, 2, 17 + classAccessModifier.Length); + await Verify.VerifyAnalyzerAsync(source, expected); } [Theory] @@ -66,9 +56,8 @@ [Xunit.Fact] public void Test1() {} [Xunit.Fact] public void Test2() {} } "; - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, source); - Assert.Empty(diagnostics); + await Verify.VerifyAnalyzerAsync(source); } [Theory] @@ -87,9 +76,14 @@ [Xunit.Fact] public void Test1() {} [Xunit.Fact] public void Test2() {} } "; - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, source1, source2); - Assert.Empty(diagnostics); + await new Verify.Test + { + TestState = + { + Sources = { source1, source2 }, + }, + }.RunAsync(); } [Theory] @@ -111,14 +105,9 @@ [Xunit.Fact] public void Test1() {} [Xunit.Fact] public void Test2() {} } "; - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, source); - Assert.Collection(diagnostics, - d => - { - Assert.Equal("Test classes must be public", d.GetMessage()); - Assert.Equal("xUnit1000", d.Descriptor.Id); - }); + var expected = Verify.Diagnostic().WithSpan(2, 16 + part1AccessModifier.Length, 2, 25 + part1AccessModifier.Length).WithSpan(7, 16 + part2AccessModifier.Length, 7, 25 + part2AccessModifier.Length); + await Verify.VerifyAnalyzerAsync(source, expected); } [Theory] @@ -140,14 +129,18 @@ [Xunit.Fact] public void Test1() {} [Xunit.Fact] public void Test2() {} } "; - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, source1, source2); - Assert.Collection(diagnostics, - d => + await new Verify.Test + { + TestState = { - Assert.Equal("Test classes must be public", d.GetMessage()); - Assert.Equal("xUnit1000", d.Descriptor.Id); - }); + Sources = { source1, source2 }, + ExpectedDiagnostics = + { + Verify.Diagnostic().WithSpan(2, 16 + part1AccessModifier.Length, 2, 25 + part1AccessModifier.Length).WithSpan("Test1.cs", 2, 16 + part2AccessModifier.Length, 2, 25 + part2AccessModifier.Length), + }, + }, + }.RunAsync(); } } } diff --git a/test/xunit.analyzers.tests/TestMethodCannotHaveOverloadsTests.cs b/test/xunit.analyzers.tests/TestMethodCannotHaveOverloadsTests.cs index 4935014c..9d845d7f 100644 --- a/test/xunit.analyzers.tests/TestMethodCannotHaveOverloadsTests.cs +++ b/test/xunit.analyzers.tests/TestMethodCannotHaveOverloadsTests.cs @@ -1,101 +1,123 @@ using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.Diagnostics; +using Microsoft.CodeAnalysis.Testing; +using Verify = Xunit.Analyzers.CSharpVerifier; namespace Xunit.Analyzers { public class TestMethodCannotHaveOverloadsTests { - readonly DiagnosticAnalyzer analyzer = new TestMethodCannotHaveOverloads(); - [Fact] public async void FindsErrors_ForInstanceMethodOverloads_InSameInstanceClass() { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = "public class TestClass { " + " [Xunit.Fact]" + " public void TestMethod() { }" + " [Xunit.Theory]" + " public void TestMethod(int a) { }" + - "}"); + "}"; - Assert.Collection(diagnostics, - d => VerifyDiagnostic(d, "TestClass"), - d => VerifyDiagnostic(d, "TestClass")); + DiagnosticResult[] expected = + { + Verify.Diagnostic().WithSpan(1, 56, 1, 66).WithSeverity(DiagnosticSeverity.Error).WithArguments("TestMethod", "TestClass", "TestClass"), + Verify.Diagnostic().WithSpan(1, 104, 1, 114).WithSeverity(DiagnosticSeverity.Error).WithArguments("TestMethod", "TestClass", "TestClass"), + }; + await Verify.VerifyAnalyzerAsync(source, expected); } [Fact] public async void FindsErrors_ForStaticMethodOverloads_InSameStaticClass() { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = "public static class TestClass { " + " [Xunit.Fact]" + " public static void TestMethod() { }" + " [Xunit.Theory]" + " public static void TestMethod(int a) { }" + - "}"); + "}"; - Assert.Collection(diagnostics, - d => VerifyDiagnostic(d, "TestClass"), - d => VerifyDiagnostic(d, "TestClass")); + DiagnosticResult[] expected = + { + Verify.Diagnostic().WithSpan(1, 70, 1, 80).WithSeverity(DiagnosticSeverity.Error).WithArguments("TestMethod", "TestClass", "TestClass"), + Verify.Diagnostic().WithSpan(1, 125, 1, 135).WithSeverity(DiagnosticSeverity.Error).WithArguments("TestMethod", "TestClass", "TestClass"), + }; + await Verify.VerifyAnalyzerAsync(source, expected); } [Fact] public async void FindsErrors_ForInstanceMethodOverload_InDerivedClass() { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, - "public class BaseClass {" + - " [Xunit.Fact]" + - " public void TestMethod() { }" + - "}", - "public class TestClass : BaseClass {" + - " [Xunit.Theory]" + - " public void TestMethod(int a) { }" + - " private void TestMethod(int a, byte c) { }" + - "}"); - - Assert.Collection(diagnostics, - d => VerifyDiagnostic(d, "BaseClass"), - d => VerifyDiagnostic(d, "BaseClass")); + await new Verify.Test + { + TestState = + { + Sources = + { + "public class TestClass : BaseClass {" + + " [Xunit.Theory]" + + " public void TestMethod(int a) { }" + + " private void TestMethod(int a, byte c) { }" + + "}", + "public class BaseClass {" + + " [Xunit.Fact]" + + " public void TestMethod() { }" + + "}", + }, + ExpectedDiagnostics = + { + Verify.Diagnostic().WithSpan(1, 69, 1, 79).WithSeverity(DiagnosticSeverity.Error).WithArguments("TestMethod", "TestClass", "BaseClass"), + Verify.Diagnostic().WithSpan(1, 106, 1, 116).WithSeverity(DiagnosticSeverity.Error).WithArguments("TestMethod", "TestClass", "BaseClass"), + }, + }, + }.RunAsync(); } [Fact] public async void FindsError_ForStaticAndInstanceMethodOverload() { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, - "public class BaseClass {" + - " [Xunit.Fact]" + - " public static void TestMethod() { }" + - "}", - "public class TestClass : BaseClass {" + - " [Xunit.Theory]" + - " public void TestMethod(int a) { }" + - "}"); - - Assert.Collection(diagnostics, - d => VerifyDiagnostic(d, "BaseClass")); + await new Verify.Test + { + TestState = + { + Sources = + { + "public class TestClass : BaseClass {" + + " [Xunit.Theory]" + + " public void TestMethod(int a) { }" + + "}", + "public class BaseClass {" + + " [Xunit.Fact]" + + " public static void TestMethod() { }" + + "}", + }, + ExpectedDiagnostics = + { + Verify.Diagnostic().WithSpan(1, 69, 1, 79).WithSeverity(DiagnosticSeverity.Error).WithArguments("TestMethod", "TestClass", "BaseClass"), + }, + }, + }.RunAsync(); } [Fact] public async void DoesNotFindError_ForMethodOverrides() { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, - "public class BaseClass {" + - " [Xunit.Fact]" + - " public virtual void TestMethod() { }" + - "}", - "public class TestClass : BaseClass {" + - " [Xunit.Fact]" + - " public override void TestMethod() { }" + - "}"); - - Assert.Empty(diagnostics); - } - - private static void VerifyDiagnostic(Diagnostic d, string otherType) - { - Assert.Equal($"Test method 'TestMethod' on test class 'TestClass' has the same name as another method declared on class '{otherType}'.", d.GetMessage()); - Assert.Equal("xUnit1024", d.Descriptor.Id); - Assert.Equal(DiagnosticSeverity.Error, d.Severity); + await new Verify.Test + { + TestState = + { + Sources = + { + "public class BaseClass {" + + " [Xunit.Fact]" + + " public virtual void TestMethod() { }" + + "}", + "public class TestClass : BaseClass {" + + " [Xunit.Fact]" + + " public override void TestMethod() { }" + + "}", + }, + }, + }.RunAsync(); } } } diff --git a/test/xunit.analyzers.tests/TestMethodMustNotHaveMultipleFactAttributesTests.cs b/test/xunit.analyzers.tests/TestMethodMustNotHaveMultipleFactAttributesTests.cs index 1fd771dc..d71cb18e 100644 --- a/test/xunit.analyzers.tests/TestMethodMustNotHaveMultipleFactAttributesTests.cs +++ b/test/xunit.analyzers.tests/TestMethodMustNotHaveMultipleFactAttributesTests.cs @@ -1,49 +1,48 @@ -using Microsoft.CodeAnalysis.Diagnostics; +using Verify = Xunit.Analyzers.CSharpVerifier; namespace Xunit.Analyzers { public class TestMethodMustNotHaveMultipleFactAttributesTests { - readonly DiagnosticAnalyzer analyzer = new TestMethodMustNotHaveMultipleFactAttributes(); - [Theory] [InlineData("Fact")] [InlineData("Theory")] public async void DoesNotFindErrorForMethodWithSingleAttribute(string attribute) { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, - "public class TestClass { [Xunit." + attribute + "] public void TestMethod() { } }"); + var source = + "public class TestClass { [Xunit." + attribute + "] public void TestMethod() { } }"; - Assert.Empty(diagnostics); + await Verify.VerifyAnalyzerAsync(source); } [Fact] public async void FindsErrorForMethodWithTheoryAndFact() { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, - "public class TestClass { [Xunit.Fact, Xunit.Theory] public void TestMethod() { } }"); + var source = + "public class TestClass { [Xunit.Fact, Xunit.Theory] public void TestMethod() { } }"; - Assert.Collection(diagnostics, - d => - { - Assert.Equal("Test methods cannot have multiple Fact or Theory attributes", d.GetMessage()); - Assert.Equal("xUnit1002", d.Descriptor.Id); - }); + var expected = Verify.Diagnostic().WithSpan(1, 65, 1, 75); + await Verify.VerifyAnalyzerAsync(source, expected); } [Fact] public async void FindsErrorForMethodWithCustomFactAttribute() { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, - "public class TestClass { [Xunit.Fact, CustomFact] public void TestMethod() { } }", - "public class CustomFactAttribute : Xunit.FactAttribute { }"); - - Assert.Collection(diagnostics, - d => + await new Verify.Test + { + TestState = { - Assert.Equal("Test methods cannot have multiple Fact or Theory attributes", d.GetMessage()); - Assert.Equal("xUnit1002", d.Descriptor.Id); - }); + Sources = + { + "public class TestClass { [Xunit.Fact, CustomFact] public void TestMethod() { } }", + "public class CustomFactAttribute : Xunit.FactAttribute { }", + }, + ExpectedDiagnostics = + { + Verify.Diagnostic().WithSpan(1, 63, 1, 73), + }, + }, + }.RunAsync(); } } } diff --git a/test/xunit.analyzers.tests/TestMethodShouldNotBeSkippedTests.cs b/test/xunit.analyzers.tests/TestMethodShouldNotBeSkippedTests.cs index e0c00464..0f071949 100644 --- a/test/xunit.analyzers.tests/TestMethodShouldNotBeSkippedTests.cs +++ b/test/xunit.analyzers.tests/TestMethodShouldNotBeSkippedTests.cs @@ -1,20 +1,18 @@ using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.Diagnostics; +using Verify = Xunit.Analyzers.CSharpVerifier; namespace Xunit.Analyzers { public class TestMethodShouldNotBeSkippedTests { - readonly DiagnosticAnalyzer analyzer = new TestMethodShouldNotBeSkipped(); - [Theory] [InlineData("Fact")] [InlineData("Theory")] public async void DoesNotFindErrorForNotSkippedTest(string attribute) { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, "public class TestClass { [Xunit." + attribute + "] public void TestMethod() { } }"); + var source = "public class TestClass { [Xunit." + attribute + "] public void TestMethod() { } }"; - Assert.Empty(diagnostics); + await Verify.VerifyAnalyzerAsync(source); } [Theory] @@ -22,15 +20,10 @@ public async void DoesNotFindErrorForNotSkippedTest(string attribute) [InlineData("Theory")] public async void FindsErrorForSkippedTests(string attribute) { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, "class TestClass { [Xunit." + attribute + "(Skip=\"Lazy\")] public void TestMethod() { } }"); + var source = "class TestClass { [Xunit." + attribute + "(Skip=\"Lazy\")] public void TestMethod() { } }"; - Assert.Collection(diagnostics, - d => - { - Assert.Equal("Test methods should not be skipped", d.GetMessage()); - Assert.Equal("xUnit1004", d.Descriptor.Id); - Assert.Equal(DiagnosticSeverity.Info, d.Severity); - }); + var expected = Verify.Diagnostic().WithSpan(1, 27 + attribute.Length, 1, 38 + attribute.Length).WithSeverity(DiagnosticSeverity.Info); + await Verify.VerifyAnalyzerAsync(source, expected); } } } diff --git a/test/xunit.analyzers.tests/TheoryMethodCannotHaveDefaultParameterTests.cs b/test/xunit.analyzers.tests/TheoryMethodCannotHaveDefaultParameterTests.cs index ca2eb8d5..c757d295 100644 --- a/test/xunit.analyzers.tests/TheoryMethodCannotHaveDefaultParameterTests.cs +++ b/test/xunit.analyzers.tests/TheoryMethodCannotHaveDefaultParameterTests.cs @@ -1,6 +1,12 @@ using System.Threading.Tasks; using Microsoft.CodeAnalysis; +// 2.1.0 does not support default parameter values +using Verify_2_1 = Xunit.Analyzers.CSharpVerifier; + +// 2.2.0 does support default parameter values +using Verify_2_2 = Xunit.Analyzers.CSharpVerifier; + namespace Xunit.Analyzers { public class TheoryMethodCannotHaveDefaultParameterTests @@ -8,35 +14,42 @@ public class TheoryMethodCannotHaveDefaultParameterTests [Fact] public async Task FindsErrorForTheoryWithDefaultParameter_WhenDefaultValueNotSupported() { - // 2.1.0 does not support default parameter values - var analyzer = new TheoryMethodCannotHaveDefaultParameter("2.1.0"); - - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = "class TestClass {" + " [Xunit.Theory] public void TestMethod(int a, string b, string c = \"\") { }" + - "}"); - - Assert.Collection(diagnostics, - d => - { - Assert.Equal("Theory method 'TestMethod' on test class 'TestClass' parameter 'c' cannot have a default value.", d.GetMessage()); - Assert.Equal("xUnit1023", d.Descriptor.Id); - Assert.Equal(DiagnosticSeverity.Error, d.Severity); - }); + "}"; + + var expected = Verify_2_1.Diagnostic().WithSpan(1, 85, 1, 89).WithSeverity(DiagnosticSeverity.Error).WithArguments("TestMethod", "TestClass", "c"); + await Verify_2_1.VerifyAnalyzerAsync(source, expected); } [Fact] public async Task DoesNotFindErrorForTheoryWithDefaultParameter_WhenDefaultValueSupported() { - // 2.2.0 does support default parameter values - var analyzer = new TheoryMethodCannotHaveDefaultParameter("2.2.0"); - - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = "class TestClass {" + " [Xunit.Theory] public void TestMethod(int a, string b, string c = \"\") { }" + - "}"); + "}"; - Assert.Empty(diagnostics); + await Verify_2_2.VerifyAnalyzerAsync(source); + } + + internal class Analyzer_2_1_0 + : TheoryMethodCannotHaveDefaultParameter + { + public Analyzer_2_1_0() + : base("2.1.0") + { + } + } + + internal class Analyzer_2_2_0 + : TheoryMethodCannotHaveDefaultParameter + { + public Analyzer_2_2_0() + : base("2.2.0") + { + } } } } diff --git a/test/xunit.analyzers.tests/TheoryMethodCannotHaveParamsArrayTests.cs b/test/xunit.analyzers.tests/TheoryMethodCannotHaveParamsArrayTests.cs index 0970173e..784f3421 100644 --- a/test/xunit.analyzers.tests/TheoryMethodCannotHaveParamsArrayTests.cs +++ b/test/xunit.analyzers.tests/TheoryMethodCannotHaveParamsArrayTests.cs @@ -1,6 +1,12 @@ using System.Threading.Tasks; using Microsoft.CodeAnalysis; +// 2.1.0 does not support params arrays +using Verify_2_1 = Xunit.Analyzers.CSharpVerifier; + +// 2.2.0 does support params arrays +using Verify_2_2 = Xunit.Analyzers.CSharpVerifier; + namespace Xunit.Analyzers { public class TheoryMethodCannotHaveParamsArrayTests @@ -8,50 +14,64 @@ public class TheoryMethodCannotHaveParamsArrayTests [Fact] public async Task FindsErrorForTheoryWithParamsArrayAsync_WhenParamsArrayNotSupported() { - // 2.1.0 does not support params arrays - var analyzer = new TheoryMethodCannotHaveParamsArray("2.1.0"); - - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = "class TestClass {" + " [Xunit.Theory] public void TestMethod(int a, string b, params string[] c) { }" + - "}"); - - Assert.Collection(diagnostics, - d => - { - Assert.Equal("Theory method 'TestMethod' on test class 'TestClass' cannot have a parameter array 'c'.", d.GetMessage()); - Assert.Equal("xUnit1022", d.Descriptor.Id); - Assert.Equal(DiagnosticSeverity.Error, d.Severity); - }); + "}"; + + var expected = Verify_2_1.Diagnostic().WithSpan(1, 76, 1, 93).WithSeverity(DiagnosticSeverity.Error).WithArguments("TestMethod", "TestClass", "c"); + await Verify_2_1.VerifyAnalyzerAsync(source, expected); } [Fact] public async Task DoesNotFindErrorForTheoryWithParamsArrayAsync_WhenParamsArraySupported() { - // 2.2.0 does support params arrays - var analyzer = new TheoryMethodCannotHaveParamsArray("2.2.0"); - - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + var source = "class TestClass {" + " [Xunit.Theory] public void TestMethod(int a, string b, params string[] c) { }" + - "}"); + "}"; - Assert.Empty(diagnostics); + await Verify_2_2.VerifyAnalyzerAsync(source); } - [Theory] - [InlineData("2.1.0")] - [InlineData("2.2.0")] - public async Task DoesNotFindErrorForTheoryWithNonParamsArrayAsync(string versionString) + [Fact] + public async Task DoesNotFindErrorForTheoryWithNonParamsArrayAsync_WhenParamsArrayNotSupported() { - var analyzer = new TheoryMethodCannotHaveParamsArray(versionString); + var source = + "class TestClass {" + + " [Xunit.Theory] public void TestMethod(int a, string b, string[] c) { }" + + "}"; + + await Verify_2_1.VerifyAnalyzerAsync(source); + } - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, + [Fact] + public async Task DoesNotFindErrorForTheoryWithNonParamsArrayAsync_WhenParamsArraySupported() + { + var source = "class TestClass {" + " [Xunit.Theory] public void TestMethod(int a, string b, string[] c) { }" + - "}"); + "}"; + + await Verify_2_2.VerifyAnalyzerAsync(source); + } - Assert.Empty(diagnostics); + internal class Analyzer_2_1_0 + : TheoryMethodCannotHaveParamsArray + { + public Analyzer_2_1_0() + : base("2.1.0") + { + } + } + + internal class Analyzer_2_2_0 + : TheoryMethodCannotHaveParamsArray + { + public Analyzer_2_2_0() + : base("2.2.0") + { + } } } } diff --git a/test/xunit.analyzers.tests/TheoryMethodMustHaveTestDataTests.cs b/test/xunit.analyzers.tests/TheoryMethodMustHaveTestDataTests.cs index 2bd69262..5cf9b0d7 100644 --- a/test/xunit.analyzers.tests/TheoryMethodMustHaveTestDataTests.cs +++ b/test/xunit.analyzers.tests/TheoryMethodMustHaveTestDataTests.cs @@ -1,17 +1,15 @@ -using Microsoft.CodeAnalysis.Diagnostics; +using Verify = Xunit.Analyzers.CSharpVerifier; namespace Xunit.Analyzers { public class TheoryMethodMustHaveTestDataTests { - readonly DiagnosticAnalyzer analyzer = new TheoryMethodMustHaveTestData(); - [Fact] public async void DoesNotFindErrorForFactMethod() { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, "public class TestClass { [Xunit.Fact] public void TestMethod() { } }"); + var source = "public class TestClass { [Xunit.Fact] public void TestMethod() { } }"; - Assert.Empty(diagnostics); + await Verify.VerifyAnalyzerAsync(source); } [Theory] @@ -20,23 +18,19 @@ public async void DoesNotFindErrorForFactMethod() [InlineData("ClassData(typeof(string))")] public async void DoesNotFindErrorForTheoryMethodWithDataAttributes(string dataAttribute) { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, - "public class TestClass { [Xunit.Theory, Xunit." + dataAttribute + "] public void TestMethod() { } }"); + var source = + "public class TestClass { [Xunit.Theory, Xunit." + dataAttribute + "] public void TestMethod() { } }"; - Assert.Empty(diagnostics); + await Verify.VerifyAnalyzerAsync(source); } [Fact] public async void FindsErrorForTheoryMethodMissingData() { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, "class TestClass { [Xunit.Theory] public void TestMethod() { } }"); + var source = "class TestClass { [Xunit.Theory] public void TestMethod() { } }"; - Assert.Collection(diagnostics, - d => - { - Assert.Equal("Theory methods must have test data", d.GetMessage()); - Assert.Equal("xUnit1003", d.Descriptor.Id); - }); + var expected = Verify.Diagnostic().WithSpan(1, 46, 1, 56); + await Verify.VerifyAnalyzerAsync(source, expected); } } } diff --git a/test/xunit.analyzers.tests/TheoryMethodShouldHaveParametersTests.cs b/test/xunit.analyzers.tests/TheoryMethodShouldHaveParametersTests.cs index c84c6cdb..937b5df9 100644 --- a/test/xunit.analyzers.tests/TheoryMethodShouldHaveParametersTests.cs +++ b/test/xunit.analyzers.tests/TheoryMethodShouldHaveParametersTests.cs @@ -1,39 +1,33 @@ -using Microsoft.CodeAnalysis.Diagnostics; +using Verify = Xunit.Analyzers.CSharpVerifier; namespace Xunit.Analyzers { public class TheoryMethodShouldHaveParametersTests { - readonly DiagnosticAnalyzer analyzer = new TheoryMethodShouldHaveParameters(); - [Fact] public async void DoesNotFindErrorForFactMethod() { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, "public class TestClass { [Xunit.Fact] public void TestMethod() { } }"); + var source = "public class TestClass { [Xunit.Fact] public void TestMethod() { } }"; - Assert.Empty(diagnostics); + await Verify.VerifyAnalyzerAsync(source); } [Fact] public async void DoesNotFindErrorForTheoryMethodWithParameters() { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, - "public class TestClass { [Xunit.Theory] public void TestMethod(string s) { } }"); + var source = + "public class TestClass { [Xunit.Theory] public void TestMethod(string s) { } }"; - Assert.Empty(diagnostics); + await Verify.VerifyAnalyzerAsync(source); } [Fact] public async void FindsErrorForTheoryMethodWithoutParameters() { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(analyzer, "class TestClass { [Xunit.Theory] public void TestMethod() { } }"); + var source = "class TestClass { [Xunit.Theory] public void TestMethod() { } }"; - Assert.Collection(diagnostics, - d => - { - Assert.Equal("Theory methods should have parameters", d.GetMessage()); - Assert.Equal("xUnit1006", d.Descriptor.Id); - }); + var expected = Verify.Diagnostic().WithSpan(1, 46, 1, 56); + await Verify.VerifyAnalyzerAsync(source, expected); } } } diff --git a/test/xunit.analyzers.tests/TheoryMethodShouldUseAllParametersTests.cs b/test/xunit.analyzers.tests/TheoryMethodShouldUseAllParametersTests.cs index db844cde..262185e3 100644 --- a/test/xunit.analyzers.tests/TheoryMethodShouldUseAllParametersTests.cs +++ b/test/xunit.analyzers.tests/TheoryMethodShouldUseAllParametersTests.cs @@ -1,51 +1,31 @@ -using System.Collections.Generic; -using System.Linq; -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.Diagnostics; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.Testing; +using Verify = Xunit.Analyzers.CSharpVerifier; namespace Xunit.Analyzers { public class TheoryMethodShouldUseAllParametersTests { - private static DiagnosticAnalyzer Analyzer { get; } = new TheoryMethodShouldUseAllParameters(); - - private static void CheckDiagnostics(IEnumerable diagnostics, params (string method, string type, string parameter)[] messageArgs) - { - var diagnosticArray = diagnostics.ToArray(); - Assert.Equal(messageArgs.Length, diagnosticArray.Length); - - for (var i = 0; i < messageArgs.Length; i++) - { - var (method, type, parameter) = messageArgs[i]; - var message = $"Theory method '{method}' on test class '{type}' does not use parameter '{parameter}'."; - - var diagnostic = diagnosticArray[i]; - Assert.Equal(message, diagnostic.GetMessage()); - Assert.Equal("xUnit1026", diagnostic.Id); - Assert.Equal(DiagnosticSeverity.Warning, diagnostic.Severity); - } - } - [Fact] public async void FindsWarning_ParameterNotReferenced() { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(Analyzer, @" + var source = @" using Xunit; class TestClass { [Theory] void TestMethod(int unused) { } -}"); +}"; - CheckDiagnostics(diagnostics, - (method: "TestMethod", type: "TestClass", parameter: "unused")); + var expected = Verify.Diagnostic().WithSpan(7, 25, 7, 31).WithSeverity(DiagnosticSeverity.Warning).WithArguments("TestMethod", "TestClass", "unused"); + await Verify.VerifyAnalyzerAsync(source, expected); } [Fact] public async void FindsWarning_ParameterUnread() { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(Analyzer, @" + var source = @" using System; using Xunit; @@ -57,34 +37,37 @@ void TestMethod(int unused) unused = 3; int.TryParse(""123"", out unused); } -}"); +}"; - CheckDiagnostics(diagnostics, - (method: "TestMethod", type: "TestClass", parameter: "unused")); + var expected = Verify.Diagnostic().WithSpan(8, 25, 8, 31).WithSeverity(DiagnosticSeverity.Warning).WithArguments("TestMethod", "TestClass", "unused"); + await Verify.VerifyAnalyzerAsync(source, expected); } [Fact] public async void FindsWarning_MultipleUnreadParameters() { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(Analyzer, @" + var source = @" using Xunit; class TestClass { [Theory] void TestMethod(int foo, int bar, int baz) { } -}"); +}"; - CheckDiagnostics(diagnostics, - (method: "TestMethod", type: "TestClass", parameter: "foo"), - (method: "TestMethod", type: "TestClass", parameter: "bar"), - (method: "TestMethod", type: "TestClass", parameter: "baz")); + DiagnosticResult[] expected = + { + Verify.Diagnostic().WithSpan(7, 25, 7, 28).WithSeverity(DiagnosticSeverity.Warning).WithArguments("TestMethod", "TestClass", "foo"), + Verify.Diagnostic().WithSpan(7, 34, 7, 37).WithSeverity(DiagnosticSeverity.Warning).WithArguments("TestMethod", "TestClass", "bar"), + Verify.Diagnostic().WithSpan(7, 43, 7, 46).WithSeverity(DiagnosticSeverity.Warning).WithArguments("TestMethod", "TestClass", "baz"), + }; + await Verify.VerifyAnalyzerAsync(source, expected); } [Fact] public async void FindsWarning_SomeUnreadParameters() { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(Analyzer, @" + var source = @" using System; using Xunit; @@ -96,33 +79,36 @@ void TestMethod(int foo, int bar, int baz) Console.WriteLine(bar); baz = 3; } -}"); +}"; - CheckDiagnostics(diagnostics, - (method: "TestMethod", type: "TestClass", parameter: "foo"), - (method: "TestMethod", type: "TestClass", parameter: "baz")); + DiagnosticResult[] expected = + { + Verify.Diagnostic().WithSpan(8, 25, 8, 28).WithSeverity(DiagnosticSeverity.Warning).WithArguments("TestMethod", "TestClass", "foo"), + Verify.Diagnostic().WithSpan(8, 43, 8, 46).WithSeverity(DiagnosticSeverity.Warning).WithArguments("TestMethod", "TestClass", "baz"), + }; + await Verify.VerifyAnalyzerAsync(source, expected); } [Fact] public async void FindsWarning_ExpressionBodiedMethod() { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(Analyzer, @" + var source = @" using Xunit; class TestClass { [Theory] void TestMethod(int unused) => Assert.Equal(5, 2 + 2); -}"); +}"; - CheckDiagnostics(diagnostics, - (method: "TestMethod", type: "TestClass", parameter: "unused")); + var expected = Verify.Diagnostic().WithSpan(7, 25, 7, 31).WithSeverity(DiagnosticSeverity.Warning).WithArguments("TestMethod", "TestClass", "unused"); + await Verify.VerifyAnalyzerAsync(source, expected); } [Fact] public async void DoesNotFindWarning_ParameterRead() { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(Analyzer, @" + var source = @" using System; using Xunit; @@ -133,39 +119,39 @@ void TestMethod(int used) { Console.WriteLine(used); } -}"); +}"; - CheckDiagnostics(diagnostics); + await Verify.VerifyAnalyzerAsync(source); } [Fact] public async void DoesNotFindWarning_ExpressionBodiedMethod() { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(Analyzer, @" + var source = @" using Xunit; class TestClass { [Theory] void TestMethod(int used) => Assert.Equal(used, 2 + 2); -}"); +}"; - CheckDiagnostics(diagnostics); + await Verify.VerifyAnalyzerAsync(source); } [Fact] public async void DoesNotCrash_MethodWithoutBody() { - var diagnostics = await CodeAnalyzerHelper.GetDiagnosticsAsync(Analyzer, @" + var source = @" using Xunit; class TestClass { [Theory] extern void TestMethod(int foo); -}"); +}"; - CheckDiagnostics(diagnostics); + await Verify.VerifyAnalyzerAsync(source); } } } diff --git a/test/xunit.analyzers.tests/xunit.analyzers.tests.csproj b/test/xunit.analyzers.tests/xunit.analyzers.tests.csproj index c5792f34..bb9b9727 100644 --- a/test/xunit.analyzers.tests/xunit.analyzers.tests.csproj +++ b/test/xunit.analyzers.tests/xunit.analyzers.tests.csproj @@ -11,6 +11,7 @@ + diff --git a/tools/DocBuilder/DocBuilder.csproj b/tools/DocBuilder/DocBuilder.csproj index 34490c95..762fe7e6 100644 --- a/tools/DocBuilder/DocBuilder.csproj +++ b/tools/DocBuilder/DocBuilder.csproj @@ -10,6 +10,10 @@ true + + + +