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

Friday, September 2, 2011

Creating a Local Build with psake, Part 2: Testing

In my last post Creating a Local Build with psake, Part 1: Compiling I showed how you could compile a solution with psake. This time we will expand our build script and include a task that will run all the tests in our solution using NUnit 2.5.10.

The output from building is often referred to as build artifacts. I like to configure the output of the projects in my solution so that they output to a folder called “build_artifacts”. In my example solution I have two projects. An WPF application and a test class library:

image

I have configured them so that the output from building with Debug is output to the “build_artifacts”-directory:

image

image

Now that the compilation outputs to our build artifacts folder we can make a psake task that finds all the test assemblies in “build_artifacts\Debug\Tests” and runs them with NUnit:

properties {
    $base_dir = resolve-path .\..
    $source_dir = "$base_dir\src"
    $build_artifacts_dir = "$base_dir\build_artifacts"
    $tools_dir = "$base_dir\tools"
    $config = "Debug"
    $test_dir = "$build_artifacts_dir\$config\Tests"
}

task test {    
    $testassemblies = get-childitem $test_dir -recurse -include *tests*.dll
    exec { 
        & $tools_dir\NUnit-2.5.10\nunit-console-x86.exe $testassemblies /nologo /nodots /xml=$test_dir\tests_results.xml; 
    }
}

Here I have defined some extra properties to make the script more readable and maintainable. We now have to remember to make the “local” task dependent on “test”. Let’s also add a “clean” task that deletes the build artifacts folder and recreates it:

task clean {
    rd $build_artifacts_dir -recurse -force  -ErrorAction SilentlyContinue | out-null
    mkdir $build_artifacts_dir  -ErrorAction SilentlyContinue  | out-null
}

Our build script now loos like this:

$framework = '4.0'

properties {
    $base_dir = resolve-path .\..
    $source_dir = "$base_dir\src"
    $build_artifacts_dir = "$base_dir\build_artifacts"
    $tools_dir = "$base_dir\tools"
    $config = "Debug"
    $test_dir = "$build_artifacts_dir\$config\Tests"
}

task default -depends local
 
task local -depends compile, test

task compile -depends clean {
    exec { msbuild  $source_dir\ContinuousDelivery.sln /t:Clean /t:Build /p:Configuration=$config /v:q /nologo }
}

task clean {
    rd $build_artifacts_dir -recurse -force  -ErrorAction SilentlyContinue | out-null
    mkdir $build_artifacts_dir  -ErrorAction SilentlyContinue  | out-null
}

task test {    
    $testassemblies = get-childitem $test_dir -recurse -include *tests*.dll
    exec { 
        & $tools_dir\NUnit-2.5.10\nunit-console-x86.exe $testassemblies /nologo /nodots /xml=$test_dir\tests_results.xml; 
    }
}

If we run build.bat we now get the following output:

image

We have now successfully run our tests with psake! This concludes how you can create a local build with psake. There might more to this than what I’ve shown, but I think this should be enough to get you going.

You can download the source code from GitHub.

Saturday, October 24, 2009

An AAA style BDD specification base class

Lately I have written a lot of Arrange, Act, Assert style tests using Rhino Mocks. I’ve also started to write more readable tests with a dash of BDD style naming like this:

[Fact]
public void Should_find_projects_when_user_searches()
{
 //Arrange
 var projectRepository = MockRepository.GenerateMock<IProjectRepository>();
 var projects = new List<Project> { ProjectMother.CreateProject("project 1"), ProjectMother.CreateProject("project 2") };
 projectRepository.Stub(me => me.FindByName(null)).IgnoreArguments().Return(projects);
 var presentationModel = new ProjectSearchPresentationModel(projectRepository);
 //Act
 presentationModel.SearchCommand.Execute("");
 //Assert
 projectRepository.AssertWasCalled(me => me.FindByName(""));
 Assert.Equal(projects.Count, presentationModel.Projects.Count);
}

The scenario for this test is “When the user searches”. If we look closely we see that it have two asserts. When the user searches it should ask the repository for projects and the result should be “displayed” in a list. This feels a bit odd. I have to create a name for the test that captures everything that has to be done when the user searches. This is hard and I’m likely to loose some of the intent. The solution is to split the test in a test for every assert. However, this means that I have to set up each test in an equal manner and call the serach command. This is DRY! To solve this I’ve created a test base class called Specification that enables me to write the above test like this:

namespace Specifications_for_project_search_presentation_model
{
 public class When_user_searches_for_projects : Specification
 {
     private ProjectSearchPresentationModel _presentationModel;
     private List<Project> _projects;
     private IProjectRepository _projectRepository;

