Showing posts with label Testing. Show all posts
Showing posts with label Testing. Show all posts

Sunday, 27 December 2015

Testing exceptions with NUnit 3.x

If you are moving from NUnit 2.x to 3.x you will find that the old ExpectedException attribute is missing. Not to worry. There are alternatives.

Here’s an example. In Domain-Driven Design (DDD) there's a concept of an 'entity'; an object with an identifier. I have been experienting with a supporting framework for DDD which includes a base class for entities. I decided I didn’t want entities to be instantiated without an identifier and I didn’t want that identifier to be the default value for the identity type. Here’s a simple entity class together with a fragment of the base class:

private class Customer : Entity<int>
{
    public Customer(int id) : base(id)
    { 
    }
}

public abstract class Entity<T> : IEquatable<Entity<T>>
{
    protected Entity(T id)
    {
        if (object.Equals(id, default(T)))
        {
            throw new ArgumentException("The ID cannot be the type's default value.", "id");
        }

        this.Id = id;
    }

    // ... snip ...
}

With 2.x tests you could write something like this:

[Test]
[ExpectedException(typeof(System.ArgumentException))]
public void EntityConstructor_WithDefaultValue_ThrowsException()
{
    var customer1 = new Customer(default(int));
}

If you have tests like that and you update NUnit to 3.x that won’t even compile because the attribute isn’t there anymore. No need to panic though, there are a couple of options available to you. The first is to use Exception Asserts (i.e. the Assert.Throws method).

[Test]
public void EntityConstructor_WithDefaultValue_ThrowsException()
{
    Assert.Throws<ArgumentException>(() => new Customer(default(int)));
}

The second option is to use the Throws Constraint which is my preference.

/// 
/// Tests that the ID can't be the types default value.
/// 
[Test]
public void EntityConstructor_WithDefaultValue_ThrowsException()
{
    Assert.That(() => new Customer(default(int)), Throws.ArgumentException);
}

Actually the last 2 alternatives have a subtle improvement over the ExpectedException attribute.

The attribute approach doesn’t allow you specify exactly when and where the exception is expected to be thrown. If you have a test with multiple lines of setup code any one of those lines could throw an exception which would be caught by the attribute (assuming the exception type is correct) so you might not be testing what you think you are testing.

The assertion approach allows you to specify the exact line of code you expect to throw the exception.

Sunday, 19 April 2015

Could Not Detect Test Framework error when running ApprovalTests from an automated build

I was making some changes to an automated continuous integration build in TeamCity when I encountered an unexpected error. I had a suite of unit tests using the ApprovalTests framework but when the build was triggered all of the tests failed, tests which ran perfectly from within Visual Studio.

Investigation in TeamCity revealed the following error details (the same for each test):

Test(s) failed. System.Exception : 
Could Not Detect Test Framework

Either:
1) Optimizer Inlined Test Methods

Solutions:
a) Add [MethodImpl(MethodImplOptions.NoInlining)]
b) Set Build->Opitmize Code to False 
   & Build->Advanced->DebugInfo to Full

or
2) Approvals is not set up to use your test framework.
It currently supports [NUnit, MsTest, MbUnit, xUnit.net, xUnit.extensions, Machine.Specifications (MSpec)]

Solution:
To add one use ApprovalTests.Namers.StackTraceParsers.StackTraceParser.AddParser() method to add implementation of ApprovalTests.Namers.StackTraceParsers.IStackTraceParser with support for your testing framework.
To learn how to implement one see http://blog.approvaltests.com/2012/01/creating-namers.html
   at ApprovalTests.Namers.StackTraceParsers.StackTraceParser.Parse(StackTrace stackTrace)
   at ApprovalTests.Namers.UnitTestFrameworkNamer..ctor()
   at ApprovalTests.Approvals.<.cctor>b__c()
   at ApprovalTests.Approvals.GetDefaultNamer()
   at ApprovalTests.Approvals.Verify(IApprovalWriter writer)
   at ApprovalTests.Approvals.VerifyFile(String receivedFilePath)
   at ApprovalTests.Approvals.Verify(FileInfo receivedFilePath)

 

