SpecFlow icon indicating copy to clipboard operation
SpecFlow copied to clipboard

MSBuild always regenerates code-behind .cs files

Open flcdrg opened this issue 5 years ago • 17 comments

SpecFlow Version:

  • [x] 3.1
  • [ ] 3.0
  • [ ] 2.4
  • [ ] 2.3
  • [ ] 2.2
  • [ ] 2.1
  • [ ] 2.0
  • [ ] 1.9

Used Test Runner

  • [ ] SpecFlow+Runner
  • [ ] MSTest
  • [ ] NUnit
  • [x] Xunit

Version number: 3.1.67

Project Format of the SpecFlow project

  • [ ] Classic project format using packages.config
  • [ ] Classic project format using <PackageReference> tags
  • [x] Sdk-style project format

.feature.cs files are generated using

  • [x] SpecFlow.Tools.MsBuild.Generation NuGet package
  • [ ] SpecFlowSingleFileGenerator custom tool

Visual Studio Version

  • [x] VS 2019
  • [ ] VS 2017
  • [ ] VS 2015

Enable SpecFlowSingleFileGenerator Custom Tool option in Visual Studio extension settings

  • [ ] Enabled
  • [x] Disabled

Are the latest Visual Studio updates installed?

  • [x] Yes
  • [ ] No, I use Visual Studio version <Major>.<Minor>.<Patch>

.NET Framework:

  • [ ] >= .NET 4.5
  • [ ] before .NET 4.5
  • [ ] .NET Core 2.0
  • [ ] .NET Core 2.1
  • [ ] .NET Core 2.2
  • [x] .NET Core 3.0

Test Execution Method:

  • [x] Visual Studio Test Explorer
  • [ ] TFS/VSTS/Azure DevOps – Task – PLEASE SPECIFY THE NAME OF THE TASK
  • [ ] Command line – PLEASE SPECIFY THE FULL COMMAND LINE

Issue Description

It appears that the current implementation of the UpdateFeatureFilesInProject target in SpecFlow.Tools.MsBuild.Generation.targets means that feature.cs files will be regenerated every time the project builds, regardless of whether any source .feature file has changed.

Is there a reason why incremental building isn't supported?

(If there isn't, then I'd be up for having a go at adding it)

flcdrg avatar Dec 17 '19 05:12 flcdrg

I found that @david1995 removed this back in https://github.com/techtalk/SpecFlow/commit/70a9b366d5ac7dc1c47e1dbec80699bcfc955643.

Was there a problem with the inputs/outputs?

flcdrg avatar Dec 18 '19 23:12 flcdrg

The problem was, that Inputs/Outputs checks only for existence of the files and not the content. That makes us problems, as there are some configs that adjust the generated code.

We have an optimization in the code, that we only write to the filesystem when the content changed. It is here: https://github.com/techtalk/SpecFlow/blob/master/SpecFlow.Tools.MsBuild.Generation/CodeBehindWriter.cs#L17

SabotageAndi avatar Dec 19 '19 11:12 SabotageAndi

Inputs / Outputs also compares file modification times, so that would be the equivalent of when the content changes.

I suspect a problem with the linked code is it still does the processing so there's still a performance impact, even if it doesn't write the changes.

flcdrg avatar Dec 19 '19 11:12 flcdrg

What configuration values is it dependant on? If using Inputs/Outputs is a problem because of configuration values, you could make a hash of all those values and write the hash to a cache file that you use as additional inputs to the target to determine if UpdateFeatureFilesInProject should incrementally built. Then it will also be triggered when configuration changes (as well as feature files).

This is how the assemblyinfo is generated only if the version and other properties are changed: https://github.com/dotnet/sdk/blob/18ee4eac8b3abe6d554d2e0c39d8952da0f23ce5/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.GenerateAssemblyInfo.targets#L134

