Building and testing .NET application in command line

Setup: Windows – .NET 4.5, Linux – Mono 3, Mint 17 (based on Ubuntu 14). I need to build and test .NET application from command line and on CI server.
Sample solution can be downloaded from here https://github.com/mchudinov/BuildingTesting. Solution is compatible with MonoDevelop 5, Xamarin Studio 5 and Visual Studio 2012,2013,2015.

building_bricks

1. Building in command line

There are two standard command line building tools for .NET: MSBuild on Windows and xbuild on Linux/Mono. xbuild build files are compatible (with some exceptions) with MSBuild files.

We need at least 4 simple steps (targets as they called in MSBuild terminology) to build a .NET solution:

  • Clean
  • Restore NuGet packages
  • Build binaries
  • Run unit tests

Clean
Cleaning in a simplest case is just removing bin and obj directories.

MSBuild has RemoveDir task for this.

Restore NuGet packages
NuGet packages must be always restored before building. Here is a good article about how restore NuGet packages on the right way. And here is the documentation form NuGet project about migrating MSBuild-Integrated solutions to use Automatic Package Restore.

My short conclusion:

  • folder packages must not be in source control
  • NuGet.exe and its config files must not be included in solution. It must be installed on build system

To restore packages nuget.exe must be installed on the build system and be in system Path. The latest version of the nuget.exe command-line tool is always available from http://nuget.org/nuget.exe
NuGet is a .NET program and is compatible with x86/x64 Linux system with Mono. Just download and save this file in /usr/bin folder and make it executable.

To restore packages just run simple command in command line from solution folder.

In MSbuild file this can be executed by Exec task.

Restore target looks like this:

Build binaries
MSBuild has a task named MSBuild to build a *.XYZproj files

Run unit tests
Here we need an extension to standard MSBuild: MSBuild Community Tasks. Install it as a NuGet package to the UnitTest solution. Community Tasks extension has a special task called NUnit. A sample target can looks like this:

ToolPath attribute points to NUnit binary location.

We can make this build target operating system independent by adding operating system condition and pointing target to the right path where NUnit is installed on different OSes.

Note that NUnit version 3 the has only a binary named nuinit3-console.exe. To make MSBuild NUnit target work with NUnit v3 we need to copy nuinit3-console.exe to nuinit-console.exe.

Now we can create a Build.proj file, include all targets into it and store the file in the solution root folder. Not in any projects folders. It should be placed in the solution root. This file will be shown in Visual Studio or MonoDevelop under “Solution items”:

solutionitems_build

Simple Build.proj file:

Run build form command line with command xbuild Build.proj in solution folder. On WIndows platform it will be C:\Windows\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe Build.proj
There is a special predefined console window on Windows “Developer Command Prompt for VS” with MSBuild in PATH.

 

Note that on Windows MSBuild is not in PATH by default. Then to build application from command line a “Developer Command Prompt for VS” should be used.

 

2. Testing in command line
To test .NET from command line NUnit must be installed as a command line program. On Windows download and install it from here http://nunit.org/index.php?p=download. On Debian-based Linux

Run unit tests in command line by pointing nunit-console program to test *.dll

3. Build on TeamCity
Generally TeamCity can build both MSBuild and xbuild projects. There is a special build step runner called MSBuild for this purpose.
build1
But TeamCity version 8.1 (the last version at the time of writing this post is 8.1.5) does not (yet?) support xbuild Mono version 4.5. This issue is registered at TeamCity bug tracker: “Support Mono 4.5 profile“. Thus we can not build Mono 4.5 application with this build step. We can not build Mono 4.0 application with it either because xbuild is not shipped with Mono 4.0 and TeamCity can not find xbuild. Thus I build Mono application using command line builder.

 

build2

xbuild must be in path in this case.

3. Test on TeamCity

TeamCity has NUnit build step runner. Everything is quite straight forward here.
Use template **\*Test*.dll to test all test dlls. And **\obj\**\*Test.dll to exclude all obj-test dlls.

build3
If you get error something like
Could not load file or assembly 'CallQualityParser, Version=1.0.1.25142, Culture=neutral, PublicKeyToken=null' or one of its dependencies. An attempt was made to load a program with an incorrect format.

this means that test assembles and executable modules are build with different platforms. Just control that Test project and other project in solution have same platform setup. It should be x86 or ‘Any CPU’ or whatever but it should be the same across test and other projects.

Sample solution can be downloaded from here https://github.com/mchudinov/BuildingTesting. Solution is compatible with MonoDevelop version 5, Xamarin Studio version 5 and Visual Studio.