SpecFlow icon indicating copy to clipboard operation
SpecFlow copied to clipboard

SpecFlow.NUnit tests do not work when LifeCycle.InstancePerTestCase is configured on assembly-level

Open johannes-schmitt opened this issue 4 years ago • 1 comments

SpecFlow Version

3.9.8

Which test runner are you using?

NUnit

Test Runner Version Number

4.0.0

.NET Implementation

equal or greater .NET Framework 4.6.1

Project Format of the SpecFlow project

Classic project format using <PackageReference> tags

.feature.cs files are generated using

SpecFlow.Tools.MsBuild.Generation NuGet package

Test Execution Method

Visual Studio Test Explorer

SpecFlow Section in app.config or content of specflow.json

Issue Description

NUnit 3.13 introduced FixtureLifeCycle. Configuring "instance per test" as default for the whole assembly/project can be done via [assembly: FixtureLifeCycle(LifeCycle.InstancePerTestCase)] attribute. Unfortunately, the generated tests by the SpecFlow.NUnit are not compatible with this, because it requires NUnit's OneTimeSetup and OneTimeTeardown to be static.

This scenario might sound a bit strange, but our team actually faces this. We have a test project that is configured to use LifeCycle.InstancePerTestCase in the whole project as described. Our tests are not using SpecFlow so far, but we slowly want to migrate to SpecFlow for those test cases. Our current workaround is to apply the LifeCycle.InstancePerTestCase attribute to all non-SpecFlow NUnit tests.

Steps to Reproduce

Steps

  1. create a new .NET Framework project (target framework version does not matter, I used .NET 4.8)
  2. reference nuget packages SpecFlow.Nunit.Runners (or install latest versions of this dependency package manually)
  3. create a dummy feature file with an empty scenario (no Given/When/Then steps required)
  4. add attribute [assembly: NUnit.Framework.FixtureLifeCycle(NUnit.Framework.LifeCycle.InstancePerTestCase)] (e.g. to AssemblyInfo.cs)
  5. build the project
  6. run the tests with the Visual Studio test runner

Expected: test succeeds Actual: test fails with error message

OneTimeSetUp: System.InvalidOperationException : Only static OneTimeSetUp and OneTimeTearDown are allowed for InstancePerTestCase mode.

Link to Repro Project

No response

johannes-schmitt avatar Jul 16 '21 14:07 johannes-schmitt

another workaround we came up with is a custom MSBuild target to set the FixtureLifeCycle attribute after SpecFlow generated the source files, like this:

<!-- workaround for https://github.com/SpecFlowOSS/SpecFlow/issues/2466 -->
<Target Name="SpecflowAdjustFixtureLifeCycle" BeforeTargets="CoreCompile" AfterTargets="GenerateFeatureFileCodeBehindTask">
  <WriteLinesToFile
      File="%(SpecFlowGeneratedFiles.Identity)"
      Lines="$([System.IO.File]::ReadAllText(%(SpecFlowGeneratedFiles.Identity)).Replace('TestFixtureAttribute()','TestFixtureAttribute(), NUnit.Framework.FixtureLifeCycle(NUnit.Framework.LifeCycle.SingleInstance)'))"
      Overwrite="true"
      Encoding="Unicode"/>
</Target>

johannes-schmitt avatar Jul 16 '21 15:07 johannes-schmitt