SNAGHTML472c94c

The first point to note is that the build was set to run using the Release configuration.

SNAGHTML4758484

The fix requires changes to the Visual Studio project settings for the test project.
Open the test project settings for the Release configuration. On the Build tab uncheck Optimize code and click Advanced…

SNAGHTML479828c

In the advanced settings dialog set Debug Info to full.

image

OK the dialog and save the project. Commit changes to source control and trigger the build again.

That should do it!

The error is caused by the absence of stacktrace information when the source is built using the Release configuration. Approvals Tests infers the name the approval file by walking the stack trace to get the test method name. No stacktrace, no inferred method name and therefore ApprovalTests can’t find the approval file.

Sunday, 29 March 2015

Running NUnit tests with Jenkins

In this series:

At the time of writing Jenkins is at version 1.602.

Following on from my previous post - Automatically triggering a Jenkins build on Git commit - the next step is to automatically run unit tests as part of the build.

My unit tests are written using NUnit. As with everything in Jenkins getting unit tests to run as part of a build is a fairly manual process which involves adding a new build step to call the NUnit console application directly. Let’s get started.

Step 1 – Install the NUnit binaries

If you haven’t got it already you’ll need to download and install NUnit. You can do so using an MSI or grab the Zip file and extract the binaries to a folder on your machine. Of course you could use Chocolatey to install NUnit.

chocolatey install nunit

Step 2 - Add a build step to your Jenkins build

Now you have NUnit you’ll need to add a new build step to your Jenkins build. Choose your project from the dashboard.

jenks001

jenks002

On the configuration page scroll to the bottom and add click ‘Add build step’. Choose ‘Execute Windows batch command’.

jenks003

This adds the new build step that you will use to call NUnit. That’s simply a case of calling the NUnit console executable passing in the path to the assembly containing the tests to be run.

jenks004

Remember to call nunit-console.exe or nunit-console-x86.exe if you’re testing a 32-bit assembly. If you need to run tests against multiple assemblies you can do so by listing them on the command line. NUnit command line documents are here. 

Once you’ve done all that save the changes and click ‘Build now’.

jenks005

All things being equal you should have a successful build. If you click on the build in the Build History and look at the Console Output you will be able to see the results of the NUnit run.

jenks006

The output isn’t very slick though, is it? Lets see about getting a nice unit test report working.

Step 3 – Publish NUnit report

First, make sure the NUnit plugin has been installed in Jenkins. If it’s not there you’ll need to add it. Go to Dashboard > Manage Jenkins > Manage Plugins and check your installed plugins. If it’s not there add it. This plugin makes it possible to import NUnit reports from each build into Jenkins so they are displayed with a trend graph and details about which tests that failed.

jenks008

Next you need to get NUnit to publish its results as an XML file from your build. To do that add ‘/xml=nunit-result.xml’ to the end of the batch command you added in Step 2.

jenks007

Now add a post-build action to your build definition and select ‘Publish NUnit test result report’.

jenks009Enter the name of the XML file you added to the batch command (nunit-result.xml) as the ‘Test report XMLs’ value and save the build configuration.

jenks010

Run a build and when it completes click on the build ID in the Build History list for the project. You’ll find a new item, Test Result, in the build history. Click on the Test Result link to see the report.

jenks011

Job done!

Saturday, 28 March 2015

Using ApprovalTests to test a simple logging framework

I’ve been playing with a simple logging framework that I’ve had lying around for ages and thought I’d add an NLog implementation just for kicks and giggles. It also gave me an opportunity to play with the ApprovalTests framework by Llewellyn Falco.

