How to create an NUnit test project that is also a self-running console app .exe

  1. Create your NUnit Test project as a Windows Console Application, not as a Class Library.
  2. Then make your main Program look like this:
    [TestFixture]
    public class Program
    {
        static void Main(string[] args)
        {
            NUnit.ConsoleRunner.Runner.Main(
                new[]{Assembly.GetExecutingAssembly().Location }
                );
        }
    
        [TestCase("Aa - Bb")]
        public void WhenValidatingForename_should_accept_valid_characters(string validInput)
        {
            var result= new ClassUnderTest().Validate(validInput);
            Assert.IsTrue(result);
        }
    
        [TestCase("X<")]
        public void WhenValidatingForename_should_reject_invalid_characters(string invalidInput)
        {
            var result= new ClassUnderTest().Validate(invalidInput);
            Assert.IsFalse(result);
        }
    }
  3. Then, add a reference not only to nunit.framework.dll but also to nunit-console-runner.dll

You now have a self-running executable that runs all your tests, but still behaves in the usual way in a build script, or when running tests inside Visual Studio with TestRunner or Resharper or similar.
NB You may need to check if your build scripts are hard-coded to expect a Test project to be a .dll.

Refactoring a static class with hard-coded dependencies for testability

is not that hard. You can add a factory method to the static class to create the dependency, and change the factory method at test-time.
Here's an example:

public static class WithDependencies
{
	public static string MethodWithDependencies()
	{
		using (var thing = new HardCodedThing())
		{
			return DoSomething();
		}
	}
}

which can be turned into:

public static class WithDependencies
{
    public static Func<HardCodedThing> CreateHardCodedThing = () => new HardCodedThing();

	public static void MethodWithDependencies()
	{
		using (var thing = CreateHardCodedThing())
		{
			DoSomething();
		}
	}
}

With this code in your test:

[TestFixture]
public class WhenDoingSomething
{
	private Mock<HardCodedThing> mockThing;

	[SetUp]
	public void SetUpMockThing()
	{
		// mockThing.Setup( ...  ) ... etc ...
	}

	public void Given_hardcodedthing_does_X_should_get_Y()
	{
		//Arrange
		WithDependencies.CreateHardCodedThing = () => mockThing.Object;
		//Act
		var result= WithDependencies.MethodWithDependencies();
		//Assert
		Assert.AreEqual("Y", result);
	}
}

NUnit Constraints Example – a Simple Custom Constraint

Are you short of an NUnit Assertion? You have some code for a test, but you really want it in NUnit constraint form so you can use it like any other test. They are easy to write. Here's an example which wraps a function you already wrote as a Constraint:

public class EqualsByValueConstraint : Constraint
{
	private readonly object expected;
	private CompareResult compareResult;

	public EqualsByValueConstraint(object expected)
	{
		this.expected = expected;
	}

	public override bool Matches(object actual)
	{
		this.actual = actual;
		compareResult = EqualsByValueOrFailureReason(actual, expected);
		return compareResult;
	}

	public override void WriteDescriptionTo(MessageWriter writer)
	{
		writer.WriteExpectedValue(this.expected);
	}
	public override void WriteActualValueTo(MessageWriter writer)
	{
		base.WriteActualValueTo(writer);
		writer.WriteLine();
		writer.WriteMessageLine("Compare Result " + compareResult);
	}
}
public class CompareResult
{
	public bool IsPass {get;set;}
	public string FailureDescription {get; set;}
}

If your function is just a boolean, then you could remove the CompareResult class. The drawback being that your failure message will only say 'failed' rather than give an explanation of the failure. In that case, you might just as well not use the constraint and use the Assert.That(bool, message) overload.

dotCover config file for command line NUnit test coverage

So you want to produce a coverage report for your .Net project, preferably from the command line? If you use dotCover and NUnit then this:

<?xml version="1.0" encoding="utf-8"?>
<AnalyseParams>
    <Executable><!-- Path to your NUnit bin directory e.g.  -->C:\Program Files\NUnit 2.5.10\bin\net-2.0\nunit-console.exe</Executable>
    <WorkingDir><!-- This path works for running dotCover with a config file in the project directory-->bin\Debug\</WorkingDir>
    <Arguments><!-- The dlls containing NUnit tests. Space delimited if more than one-->My.Tests.dll My.MoreTests.dll</Arguments>
    <Output><!-- Path to where I want the report. Can be relative or absolute -->My.Tests.Coverage.html</Output>
    <Filters>
        <IncludeFilters>
            <FilterEntry><!--  _ "Module" means project _ --><ModuleMask>*</ModuleMask></FilterEntry>
        </IncludeFilters>
        <ExcludeFilters>
            <FilterEntry><!--  _ "Module" means project _ --><ModuleMask>My.Tests</ModuleMask></FilterEntry>
            <FilterEntry><!-- namespaces can be filter with a ClassMask with * wildcard --><ClassMask>Namespaces.For.AutogeneratedCode.*</ClassMask></FilterEntry>
            <FilterEntry><ClassMask>SomeUntestable.Class</ClassMask></FilterEntry>
        </ExcludeFilters>
    </Filters>
    <ReportType>html</ReportType>
 </AnalyseParams>

will allow you, from the command line, to type:

dotCover analyse MyConfigFileName.xml

and generate coverage reports. Assuming that dotCover is in your path of course.
I like to set the filters to exclude coverge report on the test project itself as well as autogenerated code.

Covering Multiple Test Projects In One Run

  • Set your working directory to be a parent of all the test projects, e.g. the solution directory.
  • List the full relative paths to each Test dll, space limited:
    <WorkingDir>.</WorkingDir>
    <Arguments>Web.Tests\bin\Debug\MyProject.Web.Tests.dll Implementation.Tests\bin\Debug\MyProject.Implementation.Tests.dll</Arguments>

Filtering and more advanced coverage configs

  • Look down the right hand side of the page here : http://www.jetbrains.com/dotcover/documentation/index.html for documentation, such as it is.
  • Filtering is covered here: http://blogs.jetbrains.com/dotnet/2010/07/filtering-with-dotcover/
  • More complex stuff is touched on here: http://blogs.jetbrains.com/dotnet/tag/code-coverage/