Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rewrite xunit tasks #800

Merged
merged 3 commits into from
May 20, 2015
Merged

Conversation

neoeinstein
Copy link
Contributor

This pull request supersedes #798 and proposes a fix for #797.

Changes in the xUnit and xUnit2 tasks are breaking. There is an addition of an xUnitSingle task which explicitly indicates that it takes a single assembly for xUnit testing to allow a consumer to have more control over how the target is consumed since xUnit v1 only accepts one assembly at a time.

This PR also includes changes to allow specifying the reporting file names for HTML, XML, and NUnit-style reports as well as additional documentation and some refactoring to limit the exposed interface. Changes relevant to each task have been staged as separate commits.

Specifications have been added to the test project for all of these changes. Once merged, consumers who used the following xUnit parameters will break:

  • XUnitParams
    • ConfigFile - Removed: Was not being used anyway
    • HtmlOutput - Removed: Pass in report file name path as HtmlOutputPath
    • XmlOutput - Removed: Pass in report file name path as XmlOutputPath
    • NUnitXmlOutput - Removed: Pass in report file name path as NUnitXmlOutputPath
    • WorkingDir - Type change: Now accepts a string option
    • Verbose - Removed: Pass in inverted value as Silent
    • OutputDir - Removed: No longer used
    • IncludeTraits - Type change: Now accepts a list of name-value tuples
    • ExcludeTraits - Type change: Now accepts a list of name-value tuples
  • XUnit2Params
    • ConfigFile - Removed: Was not being used anyway
    • Parallel - Type change: Now accepts a discriminated union ParallelOption
    • MaxThreads - Type change: Now accepts a discriminated union MaxThreadsOption
    • HtmlOutput - Removed: Pass in report file name path as HtmlOutputPath
    • XmlOutput - Removed: Pass in report file name path as XmlOutputPath
    • XmlV1Output - Removed: Pass in report file name path as XmlV1OutputPath
    • WorkingDir - Type change: Now accepts a string option
    • OutputDir - Removed: No longer used
    • IncludeTraits - Type change: Now accepts a list of name-value tuples
    • ExcludeTraits - Type change: Now accepts a list of name-value tuples
    • Teamcity - Renamed: ForceTeamCity
    • Appveyor - Renamed: ForceAppVeyor

@neoeinstein
Copy link
Contributor Author

One remaining concern in my mind is whether or not we want the XUnitHelper to still be [<AutoOpen>], or if we should promote XUnit2Helper to also be [<AutoOpen>]. Either way, I tried to be limited in the surface area of the API that I exposed.

@forki
Copy link
Member

forki commented May 17, 2015

@ploeh could you please review if this goes into your desired direction?
Also we need to find a way to reduce the pain in this breaking change.

@ploeh
Copy link

ploeh commented May 17, 2015

As a general observation, it seems to be going in the correct direction.

However, I tried to pull down the fork and use it with a small code base of mine, and it doesn't work:

Starting Target: Test (==> Build)
c:\Users\Mark\Documents\Pluralsight\Blog\Idiomatic\Src\CaseConversion\packages\xunit.runner.console.2.0.0\tools\xunit.console.exe "c:\Users\Mark\Documents\Pluralsight\Blog\Idiomatic\Src\CaseConversion\CaseConversion.CSharp\bin\Debug\Ploeh.Samples.CaseConversion.CSharp.dll" "c:\Users\Mark\Documents\Pluralsight\Blog\Idiomatic\Src\CaseConversion\CaseConversion.FSharp\bin\Debug\Ploeh.Samples.CaseConversion.FSharp.dll" "c:\Users\Mark\Documents\Pluralsight\Blog\Idiomatic\Src\CaseConversion\CaseConversion.VisualBasic\bin\Debug\Ploeh.Samples.CaseConversion.VisualBasic.dll" -parallel all -maxthreads default
error: incorrect argument value for -maxthreads
Running build failed.
Error:
System.Exception: xUnit2 reported an error (Error Code 1)
   at Fake.XUnit2Helper.ResultHandling.failBuildWithMessage@176-3.Invoke(String message) in c:\Users\Mark\Desktop\FAKE\src\app\FakeLib\UnitTest\XUnit2Helper.fs:line 176
   at Microsoft.FSharp.Core.OptionModule.Iterate[T](FSharpFunc`2 action, FSharpOption`1 option)
   at Fake.XUnit2Helper.ResultHandling.failBuildIfXUnitReportedError@180-2.Invoke(FSharpOption`1 option) in c:\Users\Mark\Desktop\FAKE\src\app\FakeLib\UnitTest\XUnit2Help
er.fs:line 180
   at Fake.XUnit2Helper.xUnit2(FSharpFunc`2 setParams, IEnumerable`1 assemblies) in c:\Users\Mark\Desktop\FAKE\src\app\FakeLib\UnitTest\XUnit2Helper.fs:line 204
   at [email protected](Unit _arg3) in c:\Users\Mark\Documents\Pluralsight\Blog\Idiomatic\Src\CaseConversion\Build.fsx:line 18
   at Fake.TargetHelper.runSingleTarget(TargetTemplate`1 target) in c:\Users\Mark\Desktop\FAKE\src\app\FakeLib\TargetHelper.fs:line 411

