Skip to content

Commit

Permalink
Do not raise NUnit1032 if Fixture uses LifeCycle.InstancePerTestCase
Browse files Browse the repository at this point in the history
  • Loading branch information
manfred-brands committed Sep 24, 2023
1 parent c6175b3 commit 2145034
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 12 deletions.
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using System.Threading.Tasks;
using Gu.Roslyn.Asserts;
using Microsoft.CodeAnalysis.Diagnostics;
using NUnit.Analyzers.Constants;
Expand Down Expand Up @@ -742,5 +743,33 @@ private sealed class DummyAsyncWriter : IAsyncDisposable
RoslynAssert.Valid(analyzer, testCode);
}
#endif

[Test]
public void ShouldNotAnalyzeWhenInstancePerTestCase()
{
var testCode = TestUtility.WrapClassInNamespaceAndAddUsing(@$"
[FixtureLifeCycle(LifeCycle.InstancePerTestCase)]
public class TestClass
{{
private readonly IDisposable? field;
public TestClass()
{{
field = new DummyDisposable();
}}
[Test]
public void Test()
{{
Assert.That(field, Is.Not.Null);
}}
{DummyDisposable}
}}
");

// InstancePerTestCase mean test should use IDisposable
RoslynAssert.Valid(analyzer, testCode);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -45,18 +45,10 @@ public override void ReportSuppressions(SuppressionAnalysisContext context)

if (typeSymbol is not null)
{
// Is the class set up for a InstancePerTestCase
AttributeData? fixtureLifeCycleAttribute = typeSymbol.GetAllAttributes().FirstOrDefault(x => x.IsFixtureLifeCycleAttribute(context.Compilation));
if (fixtureLifeCycleAttribute is not null &&
fixtureLifeCycleAttribute.ConstructorArguments.Length == 1 &&
fixtureLifeCycleAttribute.ConstructorArguments[0] is TypedConstant typeConstant &&
typeConstant.Kind == TypedConstantKind.Enum &&
typeConstant.Type.IsType(NUnitFrameworkConstants.FullNameOfLifeCycle, context.Compilation) &&
typeConstant.Value is 1 /* LifeCycle.InstancePerTestCase */)
if (typeSymbol.IsInstancePerTestCaseFixture(context.Compilation))
{
// If a TestFixture used InstancePerTestCase, it should be IDisposable
if (diagnostic.Descriptor.Id == TypesThatOwnDisposableFieldsShouldHaveATearDown.SuppressedDiagnosticId)
continue;
continue;
}

if (typeSymbol.IsTestFixture(context.Compilation))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,9 +69,10 @@ private static void AnalyzeDisposableFields(SyntaxNodeAnalysisContext context)
return;
}

if (!typeSymbol.GetMembers().OfType<IMethodSymbol>().Any(m => m.IsTestRelatedMethod(context.Compilation)))
if (typeSymbol.IsInstancePerTestCaseFixture(context.Compilation) ||
!typeSymbol.IsTestFixture(context.Compilation))
{
// Not a TestFixture, CA1812 should have picked this up.
// CA1001 should picked this up. Assuming it is enabled.
return;
}

Expand Down
13 changes: 13 additions & 0 deletions src/nunit.analyzers/Extensions/IMethodSymbolExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System.Linq;
using Microsoft.CodeAnalysis;
using NUnit.Analyzers.Constants;

namespace NUnit.Analyzers.Extensions
{
Expand Down Expand Up @@ -72,5 +73,17 @@ internal static bool IsTestFixture(this ITypeSymbol typeSymbol, Compilation comp
{
return typeSymbol.GetMembers().OfType<IMethodSymbol>().Any(m => m.IsTestRelatedMethod(compilation));
}

internal static bool IsInstancePerTestCaseFixture(this ITypeSymbol typeSymbol, Compilation compilation)
{
// Is there a FixtureLifeCycleAttribute?
AttributeData? fixtureLifeCycleAttribute = typeSymbol.GetAllAttributes().FirstOrDefault(x => x.IsFixtureLifeCycleAttribute(compilation));
return fixtureLifeCycleAttribute is not null &&
fixtureLifeCycleAttribute.ConstructorArguments.Length == 1 &&
fixtureLifeCycleAttribute.ConstructorArguments[0] is TypedConstant typeConstant &&
typeConstant.Kind == TypedConstantKind.Enum &&
typeConstant.Type.IsType(NUnitFrameworkConstants.FullNameOfLifeCycle, compilation) &&
typeConstant.Value is 1 /* LifeCycle.InstancePerTestCase */;
}
}
}

0 comments on commit 2145034

Please sign in to comment.