     public override void Arrange()
     {
         _projectRepository = MockRepository.GenerateMock<IProjectRepository>();
         _projects = new List<Project> { ProjectMother.CreateProject("project 1"), ProjectMother.CreateProject("project 2") };
         _projectRepository.Stub(me => me.FindByName(null)).IgnoreArguments().Return(_projects);
         _presentationModel = new ProjectSearchPresentationModel(_projectRepository);
     }

     public override void Act()
     {
         _presentationModel.SearchCommand.Execute("");         
     }

     [Fact]
     public void should_search_repository()
     {
         _projectRepository.AssertWasCalled(me => me.FindByName(""));         
     }

     [Fact]
     public void should_show_result()
     {
         Assert.True(_presentationModel.CanShowProjects);
     }

     [Fact]
     public void should_list_projects_found()
     {
         Assert.Equal(_projects.Count, _presentationModel.Projects.Count);
     }
 }
}

I have now set up the context and called the search command only once, but have a seperate test for each assert. I think these kind of tests read nicely. I have a test class for each scenario and tests that reads like the specification for the scenario. This also look very good in ReSharper.

specifications

The base class is implemented like this for xUnit:

public abstract class Specification
{
 protected Specification()
 {
     Arrange();
     Act();
 }

 public abstract void Arrange();
 public abstract void Act();
}

Sunday, December 21, 2008

Test Data Builder

In every project you reach a point where you need test data for unit testing. Having a reasonably complex domain model can make this task "difficult" because testing an entity in many cases means that you also have to setup associations to other entities. Intializing objects per test is cumbersome and any changes to constructor arguments will break your tests. One of the solutions to this problem is to use the Object Mother pattern. It's basically a class with factory methods that helps you setup an object for testing. The object creation code is moved out of the tests so that it can be reused and making the test data more maintainable. So if you are developing a scrum application and want to create a project with a sprint and a user story you would do something like this:

public static class ProjectMother
{
 public static Project CreateProjectWithSprint()
 {
     Project project = new Project();
     Sprint sprint = new Sprint();
     UserStory userStory = new UserStory();
     userStory.Name = "User story";
     userStory.StoryPoints = 8;
     sprint.AddUserStory(userStory);
     project.AddSprint(sprint);
     return project;
 }
}

Project project = ProjectMother.CreateProjectWithSprintAndUserStories();
However as time goes by you end up with a lot of factory methods for the slightest variation in the test data beacuse of the heavy coupling that exists since many tests use the same method. This make the Object Mother class hard to maintain. To solve this problem I usually write a fluent interface (embedded domain specific language) that I use to initalize my objects for testing. This is heavily based on the Expression Builder pattern. For each class I want to test I write a builder for that class. So when I want to create a Project object I just write:
Project project = ProjectBuilder.Create.Project
              .WithName("Test Project")
              .WithSprint(SprintBuilder.Create.Sprint
                  .WithName("Sprint 1")
                  .WithUserStory(UserStoryBuilder.Create.UserStory
                      .WithName("Story 1")
                      .WithStoryPoints(13)
                      .WithTask(TaskBuilder.Create.Task
                          .WithName("Task 1")
                          .WithHours(3))));

Behind the scenes the ProjectBuilder takes care of everything adding sprints and so on. In each method the builder just returns itself after having done some setup on the private Project instance. The ProjectBuilder is finally casted to Project using an implicit cast operator which returns the private Project instance.
public class ProjectBuilder
{
 private static Project mProject;

 public static ProjectBuilder Create
 {
     get { return new ProjectBuilder(); }
 }

 public ProjectBuilder WithName(string name)
 {
     mProject.Name = name;
     return this;
 }

 public ProjectBuilder Project
 {
     get
     {
         mProject = new Project { Name = "Test Project" };
         return this;
     }
 }

 public ProjectBuilder WithSprint(Sprint sprint)
 {
     mProject.AddSprint(sprint);
     return this;
 }

 public ProjectBuilder WithBacklog(Backlog backlog)
 {
     mProject.Backlog = backlog;
     return this;
 }

 public static implicit operator Project(ProjectBuilder builder)
 {
     return mProject;
 }

}
Still, I don't feel that the Object Mother and the Builder are mutually exclusive. If I have a lot of tests that use the same test data I often create an Object Mother with a factory method that uses the builders. When I need a specialized initialization of an object for a test I just use the builders directly in my tests.

I find this way of creating test data really useful and hopefully you do too! Feel free to download and use the code. The builders are located in the tests project.

Merry Christmas!!