Skip to content

Commit

Permalink
tests: add examples for excluding assert methods from analyzer (#376)
Browse files Browse the repository at this point in the history
  • Loading branch information
Meir017 authored Jul 12, 2024
1 parent e8a770e commit 727aa74
Show file tree
Hide file tree
Showing 11 changed files with 143 additions and 42 deletions.
9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,15 @@ dotnet add package FluentAssertions.Analyzers
- [NUnit3 Analyzer Docs](docs/Nunit3Analyzer.md)
- [Xunit Analyzer Docs](docs/XunitAnalyzer.md)

## Configuration

© Thanks to https://github.com/meziantou/Meziantou.FluentAssertionsAnalyzers

You can exclude assertion methods using the .editorconfig file:

[*.cs]
ffa_excluded_methods=M:NUnit.Framework.Assert.Fail;M:NUnit.Framework.Assert.Fail(System.String)

## Getting Started

### Build
Expand Down
13 changes: 13 additions & 0 deletions src/FluentAssertions.Analyzers.TestUtils/CsProjectArguments.cs
Original file line number Diff line number Diff line change
@@ -1,12 +1,19 @@
using System;
using System.Collections.Generic;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Diagnostics;

namespace FluentAssertions.Analyzers.TestUtils;

public class CsProjectArguments
{
public TargetFramework TargetFramework { get; set; } = TargetFramework.Net8_0;
public string[] Sources { get; set; }
public PackageReference[] PackageReferences { get; set; } = Array.Empty<PackageReference>();
public string Language { get; set; } = LanguageNames.CSharp;
public Dictionary<string, string> AnalyzerConfigOptions { get; } = new();

public AnalyzerConfigOptionsProvider CreateAnalyzerConfigOptionsProvider() => new TestAnalyzerConfigOptionsProvider(AnalyzerConfigOptions);
}

public static class CsProjectArgumentsExtensions
Expand All @@ -28,4 +35,10 @@ public static TCsProjectArguments WithPackageReferences<TCsProjectArguments>(thi
arguments.PackageReferences = packageReferences;
return arguments;
}

public static TCsProjectArguments WithAnalyzerConfigOption<TCsProjectArguments>(this TCsProjectArguments arguments, string name, string value) where TCsProjectArguments : CsProjectArguments
{
arguments.AnalyzerConfigOptions[name] = value;
return arguments;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// <copyright file="TestAnalyzerConfigOptionsProvider.cs">
// Copyright (c) 2022 All Rights Reserved
// </copyright>
// <author>Gérald Barré - https://github.com/meziantou</author>

using System.Collections.Generic;
using System.Collections.Immutable;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Diagnostics;

namespace FluentAssertions.Analyzers.TestUtils;

public sealed class TestAnalyzerConfigOptionsProvider : AnalyzerConfigOptionsProvider
{
public static TestAnalyzerConfigOptionsProvider Empty { get; } = new(ImmutableDictionary<string, string>.Empty);

private readonly IDictionary<string, string> _values;
public TestAnalyzerConfigOptionsProvider(IDictionary<string, string> values) => _values = values;

public override AnalyzerConfigOptions GlobalOptions => new TestAnalyzerConfigOptions(_values);
public override AnalyzerConfigOptions GetOptions(SyntaxTree tree) => new TestAnalyzerConfigOptions(_values);
public override AnalyzerConfigOptions GetOptions(AdditionalText textFile) => new TestAnalyzerConfigOptions(_values);

private sealed class TestAnalyzerConfigOptions : AnalyzerConfigOptions
{
private readonly IDictionary<string, string> _values;

public TestAnalyzerConfigOptions(IDictionary<string, string> values) => _values = values;

public override bool TryGetValue(string key, out string value)
{
return _values.TryGetValue(key, out value);
}
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Collections.Generic;
using FluentAssertions.Analyzers.TestUtils;
using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.Diagnostics;

Expand Down
8 changes: 5 additions & 3 deletions src/FluentAssertions.Analyzers.Tests/DiagnosticVerifier.cs
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,9 @@ private static string GetStringFromDocument(Document document)
/// <param name="analyzers">The analyzer to run on the documents</param>
/// <param name="documents">The Documents that the analyzer will be run on</param>
/// <returns>An IEnumerable of Diagnostics that surfaced in the source code, sorted by Location</returns>
private static Diagnostic[] GetSortedDiagnosticsFromDocuments(DiagnosticAnalyzer[] analyzers, Document[] documents)
private static Diagnostic[] GetSortedDiagnosticsFromDocuments(DiagnosticAnalyzer[] analyzers, Document[] documents) => GetSortedDiagnosticsFromDocuments(analyzers, TestAnalyzerConfigOptionsProvider.Empty, documents);

private static Diagnostic[] GetSortedDiagnosticsFromDocuments(DiagnosticAnalyzer[] analyzers, AnalyzerConfigOptionsProvider analyzerConfigOptions, Document[] documents)
{
var projects = new HashSet<Project>();
foreach (var document in documents)
Expand All @@ -228,7 +230,7 @@ private static Diagnostic[] GetSortedDiagnosticsFromDocuments(DiagnosticAnalyzer
["CS1705"] = ReportDiagnostic.Suppress,
["CS8019"] = ReportDiagnostic.Suppress // TODO: Unnecessary using directive
}))
.WithAnalyzers(ImmutableArray.Create(analyzers));
.WithAnalyzers(ImmutableArray.Create(analyzers), new AnalyzerOptions(ImmutableArray<AdditionalText>.Empty, analyzerConfigOptions));
var relevantDiagnostics = compilationWithAnalyzers.GetAnalyzerDiagnosticsAsync().Result;

var allDiagnostics = compilationWithAnalyzers.GetAllDiagnosticsAsync().Result;
Expand Down Expand Up @@ -291,7 +293,7 @@ public static void VerifyDiagnostic(DiagnosticVerifierArguments arguments)
var project = CsProjectGenerator.CreateProject(arguments);
var documents = project.Documents.ToArray();

var diagnostics = GetSortedDiagnosticsFromDocuments(arguments.DiagnosticAnalyzers.ToArray(), documents);
var diagnostics = GetSortedDiagnosticsFromDocuments(arguments.DiagnosticAnalyzers.ToArray(), arguments.CreateAnalyzerConfigOptionsProvider(), documents);
VerifyDiagnosticResults(diagnostics, arguments.DiagnosticAnalyzers.ToArray(), arguments.ExpectedDiagnostics.ToArray());
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using FluentAssertions.Analyzers.TestUtils;
using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.VisualStudio.TestTools.UnitTesting;

Expand Down
14 changes: 14 additions & 0 deletions src/FluentAssertions.Analyzers.Tests/Tips/MsTestTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,20 @@ namespace FluentAssertions.Analyzers.Tests.Tips
[TestClass]
public class MsTestTests
{
[TestMethod]
[Implemented]
public void SupportExcludingMethods()
{
var source = GenerateCode.MsTestAssertion("bool actual", "Assert.IsTrue(actual);");
DiagnosticVerifier.VerifyDiagnostic(new DiagnosticVerifierArguments()
.WithAllAnalyzers()
.WithSources(source)
.WithPackageReferences(PackageReference.FluentAssertions_6_12_0, PackageReference.MSTestTestFramework_3_1_1)
.WithAnalyzerConfigOption("ffa_excluded_methods", "M:Microsoft.VisualStudio.TestTools.UnitTesting.Assert.IsTrue(System.Boolean)")
.WithExpectedDiagnostics()
);
}

[DataTestMethod]
[AssertionDiagnostic("Assert.Inconclusive({0});")]
[AssertionDiagnostic("Assert.Fail({0});")]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using FluentAssertions.Analyzers.TestUtils;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Text;

namespace FluentAssertions.Analyzers.Tests.Tips
Expand Down
22 changes: 17 additions & 5 deletions src/FluentAssertions.Analyzers.Tests/Tips/NunitTests.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
using System;
using System.Collections;
using System.Collections.Generic;
using FluentAssertions.Analyzers.TestUtils;
using Microsoft.CodeAnalysis;
using Microsoft.VisualStudio.TestTools.UnitTesting;
Expand All @@ -10,6 +8,20 @@ namespace FluentAssertions.Analyzers.Tests.Tips;
[TestClass]
public class NunitTests
{
[TestMethod]
[Implemented]
public void SupportExcludingMethods()
{
var source = GenerateCode.Nunit3Assertion("bool actual", "Assert.IsTrue(actual);");
DiagnosticVerifier.VerifyDiagnostic(new DiagnosticVerifierArguments()
.WithAllAnalyzers()
.WithSources(source)
.WithPackageReferences(PackageReference.FluentAssertions_6_12_0, PackageReference.Nunit_3_14_0)
.WithAnalyzerConfigOption("ffa_excluded_methods", "M:NUnit.Framework.Assert.IsTrue(System.Boolean)")
.WithExpectedDiagnostics()
);
}

#region Assert.cs

[DataTestMethod]
Expand Down Expand Up @@ -1705,7 +1717,7 @@ public void Nunit4_CollectionAssertDoesNotContain_TestCodeFix(string oldAssertio
Nunit4VerifyFix("object expected, List<object> actual", oldAssertion, newAssertion);
Nunit4VerifyFix("DateTime expected, DateTime[] actual", oldAssertion, newAssertion);
Nunit4VerifyFix("DateTime expected, List<DateTime> actual", oldAssertion, newAssertion);
}
}

[DataTestMethod]
[AssertionMethodCodeFix(
Expand Down Expand Up @@ -1775,7 +1787,7 @@ public void Nunit4_CollectionAssertDoesNotContain_WithCasting_TestCodeFix(string
[AssertionDiagnostic("Assert.That(actual, Has.All.InstanceOf<int>(){0});")]
[AssertionDiagnostic("Assert.That(actual, Has.All.InstanceOf(type){0});")]
[Implemented]
public void Nunit3_CollectionAssertAllItemsAreInstancesOfType_TestAnalyzer(string assertion) => Nunit3VerifyDiagnostic("IEnumerable<string> actual, Type type", assertion);
public void Nunit3_CollectionAssertAllItemsAreInstancesOfType_TestAnalyzer(string assertion) => Nunit3VerifyDiagnostic("IEnumerable<string> actual, Type type", assertion);

[DataTestMethod]
[AssertionDiagnostic("CollectionAssert.AllItemsAreInstancesOfType(actual, typeof(string){0});")]
Expand All @@ -1787,7 +1799,7 @@ public void Nunit4_CollectionAssertDoesNotContain_WithCasting_TestCodeFix(string
[AssertionDiagnostic("Assert.That(actual, Has.All.InstanceOf<int>());")]
[AssertionDiagnostic("Assert.That(actual, Has.All.InstanceOf(type));")]
[Implemented]
public void Nunit4_CollectionAssertAllItemsAreInstancesOfType_TestAnalyzer(string assertion) => Nunit4VerifyDiagnostic("IEnumerable<string> actual, Type type", assertion);
public void Nunit4_CollectionAssertAllItemsAreInstancesOfType_TestAnalyzer(string assertion) => Nunit4VerifyDiagnostic("IEnumerable<string> actual, Type type", assertion);

[DataTestMethod]
[AssertionCodeFix(
Expand Down
Loading

0 comments on commit 727aa74

Please sign in to comment.