Very briefly ApprovalTests lets you compare output generated during a test with a predefined example. If they differ the test fails. In this case I wanted to verify that a log file generated during a the execution of a unit test matched an example log file. I could then be sure that the log file had been generated and that the contents were correctly formatted.

I’m not going in to a great deal of detail about the basics of unit testing here. Suffice is to say that I’m using NUnit.

In Visual Studio I created a test project, added a reference to the project containing my logger implementation and added a few NuGet packages to the test project:

app001

Note that I’ve added ApprovalTests and NLog as well as NUnit.

I added an App.config file to the test project and put some basic NLog configuration in it. NLog is very helpful and attempts to automatically configure itself on start-up by looking for configuration files in some standard locations. One of those is – you guessed it – the standard App.config file.

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <configSections>
    <section name="nlog" type="NLog.Config.ConfigSectionHandler, NLog"/>
  </configSections>
  <nlog throwExceptions="true">
    <targets>
      <target name="file" type="File" fileName="log.txt" layout="${level:uppercase=true}|${logger}|${message}|${exception}" />
    </targets>
    <rules>
      <logger name="*" minlevel="Debug" writeTo="file" />
    </rules>
  </nlog>
</configuration>

Note the target on line 8. That defines the layout for a log message and therefore what we expect to see for each entry in the log file. The macros (prefixed with $) will be replaced with appropriate values when the log entry is written. Also note that the generated log file will be called log.txt and will appear in the same directory as the compiled dlls.

The next step is to create a test fixture. Here’s some code:

namespace Andy.French.Logging.NLog.Tests
{
    using System;
    using System.IO;

    using ApprovalTests;
    using ApprovalTests.Reporters;

    using NUnit.Framework;

    /// <summary>
    /// Tests for the <see cref="Andy.French.Logging.NLog.Logger"/>.
    /// </summary>
    [TestFixture]
    public class LoggerTests
    {
        /// <summary>The logger to test.</summary>
        private ILogger logger;

        /// <summary>
        /// Sets up a unit test.
        /// </summary>
        [SetUp]
        public void SetUp()
        {
            this.logger = new Logger("This.Is.A.Test.Logger");
        }

        /// <summary>
        /// Tests that the information method the with a string argument writes a message in correct format.
        /// </summary>
        [Test]
        [UseReporter(typeof(DiffReporter))]
        public void Information_WithStringArgument_WritesInfoMessageInCorrectFormat()
        {
            // Arrange

            // Act
            this.logger.Information("This is a test message.");
            
            // Assert
            Approvals.Verify(new FileInfo("log.txt"));
        }

        /// <summary>
        /// Tears down a unit test.
        /// </summary>
        [TearDown]
        public void TearDown()
        {
            if (File.Exists("log.txt"))
            {
                File.Delete("log.txt");
            }
        }
    }
}

So what’s going on here?

Firstly, we have a setup method that instantiates a new instance of my Logger class prior to execution of each unit test. We also have a teardown method that checks for the log file at the end of each unit test and if it’s there it deletes it. This way we guarantee that each unit test starts with a clean slate.

Update: The teardown method isn’t strictly required because ApprovalTests cleans up after each unit test run. In this case it deletes the log file.

There are a couple of interesting lines in the test. On line 33 there’s a UseReporter attribute. This is part of the ApprovalTests framework and does some interesting things. More on that later.

On line 42 we make a call to Approvals.Verify. Note we aren’t using standard NUnit assertions here but are using the ApprovalTests API instead. This call is going to check that the log file matches the predefined example. If it doesn’t, the test fails.

So where is the example log file and how do we generate it? That’s where the UseReporter attribute comes in.

The first time you run the test in Visual Studio (I use the ReSharper unit test runner) the test will fail because we haven’t got an example for ApprovalTests to use to make a comparison with. Because we’ve added the UseReporter attribute ApprovalTests steps in and reports what’s going on. It actually creates an example file for us, shows us what’s in the generated file and allows us to edit the example.