Used here as Inputs: https://github.com/dotnet/sdk/blob/18ee4eac8b3abe6d554d2e0c39d8952da0f23ce5/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.GenerateAssemblyInfo.targets#L152

pergardebrink avatar Aug 15 '20 02:08 pergardebrink

Would definitely like to see this fixed. Not allowing MSBuild to figure out that there's nothing to do means builds are much more inefficient.

flcdrg avatar Aug 15 '20 05:08 flcdrg

Hi, What is the status of this issue ? Is there a temporary solution ?

Regards

reegeek avatar Apr 02 '21 10:04 reegeek

Hi, What is the status of this issue ? Is there a temporary solution ?

Regards

I think I fixed this in https://github.com/SpecFlowOSS/SpecFlow/pull/2094 but it was a long time ago, so not sure it was the same issue? My fix didn't write the files unless it had to..

Are you seeing this issue still?

pergardebrink avatar Apr 02 '21 10:04 pergardebrink

@reegeek Nothing changed and no there is no temporary solution.

@pergardebrink If I remember correctly, it is about that the MSBuild task is called at all.

SabotageAndi avatar Apr 02 '21 11:04 SabotageAndi

But as SpecFlow is Open Source and you are annoyed with this issue, please submit a PR to fix it. We are only a small team and can't do everything. SpecFlow is dependent on the contributions of its users.

Next week we are having again an open-source iteration (https://specflow.org/blog/our-second-open-source-iteration-starts-next-week/). The whole team will be available to mentor future contributors and help them with their change to SpecFlow.

SabotageAndi avatar Apr 02 '21 11:04 SabotageAndi

If someone wanted to test this locally, find your local copy of SpecFlow.Tools.MsBuild.Generation.targets and revert the change made in the commit mentioned above and see if it behaves correctly. If it does, then consider raising a PR.

I've moved onto different work that isn't using SpecFlow at the moment, otherwise I'd do it myself.

flcdrg avatar Apr 05 '21 22:04 flcdrg

I will made the test and maybe raising a PR.

reegeek avatar Apr 06 '21 07:04 reegeek

Thanks, @reegeek for the PR, but it is only adding the Inputs/Outputs to the target, which as already written is not enough.

The generated code is not only dependent on the input files, but also on:

  • used unit test framework (via NuGet package)
  • some config values in the generator section (https://docs.specflow.org/projects/specflow/en/latest/Installation/Configuration.html#generator)

When I would change one of these, the target wouldn't be called at all and the user is stuck with the old generated code.

So something like @pergardebrink suggested would be necessary to handle this cases.

SabotageAndi avatar Apr 06 '21 12:04 SabotageAndi

Ok, if I understand well: If unit test framework changes, we must regenerate output files. How to know which config values should regenerate files ?

reegeek avatar Apr 06 '21 13:04 reegeek

The generator section has two possible properties and both of them (allowDebugGeneratedFiles, allowRowTests) adjust the generated code.

SabotageAndi avatar Apr 06 '21 14:04 SabotageAndi

ok. If we add in "app.config" file and "specflow.json" file Inputs, I think it is solving the second point.

reegeek avatar Apr 06 '21 15:04 reegeek

Yes, that could be enough.

SabotageAndi avatar Apr 06 '21 15:04 SabotageAndi

Hi, I add configuration files and plugins files in inputs.

  <ItemGroup>
    <!-- features files -->
    <UpdateFeatureFilesInProjectInputs Include="@(SpecFlowFeatureFiles)"/>
    <!-- configuration files -->
    <UpdateFeatureFilesInProjectInputs Include="**\specflow.json"/>
    <UpdateFeatureFilesInProjectInputs Include="**\app.config" />
    <!-- plugin files -->
    <UpdateFeatureFilesInProjectInputs Include="@(SpecFlowGeneratorPlugins)"/>
  </ItemGroup>

@SabotageAndi I think it is enough.

reegeek avatar Apr 12 '21 09:04 reegeek