Continuous testing for .net core
Visual Studio 2017 is already there and it’s awesome.
One of the best features I’ve seen is the Live Unit Testing. The bad news is: it does not yet support .net core :(
It’s not the same, but one thing you can use to automatically run your tests every time you change some file is the command line dotnet watch.
Let’s create one example:
Create your lib project:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
C:\dev\temp>md lib C:\dev\temp>cd lib C:\dev\temp\lib>dotnet new classlib Content generation time: 100,8878 ms The template "Class library" created successfully. C:\dev\temp\lib>dotnet restore Restoring packages for C:\dev\temp\lib\lib.csproj... Generating MSBuild file C:\dev\temp\lib\obj\lib.csproj.nuget.g.props. Generating MSBuild file C:\dev\temp\lib\obj\lib.csproj.nuget.g.targets. Writing lock file to disk. Path: C:\dev\temp\lib\obj\project.assets.json Restore completed in 1,69 sec for C:\dev\temp\lib\lib.csproj. NuGet Config files used: C:\Users\andrecarlucci\AppData\Roaming\NuGet\NuGet.Config C:\Program Files (x86)\NuGet\Config\Microsoft.VisualStudio.Offline.config Feeds used: https://api.nuget.org/v3/index.json C:\Program Files (x86)\Microsoft SDKs\NuGetPackages\ C:\dev\temp\lib>cd.. |
Create your test project:
1 2 3 4 5 6 7 |
C:\dev\temp>md test C:\dev\temp>cd test C:\dev\temp\test>dotnet new xunit Content generation time: 59,5689 ms The template "xUnit Test Project" created successfully. C:\dev\temp\test> |
Add reference to your lib project
Open your test.csproj and add this section anywhere:
1 2 3 |
<ItemGroup> <ProjectReference Include="..\test\test.csproj" /> </ItemGroup> |
Add the DotNet Watcher tool to your test project
Still with your test.csproj open, add another item group:
1 2 3 |
<ItemGroup> <DotNetCliToolReference Include="Microsoft.DotNet.Watcher.Tools" Version="1.0.0" /> </ItemGroup> |
Save and type:
1 |
C:\dev\temp\test>dotnet restore |
Finally, start your continuous tests
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
C:\dev\temp\test>dotnet watch test [90mwatch : [39mStarted Build started, please wait... Build completed. Test run for C:\dev\temp\test\bin\Debug\netcoreapp1.1\test.dll(.NETCoreApp,Version=v1.1) Microsoft (R) Test Execution Command Line Tool Version 15.0.0.0 Copyright (c) Microsoft Corporation. All rights reserved. Starting test execution, please wait... [xUnit.net 00:00:01.1104495] Discovering: test [xUnit.net 00:00:01.3775817] Discovered: test [xUnit.net 00:00:01.4713129] Starting: test [xUnit.net 00:00:01.7878213] Finished: test Total tests: 1. Passed: 1. Failed: 0. Skipped: 0. Test Run Successful. Test execution time: 3,8320 Seconds [90mwatch : [39mExited [90mwatch : [39m[93mWaiting for a file to change before restarting dotnet...[39m |
Note the message that it is waiting for file changes :)
Modify your test/lib projects and check the results
In your test/UnitTest1.cs:
1 2 3 4 5 6 7 8 |
using lib; ... [Fact] public void Test1() { Assert.Equal(2, new Class1().DoubleIt(1)); } |
And your lib/Class1.cs
1 2 3 |
public int DoubleIt(int value) { return 0; } |
Save both and watch your test fail :)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
[90mwatch : [39mStarted Build started, please wait... Build completed. Test run for C:\dev\temp\test\bin\Debug\netcoreapp1.1\test.dll(.NETCoreApp,Version=v1.1) Microsoft (R) Test Execution Command Line Tool Version 15.0.0.0 Copyright (c) Microsoft Corporation. All rights reserved. Starting test execution, please wait... [xUnit.net 00:00:01.0690239] Discovering: test [xUnit.net 00:00:01.3000697] Discovered: test [xUnit.net 00:00:01.3923048] Starting: test [xUnit.net 00:00:01.7705914] test.UnitTest1.Test1 [FAIL] [xUnit.net 00:00:01.7732986] Assert.Equal() Failure [xUnit.net 00:00:01.7735568] Expected: 2 [xUnit.net 00:00:01.7736792] Actual: 0 [xUnit.net 00:00:01.7756190] Stack Trace: [xUnit.net 00:00:01.7779834] C:\dev\temp\test\UnitTest1.cs(11,0): at test.UnitTest1.Test1() [xUnit.net 00:00:01.8179893] Finished: test Failed test.UnitTest1.Test1 Error Message: Assert.Equal() Failure Expected: 2 Actual: 0 Stack Trace: at test.UnitTest1.Test1() in C:\dev\temp\test\UnitTest1.cs:line 11 Total tests: 1. Passed: 0. Failed: 1. Skipped: 0. Test Run Failed. Test execution time: 3,7843 Seconds |
Fix your test
In lib/Class1.cs, change the result:
1 2 3 |
public int DoubleIt(int value) { return value << 1; } |
And watch your cmd:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
[90mwatch : [39mStarted Build started, please wait... Build completed. Test run for C:\dev\temp\test\bin\Debug\netcoreapp1.1\test.dll(.NETCoreApp,Version=v1.1) Microsoft (R) Test Execution Command Line Tool Version 15.0.0.0 Copyright (c) Microsoft Corporation. All rights reserved. Starting test execution, please wait... [xUnit.net 00:00:01.1658403] Discovering: test [xUnit.net 00:00:01.4331220] Discovered: test [xUnit.net 00:00:01.5269952] Starting: test [xUnit.net 00:00:01.8384543] Finished: test Total tests: 1. Passed: 1. Failed: 0. Skipped: 0. Test Run Successful. Test execution time: 3,8702 Seconds [90mwatch : [39mExited [90mwatch : [39m[93mWaiting for a file to change before restarting dotnet...[39m |
\o/
Filtering your tests
You don’t need to run all tests all the time. You can filter them by DisplayName, FullyQualifiedName and Traits.
Also, these operators are allowed: =, != and ~ (contains).
Ex:
1 |
dotnet watch test --filter "FullyQualifiedName=YourNamespace.TestClass1.Test1" |
More information about filtering tests here.
Happy testing :)