Here’s the test failure in the ReSharper test runner:

app002

And this is what we’ve got in the Visual Studio editor:

app003

The output in the actual log file is correct so we can safely copy the text from the log file (on the left) into the example (on the right) and save it.

app004

Note that ApprovalTests has created the example file in the project folder and has used a naming convention based on the name of the test class and the name of the test method. ApprovalTests uses this naming convention to matchup an example file with a specific unit test. In this case the name is:

LoggerTests.Information_WithStringArgument_WritesInfoMessageInCorrectFormat.approved.txt

app007

To see this file click the ‘Show All Files’ icon in the Solution Explorer. Right-click on it and select ‘Include In Project’. The example files need to be saved with the project and added to version control.

Next time the test is run we get a pass!

app006

By the way, if you’re wondering about the test method naming convention it’s the one I’ve used for years and was first suggested by Roy Osherove.

Update: I forgot to mention that ApprovalTests doesn’t just work with text-based files like the log file we were testing here. It can work with a variety of file formats including images. You can find the source code here if you are interested in poking around.

Wednesday, 25 June 2014

Using Entity Framework in integration tests

Entity Framework code first includes an interesting feature called database initializers. When I first encountered this feature I wondered if it would be possible to use a database initializer to drop and recreate a database as part of a suite of integration tests. It might prove very useful if we were able to create a set of repeatable and atomic tests around, for example, a data access layer. Of course it turns out that this is possible.

At the time of writing Entity Framework is in version 6.1.1.

 

What is a database initializer?

A database initializer is an implementation of the IDatabaseInitializer<TContext> interface and is used by Entity Framework to setup the database when the context is used for the first time. This could involve dropping and recreating the entire database, or just updating the schema if the model has changed. MSDN describes the interface as follows:

“An implementation of this interface is used to initialize the underlying database when an instance of a DbContext derived class is used for the first time. This initialization can conditionally create the database and/or seed it with data.” [1]

There are several implementations available out of the box:

  • DropCreateDatabaseIfModelChanges<TContext> – will DELETE, recreate, and optionally re-seed the database only if the model has changed since the database was created.
  • DropCreateDatabaseAlways<TContext> - will always recreate and optionally re-seed the database the first time that a context is used in the app domain. To seed the database, create a derived class and override the Seed method.
  • CreateDatabaseIfNotExists<TContext> - will recreate and optionally re-seed the database only if the database does not exist. To seed the database, create a derived class and override the Seed method.

In our scenario we always want to reinitialize the database before each test. This will give us a repeatable baseline at the start of each test case. Also, we probably want to be able to insert some known test data. The DropCreateDatabaseAlways<TContext> class looks like it does exactly what we want: it always recreates the schema and can optionally re-seed the database.

 

Creating an initializer derived from DropCreateDatabaseAlways<TContext>

Creating our custom initializer turns out to be very simple:

namespace Andy.French.Repository.Entity.Framework.Tests
{
    using System.Data.Entity;
    using System.Data.Entity.Migrations;

    using Andy.French.Repository.Entity.Framework.Tests.Domain;

    public class TestInitializer : DropCreateDatabaseAlways<TestContext>
    {
        protected override void Seed(TestContext context)
        {
            context.Customers.AddOrUpdate(
                                c => c.Id,
                                new Customer { Name = "Customer 1" },
                                new Customer { Name = "Customer 2" });

            base.Seed(context);
        }
    }
}

In this example I’m seeding the database with a couple of customers. Naturally you would seed the database according to your needs using your domain classes.

 

Invoking the initializer in our test suite

I use NUnit for tests - and have done so for a very long time – so the example below is based on NUnit.

For true atomic repeatable tests you should drop and recreate the database before each and every test case but for this example I have chosen to do so once for each test fixture - a class that contains tests. To do that I have created a class that’s marked with the SetUpFixture attribute. NUnit will pick this up and will run the method marked with the SetUp attribute for each test fixture and before any of the tests it contains are run.