As you can see, the offending command line option is -maxthreads default. This also fits the options reported by xunit.console.exe itself:

usage: xunit.console <assemblyFile> [configFile] [assemblyFile [configFile]...] [options]

Note: Configuration files must end in .config

Valid options:
[...]
  -maxthreads count      : maximum thread count for collection parallelization
                         :   0 - run with unbounded thread count
                         :   >0 - limit task thread pool size to 'count'
[...]

However, looking at the generated command line expression, the rest looks correct. If I remove -maxthreads default and run the expression directly, it does what I want it to do:

$ packages/xunit.runner.console.2.0.0/tools/xunit.console.exe "c:\Users\Mark\Documents\Pluralsight\Blog\Idiomatic\Src\CaseConversion\CaseConversion.CSharp\bin\Debug\Ploeh.Samples.CaseConversion.CSharp.dll" "c:\Users\Mark\Documents\Pluralsight\Blog\Idiomatic\Src\CaseConversion\CaseConversion.FSharp\bin\Debug\Ploeh.Samples.CaseConversion.FSharp.dll" "c:\Users\Mark\Documents\Pluralsight\Blog\Idiomatic\Src\CaseConversion\CaseConversion.VisualBasic\bin\Debug\Ploeh.Samples.CaseConversion.VisualBasic.dll" -parallel all
xUnit.net console test runner (64-bit .NET 4.0.30319.34209)
Copyright (C) 2015 Outercurve Foundation.

Discovering: Ploeh.Samples.CaseConversion.VisualBasic
Discovering: Ploeh.Samples.CaseConversion.CSharp
Discovering: Ploeh.Samples.CaseConversion.FSharp
Discovered:  Ploeh.Samples.CaseConversion.VisualBasic
Starting:    Ploeh.Samples.CaseConversion.VisualBasic
Discovered:  Ploeh.Samples.CaseConversion.CSharp
Starting:    Ploeh.Samples.CaseConversion.CSharp
Discovered:  Ploeh.Samples.CaseConversion.FSharp
Starting:    Ploeh.Samples.CaseConversion.FSharp
Finished:    Ploeh.Samples.CaseConversion.VisualBasic
Finished:    Ploeh.Samples.CaseConversion.CSharp
Finished:    Ploeh.Samples.CaseConversion.FSharp

=== TEST EXECUTION SUMMARY ===
   Ploeh.Samples.CaseConversion.CSharp       Total:  7, Errors: 0, Failed: 0, Skipped: 0, Time: 0,432s
   Ploeh.Samples.CaseConversion.FSharp       Total:  7, Errors: 0, Failed: 0, Skipped: 0, Time: 0,726s
   Ploeh.Samples.CaseConversion.VisualBasic  Total:  7, Errors: 0, Failed: 0, Skipped: 0, Time: 0,423s
                                                    --          -          -           -        ------
                                       GRAND TOTAL: 21          0          0           0        1,580s (1,744s)

@neoeinstein
Copy link
Contributor Author

Yep, I misinterpreted how xUnit 2 interprets the -maxthreads option. I'll correct and push up a revision.

@neoeinstein
Copy link
Contributor Author

Actually, I interpreted how xUnit 2 will interpret the -maxthreads option: xunit/xunit@e2ba592, but that has only been released in the 2.1-beta2 prerelease. I will push up a change that should work for the general v2 case.

@neoeinstein
Copy link
Contributor Author

I think I have an idea about how to reduce the pain of the breaking change. In general, if we are introducing a breaking change, then we are in for a penny; we are in for a pound. It's better to make the breaking changes wholesale and get to the API we want rather than have several piecemeal changes with breaking impedance at each step.

