Saturday, 28 May 2016

Getting dotCover to report in TeamCity via command line parameters

This is a series of articles about one of my favourite subjects: Continuous Integration and Continuous Delivery. In this article I will focus on the Development step that includes the build process, the packaging of artifacts, the testing and finally the reporting of code coverage. All this from TeamCity.

I will base this solution in one of my .net projects as the integration is really high and it is really easy to do and use. I faced some challenges when setting up NUnit 3.x and dotCover in TeamCity and this post tries to alleviate the pain with a deep explanation about the setting up and configuration.

In further articles I will delve into detail regarding the next items that are part of the continuous delivery pipeline.

One of the most important aspects of any solution is that if you want to get away from spaghetti code you need to have proper controls in place such as unit tests, integration tests, etc. This for me is a must-have in any project. If you can't answer the following question "What's your % of code coverage?" with something rather than 0, then you are in for trouble as you are probably maintaining something similar to spaghetti code. This doesn't relate to the ability you have for coding, this only relates to its maintainability and scalability.

I will use one of my projects from GitHub for this article:
This project contains a basic library with my MapReduce approach, a console application that runs the library and a unit test project that tries to cover as much code as possible.

Here is my TeamCity project for this github solution with the artifacts.
As you can see, the project gets automatically build via TeamCity and the configuration of the project is as follows:

1. VCS Root:

2. Build Step for Visual Studio:

3. Generation of Artifacts:

As you can see, the setting up of the build process is quite simple. Just create your project in teamcity, point your VCS Root to GitHub, create a build step for Visual Studio (pointing it to the .sln file) and add the location of the binaries to be picked up by TeamCity and generated as artifacts.

So far so good, right!?. Now we need to go one step forward. My project has a console app and a unit test project and I need to build both prior to run the unit test project. To achieve this I will have to piggyback on MsBuild.

Here is the structure of my project:
Now I need to build the projects CountingWordsConsole and MapReduce.Tests together prior to the running of the tests. Here is my msbuild file to build my solution:

And here is the configuration in TeamCity:
I got rid of the previous build step for Visual Studio and this time I'm creating an MsBuild step that will target all my project files.

You will also notice that in the MsBuild file there is a shared argument between TeamCity and MsBuild called ReleaseFolder. This property is set up in TeamCity with the folder location of where my projects will be built. This will help us later as to identify where are our binaries and how we pick those up from TeamCity as artifacts.
Notice that in the MsBuild file the notation of this property is via $(ReleaseFolder) whereas in TeamCity is %system.ReleaseFolder%.

Now that we have the project up and running via MsBuild, it's time to set up NUnit and dotCover.

Setting up NUnit and dotCover

1. Get the latest NUnit.
You can get the latest NUnit 3.2.1 from here. Download the .msi file and install the typical installation. This will leave the files in the following folder:

  • C:\Program Files (x86)\\nunit-console\
Add a new build step in TeamCity and configure it to run it for NUnit 3.x. As soon as you run the project you will get the following error:

This version of NUnit 3 is not a release version and is not compatible with TeamCity. Please update NUnit to a newer release version.

I even tried with NUnit 3.0 RC and NUnit 3.0 but the error never went away. How to fix this? via command line.

To make things a bit more exciting, I will configure directly dotCover as this one will run NUnit by default. dotCover comes automatically by default with TeamCity:
("C:\TeamCity\buildAgent\tools\dotCover") and you only need to configure your project with some configuration files to be able to run dotCover from the command line.

The other aspect to cover later on is how to publish the dotCover report in teamCity but I will get to it.

2. Using dotCover
Using dotCover is really simple, just call dotCover with the argument cover and the .xml config and that's it. Inside the configuration file, dotCover will call NUnit and report the tests back to TeamCity. Here is my configuration file:

Now configure the build step to use dotCover:
Once you run this step, you will see that TeamCity reports back this test automatically:
Now we are almost done. The last part is the tricky one and the answer to the title of this article "Getting dotCover to report in TeamCity via command line parameters". If you check the coverage.xml file, you will see that there is one report created called output.dcvr and now we need to tell TeamCity that the file is there to be picked up.

3. Using service messages.
The common way to report things back to TeamCity is via service messages. To do this, you just need to write this message in the console output:

##teamcity[importData type='dotNetCoverage' tool='dotcover' path='C:\MapReduce\MapReduce.Tests\output.dcvr']

So what I did was building a lightweight console application that just writes that command output:

Now place the executable in the root of your project so it can be called from TeamCity. Add a third build step in your project and use the following arguments:
Run the project in TeamCity and et voilĂ !:

Now you can see the coverage of my unit tests against my source code (>75%) and inspect the report further through TeamCity:

I can see that most of my classes are covered 100% so it gives me enough confidence to keep modifying the project knowing that if I break something the tests will tell me straight away.

I hope you find this useful as it's a quite a long and tedious post and I consider that you already know about TeamCity.


Post a Comment