namespace Andy.French.Repository.Entity.Framework.Tests
{
    using System.Data.Entity;
    using NUnit.Framework;

    [SetUpFixture]
    public class SetUpFixture
    {
        public SetUpFixture()
        {
        }

        [SetUp]
        public void SetUp()
        {
            Database.SetInitializer(new TestInitializer());
            
            var context = new TestContext();
            context.Database.Initialize(true);
        }
    }
}

That’s all here is to it! On line 16 we call the Database.SetInitializer method so Entity Framework will use our custom initializer. Remember, the custom initializer extends DropCreateDatabaseAlways<TestContext> so the initializer is set for the test context type.

On lines 18 and 19 we simply create a context and call context.Database.Initialize(true) which causes the database to be dropped, recreated and re-seeded. MSDN describes the Initialize method in the following terms:

“Runs the the registered IDatabaseInitializer<TContext> on this context. If "force" is set to true, then the initializer is run regardless of whether or not it has been run before. This can be useful if a database is deleted while an app is running and needs to be reinitialized. If "force" is set to false, then the initializer is only run if it has not already been run for this context, model, and connection in this app domain. This method is typically used when it is necessary to ensure that the database has been created and seeded before starting some operation where doing so lazily will cause issues, such as when the operation is part of a transaction.” [2]

 

Running a test

With everything in place we can now run some tests. Here’s an example where we are testing a customer repository:

namespace Andy.French.Repository.Entity.Framework.Tests
{
    using System.Linq;
    using NUnit.Framework;

    [TestFixture]
    public class CustomerRepositoryTest
    {
        private CustomerRepository _repository;

        [SetUp]
        public void SetUp()
        {
            var context = new TestContext();
            _repository = new CustomerRepository(context);
        }

        [Test]
        public void FindAll_WhenCalled_FindsAllInstances()
        {
            // Arrange

            // Act
            var result = _repository.FindAll();

            // Assert
            Assert.That(result.Count(), Is.EqualTo(2));
        }
    }
}

 

A note on configuration

You will need to add an app.config file to your project. The config file will have to tell Entity Framework which database to use. It might look something like this:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <configSections>
    <section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false"/>
  </configSections>
  
  <entityFramework>
    <defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
      <parameters>
        <parameter value="v11.0"/>
      </parameters>
    </defaultConnectionFactory>
    
    <providers>
      <provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer"/>
    </providers>
  </entityFramework>
  
  <startup>
     <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.1"/>
  </startup>
</configuration>

Note that we are using a SQL Server Express local database (v11.0). In my case the result is I get a couple of database files (.mdf and .ldf) named after the context used by the database initializer in my user directory.

 

image

 

References

[1] DatabaseInitializer<TContext> Interface (MSDN)

[2] Database.Initialize Method (MSDN)

Saturday, 11 January 2014

How to access parameters passed in to a mocked method using Moq

The problem

I was writing unit tests for a WPF application using the MVVM pattern supported by Caliburn.Micro. I had methods on the view-model that were automatically bound to buttons in the user interface using Caliburn.Micro’s convention-based bindings. Some of these methods required that a pop-up dialog box be displayed to the end user to confirm an action. The dialog could be submitted or cancelled.
For example, when the user clicked a ‘back’ button to navigate back to a previous screen I needed to check if any data had changed on the current screen. If it had, I needed to present the user with a dialog asking if they really wanted to go back when there was unsaved data. If the user submitted the dialog by clicking OK the application would go to the previous screen.
The code looked something like this:
public void Back()
{
    if (!IsChanged)
    {
        EventAggregator.Publish(new NavigationMessage(GetBackScreen()));
    }
    else
    {
        var heading = ResourceProvider.GetString("Dialog.Navigate.Back.Heading");
        var text = ResourceProvider.GetString("Dialog.Navigate.Back.Text");
        var confirmationDialogViewModel = new ConfirmationDialogViewModel(heading, text);

        WindowManager.ShowChromelessDialog(confirmationDialogViewModel);

        if (confirmationDialogViewModel.Submitted)
        {
            EventAggregator.Publish(new NavigationMessage(GetBackScreen()));
        }
    }
}

By way of explanation, navigation in the application was managed by publishing navigation messages. The Shell view-model subscribed to the navigation messages and swapped the screens as appropriate when it handled such a message. Messaging was accomplished using Caliburn.Micro’s EventAggregator. Dialogs were managed using a class derived from Caliburn.Micro’s WindowManager class.
So the question was, given the code above how could I write unit tests that could test for cases when _confirmationDialogViewModel.Submitted was either true or false? My intention was to use Moq to mock the WindowManager so I would have to be able to access the _confirmationDialogViewModel passed in to WindowManager.ShowChromelessDialog(_confirmationDialogViewModel) and to be able to set its Submitted property.
How could I do that?

The solution

NB: Before I go on I should point out that there is an alternative – and arguably preferable - solution to the one presented below. Rather than instantiating the ConfirmationDialogViewModel as shown above it should have been injected into the parent view-model as a dependency. By so doing I could have simply set the Submitted property after instantiating the ConfirmationDialogViewModel in the unit test. This is what I actually ended up doing but the problem as presented above sparked my curiosity to see if it was possible to get at parameters passed into mocked methods.
Of course you can, by using Moq’s support for callbacks. There are several approaches to this but I liked the following:
[Test]
public void Back_IfConfirmationDialogIsSubmitted_NavigationMessageIsPublished()
{
    // Arrange
    _viewModel.Data = "Data has changed";

    ConfirmationDialogViewModel dialog;

    _mockEventAggregator.Setup(x => x.Publish(It.Is<NavigationMessage>(m => m.ScreenToNavigateTo == Screen.Home)));
    _mockWindowManager.Setup(w => w.ShowChromelessDialog(It.IsAny<ConfirmationDialogViewModel>()))
                      .Callback((object rootModel) => ((ConfirmationDialogViewModel)rootModel).Submit());

    // Act
    _viewModel.Back();

    // Assert
    _mockEventAggregator.Verify(x => x.Publish(It.Is<NavigationMessage>(m => m.ScreenToNavigateTo == Screen.Home)), Times.Once);
}

In this case we are able to call the Submit() method on the dialog view-model automatically when the mocked ShowChromelessDialog method is called (see lines 10 and 11). This in turn caused the Submitted property to be set to true. Job done!
Incidentally, if you need to you can get a reference to the method parameter by doing something like this:
[Test]
public void Back_IfConfirmationDialogIsSubmitted_NavigationMessageIsPublished()
{
    // Arrange
    _viewModel.Data = "Data has changed";
    _mockEventAggregator.Setup(x => x.Publish(It.Is<NavigationMessage>(m => m.ScreenToNavigateTo == Screens.EnquiryList)));

    ConfirmationDialogViewModel dialog = null;
    _mockWindowManager.Setup(w => w.ShowChromelessDialog(It.IsAny<ConfirmationDialogViewModel>()))
                      .Callback((object rootModel) => dialog = (ConfirmationDialogViewModel)rootModel);

    // Act
    _viewModel.Back();

    // We can now get at the dialog variable 
    var heading = dialog.Heading;

    // ... snip ...
 
}

In the example above you could access the dialog variable once the mocked ShowChromelessDialog method has been called.

Monday, 21 March 2011

Using Moq to verify that a method does NOT get called

I recently had a bit of a brain fade when using Moq. I wanted to check that one method on a mocked class wasn’t called but that another was. Imagine a class like this:

public class Testable
{
    IService _service;
    
    public Testable(IService service)
    {
        _service = service;
    }

    public void MethodToTest(int i)
    {
        if(i <= 0)
        {
            _service.DoSomething();
            return;
        }
        
        _service.DoSomethingElse();
    }
}

I want to test that when if i > 0 only the _service.DoSomethingElse() method is called. I need the mock implementation of IService to throw an exception if the wrong method is called. The solution is to ask Moq to create a strict mock:

using Moq;
using NUnit.Framework;

[TestFixture]
public class TestableTest 
{
    [Test]
    public void MethodToTest_WhenArgumentGreaterThanZero_DoesSomethingElse()
    {
        // Arrange
        Mock<IService> mockService = new Mock<IService>(MockBehavior.Strict);
        mockService.SetUp(x => x.DoSomethingElse());
        
        Testable testable = new Testable(mockService.Object);
        
        // Act
        testable.MethodToTest(1);
        
        // Assert
        mockService.Verify(x => x.DoSomethingElse());
    }
}

When MockBehavior.Strict is used, Moq will throw an exception if any method is called that does not have a corresponding setup. In this case if the DoesSomething() method is called and exception will be thrown and the test will fail.

Thursday, 13 January 2011

NUnit tests being ignored

Problem

I created a test assembly and added NUnit test fixtures to it. Everything was proceeding nicely until I added an App.config file to the test project. Thereafter, I could not run any of the tests with the ReSharper test runner which reported that each test was being ignored.

untitled

I also found it was impossible to add the test assembly to the Gallio test runner.

Solution

The problem was that I had accidentally created a badly formatted App.config file (I had forgotten to wrap <add/> elements in an <appSettings/> element). Correcting this error allowed all tests to run normally. The incorrectly formatted App.config file looked something like this:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <add key="SomeKey" value="SomeValue" />
</configuration>

The corrected version looked something like this:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <appSettings>
    <add key="SomeKey" value="SomeValue" />
  </appSettings>
</configuration>

Friday, 7 January 2011

Useful NUnit attributes

I can never remember the various NUnit attributes I find useful (other than the basics like TestFixture, Test, SetUp, TearDown and ExpectedException) so here’s a quick aide-mémoire (NB: this is not a complete list by any means):

Attribute Description
CombinatorialAttribute Used on a test to specify that NUnit should generate test cases for all possible combinations of the individual data items provided.

ExplicitAttribute

Causes a test or test fixture to be ignored unless it is explicitly selected for running.

RandomAttribute

Used to specify a set of random values to be provided for an individual parameter of a parameterized test method.
RangeAttribute Used to specify a range of values to be provided for an individual parameter of a parameterized test method.

SequentialAttribute

used on a test to specify that NUnit should generate test cases by selecting individual data items provided for the parameters of the test, without generating additional combinations.
TestCaseAttribute Serves the dual purpose of marking a method with parameters as a test method and providing inline data to be used when invoking that method.
TestCaseSourceAttribute Used on a parameterized test method to identify the property, method or field that will provide the required arguments.
ValuesAttribute Used to specify a set of values to be provided for an individual parameter of a parameterized test method.

Row testing with NUnit

In times past there was an extension to NUnit that facilitated row testing (i.e. allowing a test case to be executed multiple times, passing in different values to each run). The extension is no longer required; you can use the [TestCase] attribute instead:

[TestCase("wrongusername", "password")]
[TestCase("username", "wrongpassword")]
[TestCase("worngusername", "wrongpassword")]
[ExpectedException(typeof(SecurityTokenException))]
public void Validate_WithInvalidUsernameOrPassword_ThrowsException(string username, string password)
{
    var validator = new SimpleUsernameValidator();
    validator.Validate(username, password);
    Assert.Fail();
}

Note that you can also specify an expected result if the method under test returns a value*:

[TestCase(12,3, Result=4)]
[TestCase(12,2, Result=6)]
[TestCase(12,4, Result=3)]
public int DivideTest(int n, int d)
{
  return( n / d );
}

There is also a [TestCaseSource] attribute that can be used in conjunction with [TestCase] to identify a class that can supply test case arguments**:

[Test, TestCaseSource("DivideCases")]
public void DivideTest(int n, int d, int q)
{
    Assert.AreEqual( q, n / d );
}

static object[] DivideCases =
{
    new object[] { 12, 3, 4 },
    new object[] { 12, 2, 6 },
    new object[] { 12, 4, 3 } 
};

 

References

* TestCaseAttribute (NUnit 2.5)
** TestCaseSourceAttribute (NUnit 2.5)

Wednesday, 5 January 2011

Basic unit test coverage reporting with PartCover

I’m fed up with having to guess at how much of my code is covered with unit tests and there’s no budget for NCover. So, after a bit of hunting I came across PartCover, an open source code coverage tool for .Net (https://github.com/sawilde/partcover.net4). As I’ve just started using it so I thought I’d jot down a few notes on the basics of getting a coverage report working.

The first step is creating a settings file. This is an XML file containing the settings PartCover will use to produce a coverage report.

<PartCoverSettings>
  <Target>C:\path_to_nunit\nunit-console-x86.exe</Target>
  <TargetWorkDir>C:\path_to_source\EnquirySubmissionServiceCoreTests\bin\Debug</TargetWorkDir>
  <TargetArgs>EnquirySubmissionServiceCoreTests.dll</TargetArgs>
  <Rule>+[*]*</Rule>
  <Rule>-[EnquirySubmissionServiceCore]EnquirySubmissionServiceCore.Some.Namespace*</Rule>
  <Rule>-[log4net*]*</Rule>
  <Rule>-[Moq*]*</Rule>
  <Rule>-[nunit*]*</Rule>
  <Rule>-[EnquirySubmissionServiceCoreTests*]*</Rule>
</PartCoverSettings>

You need to provide a path to NUnit, a working directory (the directory containing the assembly to check), the target assembly and a set of rules. The rules are basically RegEx and tell PartCover what to include and what to exclude from the report. My rules say include everything (+[*]*) then start excluding assemblies I don’t want in the report.

Note line 6 of the above settings file. It is possible to exclude specific namespaces within an assembly so you can exclude files you don’t want to be tested for coverage. In fact, you can even exclude specific classes in the same way.

I saved the settings file into the PartCover installation directory and then ran PartCover.exe:

partcover.exe --settings settings.xml --output output.xml

This runs the PartCover with the settings file and creates an XML file containing the output (in this case named output.xml). The output file can be opened with PartCover.Browser.exe to view the results:

untitled

That’s it for a basic setup and first report generation. Looks like I’ve got a few unit tests to write…

Tuesday, 27 October 2009

Naming unit tests

In his book The Art of Unit Testing, Roy Osherove suggests the following format for the name of unit tests:

MethodUnderTest_Scenario_Behaviour()

  • MethodUnderTest - The name of the method being tested.
  • Scenario - This part gives us the “with” part of the name: “When I call method X with a null value, then it should do Y.”
  • Behaviour - This part specifies in plain English what the method should do or return, or how it should behave, based on the current scenario: “When I call method X with a null value, then it should do Y.”

Tuesday, 6 October 2009

Gallio test automation platform

Gallio is a neutral test automation platform designed to help run tests from a variety of testing frameworks in a unified environment. It is a project that seems to be a spin off from the MbUnit team but will run tests from a variety of other frameworks including NUnit.

The Gallio Icarus test runner is somewhat similar to the test runner you get with Resharper. There is also a command line tool called Echo that has support for generating test reports etc.

Gallio also integrates with CruiseControl.Net. You need to setup your build to export a report in Gallio XML format (e.g. run Gallio.Echo.exe as a build task) and update the <publishers> node in ccnet.config. There is then a new report plug-in to be added to the CCNet dashboard to display the Gallio reports.

http://www.gallio.org/