My idea on how to resolve this is to keep the old tasks around, but mark them [<Obsolete>]. Then, add these new tasks in Fake.Testing.XunitTasks and Fake.Testing.Xunit2Tasks modules (names up for suggestions). Neither should be marked [<AutoOpen>], and consumers would need to explicitly open them. By using a Fake.Testing namespace, we also open the road for consolidating such testing tasks under that namespace, and we can work toward providing a consistent pattern of interaction for each of the testing frameworks.

@forki
Copy link
Member

forki commented May 18, 2015

Yes creating copies and making the old one obsolete is good.

This commit also introduces an xUnitSingle task which expects only a
single assembly. Because xUnit v1 only accepts one assembly at a time,
the xUnit task delegates to run each assembly in series. In doing that
delegation, the xUnit task intercepts the report path parameters to inject
the assembly name for each tested assembly. (Closes fsprojects#568)
This commit allows the parallel execution of multiple xUnit test
assemblies from a single task using the parallelism features in the xUnit
console runner. (Fixes fsprojects#797)
@neoeinstein
Copy link
Contributor Author

Ok. This should be ready for review.

|> appendTraits parameters.ExcludeTraits "-notrait"
|> toText

module internal ResultHandling =
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if we should use Chessie.

@forki
Copy link
Member

forki commented May 20, 2015

@ploeh what do you say? Release as new minor rev?

@ploeh
Copy link

ploeh commented May 20, 2015

I just tried with my small 'test' project, and it looks great:

Starting Target: Test (==> Build)
c:\Users\Mark\Documents\Pluralsight\Blog\Idiomatic\Src\CaseConversion\packages\xunit.runner.console.2.0.0\tools\xunit.console.exe "c:\Users\Mark\Documents\Pluralsight\Blog\Idiomatic\Src\CaseConversion\CaseConversion.CSharp\bin\Debug\Ploeh.Samples.CaseConversion.CSharp.dll" "c:\Users\Mark\Documents\Pluralsight\Blog\Idiomatic\Src\CaseConversion\CaseConversion.FSharp\bin\Debug\Ploeh.Samples.CaseConversion.FSharp.dll" "c:\Users\Mark\Documents\Pluralsight\Blog\Idiomatic\Src\CaseConversion\CaseConversion.VisualBasic\bin\Debug\Ploeh.Samples.CaseConversion.VisualBasic.dll" -parallel all
xUnit.net console test runner (64-bit .NET 4.0.30319.34209)
Copyright (C) 2015 Outercurve Foundation.

Discovering: Ploeh.Samples.CaseConversion.VisualBasic
Discovering: Ploeh.Samples.CaseConversion.CSharp
Discovering: Ploeh.Samples.CaseConversion.FSharp
Discovered:  Ploeh.Samples.CaseConversion.CSharp
Starting:    Ploeh.Samples.CaseConversion.CSharp
Discovered:  Ploeh.Samples.CaseConversion.VisualBasic
Starting:    Ploeh.Samples.CaseConversion.VisualBasic
Discovered:  Ploeh.Samples.CaseConversion.FSharp
Starting:    Ploeh.Samples.CaseConversion.FSharp
Finished:    Ploeh.Samples.CaseConversion.CSharp
Finished:    Ploeh.Samples.CaseConversion.VisualBasic
Finished:    Ploeh.Samples.CaseConversion.FSharp

=== TEST EXECUTION SUMMARY ===
   Ploeh.Samples.CaseConversion.CSharp       Total:  7, Errors: 0, Failed: 0, Skipped: 0, Time: 0,748s
   Ploeh.Samples.CaseConversion.FSharp       Total:  7, Errors: 0, Failed: 0, Skipped: 0, Time: 0,983s
   Ploeh.Samples.CaseConversion.VisualBasic  Total:  7, Errors: 0, Failed: 0, Skipped: 0, Time: 0,738s
                                                    --          -          -           -        ------
                                       GRAND TOTAL: 21          0          0           0        2,469s (2,201s)
Finished Target: Test

It also works as expected if I turn off parallelisation:

Starting Target: Test (==> Build)
c:\Users\Mark\Documents\Pluralsight\Blog\Idiomatic\Src\CaseConversion\packages\xunit.runner.console.2.0.0\tools\xunit.console.exe "c:\Users\Mark\Documents\Pluralsight\Blog\Idiomatic\Src\CaseConversion\CaseConversion.CSharp\bin\Debug\Ploeh.Samples.CaseConversion.CSharp.dll" "c:\Users\Mark\Documents\Pluralsight\Blog\Idiomatic\Src\CaseConversion\CaseConversion.FSharp\bin\Debug\Ploeh.Samples.CaseConversion.FSharp.dll" "c:\Users\Mark\Documents\Pluralsight\Blog\Idiomatic\Src\CaseConversion\CaseConversion.VisualBasic\bin\Debug\Ploeh.Samples.CaseConversion.VisualBasic.dll" -parallel none
xUnit.net console test runner (64-bit .NET 4.0.30319.34209)
Copyright (C) 2015 Outercurve Foundation.

Discovering: Ploeh.Samples.CaseConversion.CSharp
Discovered:  Ploeh.Samples.CaseConversion.CSharp
Starting:    Ploeh.Samples.CaseConversion.CSharp
Finished:    Ploeh.Samples.CaseConversion.CSharp
Discovering: Ploeh.Samples.CaseConversion.FSharp
Discovered:  Ploeh.Samples.CaseConversion.FSharp
Starting:    Ploeh.Samples.CaseConversion.FSharp
Finished:    Ploeh.Samples.CaseConversion.FSharp
Discovering: Ploeh.Samples.CaseConversion.VisualBasic
Discovered:  Ploeh.Samples.CaseConversion.VisualBasic
Starting:    Ploeh.Samples.CaseConversion.VisualBasic
Finished:    Ploeh.Samples.CaseConversion.VisualBasic

=== TEST EXECUTION SUMMARY ===
   Ploeh.Samples.CaseConversion.CSharp       Total:  7, Errors: 0, Failed: 0, Skipped: 0, Time: 0,371s
   Ploeh.Samples.CaseConversion.FSharp       Total:  7, Errors: 0, Failed: 0, Skipped: 0, Time: 0,667s
   Ploeh.Samples.CaseConversion.VisualBasic  Total:  7, Errors: 0, Failed: 0, Skipped: 0, Time: 0,336s
                                                    --          -          -           -        ------
                                       GRAND TOTAL: 21          0          0           0        1,375s (3,250s)
Finished Target: Test

In addition, it also works in the old mode, and as expected, I get a compiler warning because the old mode is deprecated.

So it looks good from my perspective 👍

@forki
Copy link
Member

forki commented May 20, 2015

ok then let's do this.

forki added a commit that referenced this pull request May 20, 2015
@forki forki merged commit 57586a3 into fsprojects:master May 20, 2015
@forki
Copy link
Member

forki commented May 20, 2015

released in 3.33. Thanks. 👍

@ploeh
Copy link

ploeh commented May 20, 2015

Thank you both 🎉 😄

@ilkerde
Copy link
Contributor

ilkerde commented Jun 28, 2015

Just recently discovered this breaking change while we auto-updated FAKE. I kind of understand that FAKE as an application may not adhere to SemVer constraints. However, I would suggest to think about how to deal with breaking changes on helper/type level.

@ploeh
Copy link

ploeh commented Jun 28, 2015

@ilkerde, did it break your build script?

I recently upgraded one of my projects to this version, and while my script gets a compiler warning about Fake.XUnitHelper.xUnit being deprecated, the script still runs without errors.

@screamish
Copy link

I just went through the (slight) pain of upgrading and was wondering, did anyone blog about these changes? I love the work and a simple blog post covering the breaking changes would be awesome.

@screamish
Copy link

In particular the change to how test result paths are handled feels like a tiny loss, in that I quite liked the way this

appendIfTrue parameters.XmlOutput (sprintf "-xml\" \"%s" (dir @@ (name + ".xml")))

used the assembly name.

@neoeinstein
Copy link
Contributor Author

Check the docs. The example shows how to get the previous naming convention even with the new method.

@screamish
Copy link

😨 I really searched high and low and couldn't find any docs explaining this.

Do you mean here? http://fsharp.github.io/FAKE/apidocs/fake-testing-xunit2.html

Sorry if I'm just being dense here.

@neoeinstein
Copy link
Contributor Author

Sorry, I'm responding from a dumb terminal, so I can't be as expressive as I'd like. The xUnit (v1) docs has a sample usage with the case you desire. (Same link, just drop the 2 in the url.) Basically, use testDir @@ "xml".

@screamish
Copy link

But where do you get "name" from?

Previously the path was generated for each assembly from its name, now you set one path for the config which is applied to all assemblies which means the file will be overwritten, no?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants