Functional Testing with Twist

•3 October 2009 • 5 Comments

Twist is an automated functional testing framework from ThoughtWorks Studios. I am used to using FitNesse so I am interested in seeing how the two products compare.

Writing your first real FitNesse test can be tricky business, which fixture should I use, where does my wiki mark up go, how is my wiki markup different depending on which fixture type I choose etc etc. Using Twist I found that it took only about 10 minutes to write and execute my first fixture, scenario in Twist language and this is what was involved :

  • Create a new project

CreateNewTwistProject

  • Create a new scenario and call it something like ‘When searching for Twist on Google’
  • Using the intellisense sortcut in elclipse, ctrl+space, Twist gives you the option of adding a new ‘Business Scenario’ . Select this option and name the scenario ‘Should display the link to the twist home page’.

To define the steps that Twist should carry out you write a bulleted list of actions, here is my example:

NewWorkflow

At this point you can execute the scenario, click on the execute button in the top right of the screen, the test will run but will fail. The error message is “java.lang.Exception: Context “New Context” is not implemented”, cryptically, this is telling me that I have to go and implement the java that will execute this workflow.

The context contains the setup and tear down code for the test, to create this click on the at the top.

import com.thoughtworks.twist.driver.selenium.TwistSelenium;

public class NewContext {

	private TwistSelenium selenium;

	public NewContext(TwistSelenium selenium) {
		this.selenium = selenium;
	}

	public void setUp() throws Exception {
		selenium.open("http://www.google.co.uk");
	}

	public void tearDown() throws Exception {
		selenium.close();
	}
}

Run the scenario again and you will get the following exception ‘java.lang.Exception: Workflow step “Enter text “Twist”” is not implemented’. This is telling you to create a method called ‘enterText’. To implement this you can click on the workflow item and use ctrl+space again this will give you an option to generate a stub class with the correct name. You can create the method ‘enterText’ by clicking on the ‘Enter text “Twist”‘ workflow item and using ctrl+space this will again give you an option of creating the method stub with the correct name, implement the method and re-run the test.

Re-running the test will give you another exception, not surprisingly, telling me that the clickOn method is not declared, so I implement that and the last method, assertThatExistsOnThePage, and run the test one more time. Hoooray, it passes, I can see IE start up and selenium running through my scenario. Cool stuff.

Here is the code I finished up with:

// JUnit Assert framework can be used for verification

import com.thoughtworks.twist.driver.selenium.TwistSelenium;

public class ShouldFindThoughtWorksInTheSearchResults {

	private TwistSelenium selenium;

	public ShouldFindThoughtWorksInTheSearchResults(TwistSelenium selenium) {
		this.selenium = selenium;
	}

	public void enterText(String text) throws Exception {
		selenium.type("q", text);
	}

	public void clickOn(String identifier) throws Exception {
		selenium.click(identifier);
	}

	public void assertThatExistsOnThePage(String text) throws Exception {
		assertThatExistsOnThePage(text);
	}
}

Aside: Another nice feature of Twist, is it has tight integration with a unit testing framework, jUnit, which I can leverage to implement my assertions, FitNesse does not give you this tight integration.

Another aside: I am sure you have worked this out but the correlation between the steps in the business workflow and the methods that are created in java is as follows. Each step in the business workflow represents a method call, the methods are named by concatenating the words that are not in quotes and applying camelCasing, the words that are in quotes are the parameters that the method takes and are passed to the method in the order they appear. This is quite similar to the Do fixture in FitNesse.

Twist has an integrated environment for writing your tests, it is built ontop of elclipse, which is something that FitNesse lacks, it also doesn’t require you to learn any wiki markup to specify your scenarios. For me this is more of a benifit, whilst you are getting over the initial learning curve, as you become more proficient this is likley to be less important.

I use FitNesse for testing subsystems, things like individual services and for end-to-end testing, obviously for testing the whole system. The immediate disadvantage with Twist is that I can’t use it for subsystem testing. Twist has been designed to sit on-top of tools like selenium and Frankenstein which drive the UI. Additionally I predominatly work in a .Net environment, FitNesse provides a .Net adaptor to allow me to get into the code and configure and host my services, Twist doesn’t provide that level of support for anything that is not written in Java. An obvious downside to Twist vs FitNesse is that it is a paid for product.

I have used Twist to add tests here to add tests to an existing system, I see no reason why you couldn’t use this to specify your system as well before it has been created.

After only a brief encounter with Twist I’m not sure if it is as flexible or mature as FitNesse but it looks like a nice product to use and I can definatly see that it has its place. I have definatly got some more questions regarding Twist so will be spending some more time figuring out what is possible with it. It would also seem to be lacking one key feature which is integration with Mingle, without this you are going to have to maintain 2 separate sets of requirements.

You can download a trial version of Twist from: ThoughtWorks Studios.

Uninstalling Picasa – Ubuntu

•29 May 2009 • 5 Comments

It seems that there is no obvious way to uninstall Picasa on Ubuntu.

After some quick Googling I found a simple way to do it.

Just run:
sudo aptitude remove picasa

Done!

Unlocking G1 for Vodafone UK

•6 January 2009 • 14 Comments

I was lucky enough to get a G1 for Christmas last year, as true for all new G1’s in the UK the phone was sim-locked to T-Mobile. This is a quick guide to how you can unlock the phone for use on Vodafone UK, you’ll be up and running in 5 minutes flat!

With the phone my girlfriend had given me an ghost-sim to do the unlocking. The chip is a thin pcb with a single microchip in one corner. The ghost-sim is designed to live between the contacts on your sim card and the contacts on the phone. Although the ghost-sim is very thin the microchip is quite big. This means that to get a good fit you will need make a couple of small cuts on the sim card.

unlock-chip sim-cut

sim-cutdone

You have quite enough space at this end of the sim card before you get anywhere near the contacts on the back, so no need to worry about that! Once you have cut the sim card you can now slide it together with the ghost-sim into your G1, put the battery in and switch it on. The ghost-sim will unlock the phone from the minute the phone is switched on but by default the phone only knows about T-Mobile Access Point Names, so you’ll have to add some settings to get the phone working on Vodafone.

When the phone comes on you should see the “Login to your Google account screen”, press the phones’ menu button, the “New APN” menu will popup. Select it and enter the following settings for Vodafone UK.

Name: Vodafone

APN: wap.vodafone.co.uk

Username: wap

Password: wap

Leave the MMC and MNC settings with their default values (234 & 15).

All other settings should be left blank otherwise you will not be able to connect, this caught me out! Save the new APN by using the menu button again. You should now be able to get a 3G connection and login to your Google account. All services other than MMS (some extra settings are required for this) should be available to you. I have been using my G1 for a couple of weeks now without any problems.

This was written from memory so if I have missed a step let me know and I’ll update.

Cheers

Tim

Running integration tests using Cassini and NUnit

•9 December 2008 • 6 Comments

Recently, at work, I had the opportunity to do some work on a greenfield ASP.Net MVC application. Part of the development involved creating a suite of integration tests/specs. I had worked on projects where we had written integration tests before but they relied on having an installation of the system, this usually means configuring IIS, around for the tests to run against. This has not always been available on the CI server. A better solution is to create an instance of a web server as part of the TestFixtureSetUp. Here’s how easy it is with Cassini.

Create an abstract class that forms the base class for the integration tests.

using System.Configuration;
using Cassini;
using NUnit.Framework;

namespace TimEscott.Blog.WebApp.Tests.Integration
{
    public abstract class IntegrationTestBase
    {
        private readonly IntegrationTestConfig config;
        private Server webServer;

        protected IntegrationTestBase()
        {
            config = (IntegrationTestConfig) ConfigurationManager.GetSection("IntegrationTest");

            if(config == null)
            {
                throw new IntegrationTestConfigurationException("Could not load configuration information to run the integration tests.");
            }
        }

        [TestFixtureSetUp]
        public void TestFixtureSetup()
        {
            webServer = new Server(config.Port, config.VirtualPath, config.PhysialPath);
            webServer.Start();
        }

        [TestFixtureTearDown]
        public void TestFixtureTearDown()
        {
            if(webServer != null)
            {
                webServer.Stop();
            }
        }

        protected string BuildTestUrl(string path)
        {
            return string.Format("http://localhost:{0}/{1}", config.Port, path);
        }
    }
}

So now I can create an integration test, using WatiN:

using NUnit.Framework;
using NUnit.Framework.SyntaxHelpers;
using WatiN.Core;

namespace TimEscott.Blog.WebApp.Tests.Integration.Home
{
    [TestFixture]
    public class When_loading_the_home_page : IntegrationTestBase
    {
        [Test]
        public void Should_contain_the_correct_title()
        {
            using (var ie = new IE())
            {
                ie.GoTo(BuildTestUrl("Home"));

                Assert.That(ie.ContainsText("Welcome to ASP.NET MVC!"), Is.True);
            }
        }

    }
}

Here is the config class and the app.config for completeness:

using System.Configuration;

namespace TimEscott.Blog.WebApp.Tests.Integration
{
    public class IntegrationTestConfig : ConfigurationSection
    {
        [ConfigurationProperty("Port", IsRequired = true)]
        public int Port
        {
            get { return int.Parse(this["Port"].ToString()); }
        }

        [ConfigurationProperty("VirtualPath", IsRequired = true)]
        public string VirtualPath
        {
            get { return this["VirtualPath"].ToString(); }
        }

        [ConfigurationProperty("PhysialPath", IsRequired = true)]
        public string PhysialPath
        {
            get { return this["PhysialPath"].ToString(); }
        }
    }
}
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <configSections>
    <section name="IntegrationTests"
             type="TimEscott.Blog.WebApp.Tests.Integration.IntegrationTestConfig, TimEscott.Blog.WebApp.Tests.Integration"/>
  </configSections>
  <IntegrationTests Port="4015"
                   VirtualPath="/"
                   PhysialPath="C:\Projects\Blog\TimEscott.Blog.WebApp\" />
</configuration>

This in conjunction with something like Ayende’s SqlCEDbHelper as a mechanism to help create a test database, gives a very portable test suite which can run anywhere that .Net and Cassini are installed.

Scott Hanselman describes one way to remove the pre-requisite we have here (having the Cassini dll installed in the GAC). But for the sake of having one dll installed on an internal server I am currently not too worried about having this dependency.

A nice addition might be to actually check that the port is free, if not find one that is?!

Fluent Rhino Mocks

•30 October 2008 • Leave a Comment

I was recently introduced to the fluent interface that the Rhino Mocks library exposes. I wasn’t sure that it was as easy to read as the Record/Playback syntax I was use to using. I persisted with the ‘new’ syntax to see if I could see any benefit of using the fluent interface.

I now find that using the fluent interface helps on a number of fronts.

  • Eliminates many potential mistakes buy using method chaining.
  • Helps me keep to one Expectation or Assert per test.
  • Makes my code more like an English sentence and therefore easier to read.
  • Means that my code is smaller.
  • Allows me to use ExpectingInSameOrder – although I haven’t found a really good use for this yet.

I have to say I wasn’t instantly sold on the syntax but the more I used it the more I like it.

Here is a simple example of a refactored test using the fluent interface.

Original

[Test]
public void Should_leverage_the_repository_to_retrieve_all_games()
{
    using (mockery.Record())
    {
        Expect.Call(repository.Find(null)).Return(new List<Game>()).IgnoreArguments();
    }

    using (mockery.Playback())
    {
        service.GetGames();
    }
}

New

[Test]
public void Should_leverage_the_repository_to_retrieve_all_games()
{
    With.Mocks(mockery)
        .Expecting(() => Expect.Call(repository.Find(null)).Return(new List<Game>()).IgnoreArguments())
        .Verify(() => service.GetGames());
}

A whole 50% smaller!

TDD with Monorail – Part 6

•6 August 2008 • 1 Comment

As promised the mapping and repository layers…

Not much of particular interest here really, but for the sake of completeness I will write about what I have done in these areas.

The Mappers

The mappers are mainly a supporting mechanism to allow me to send messages through the API interface rather than the domain objects themselves. A mapping classes simply takes an object of a specific type and returns an object of another type. The interface implemented by all my mappers also defines a method for doing this for a collection of the same types. Here is how I implemented a mapper for my SaveUserRequest message and User domain classes.

mappers

The test

using NUnit.Framework;
using NUnit.Framework.SyntaxHelpers;
using TimEscott.GrassRoots.Core.Mappers;
using TimEscott.GrassRoots.Specs.Builders.Domain;
using TimEscott.GrassRoots.Specs.Builders.Messages;

namespace TimEscott.GrassRoots.Specs.Unit.Mappers
{
    [TestFixture]
    public class When_mapping_a_save_user_request_to_a_user : UnitTestBase
    {
        private IUserMapper mapper;

        [SetUp]
        public void SetUp()
        {
            userBuilder = new UserBuilder();
            saveUserRequestBuilder = new SaveUserRequestBuilder();
            mapper = new UserMapper();
        }

        [Test]
        public void Should_create_a_user()
        {
            var expectedUser = userBuilder.BuildVaildObject();

            var actualUser = mapper.MapFrom(saveUserRequestBuilder.BuildVaildObject());

            Assert.That(actualUser.Email, Is.EqualTo(expectedUser.Email));
            Assert.That(actualUser.FirstName, Is.EqualTo(expectedUser.FirstName));
            Assert.That(actualUser.Surname, Is.EqualTo(expectedUser.Surname));
            Assert.That(actualUser.Phone, Is.EqualTo(expectedUser.Phone));
        }
    }
}

The implementation – notice that I have not implemented the map collection method yet as I do not have a requirement for it.

using System.Collections.Generic;
using TimEscott.GrassRoots.Core.Domain;
using TimEscott.GrassRoots.Core.Messages.Users;

namespace TimEscott.GrassRoots.Core.Mappers
{
    public class UserMapper : IUserMapper
    {
        public User MapFrom(ISaveUserRequest source)
        {
            return new User()
                       {
                           Email = source.Email,
                           FirstName = source.FirstName,
                           Surname = source.Surname,
                           Phone = source.Phone
                       };
        }

        public IEnumerable<User> MapCollection(IEnumerator<ISaveUserRequest> sources)
        {
            throw new System.NotImplementedException();
        }
    }
}

I am not really sure that there is much more to say about the mappers.

The Repository layer

This is where things are quite exciting for me. Coming from a world without ORM, now that I know about it I don’t know how I ever lived without it. I am using another part of the Castle stack here, ActiveRecord. To use ActiveRecord there is a couple of things I need to do to wire things up. Firstly I need to add the ActiveRecord config to the Windsor config files.

<facility
            id="activerecord"
            type="Castle.Facilities.ActiveRecordIntegration.ActiveRecordFacility, Castle.Facilities.ActiveRecordIntegration"
            isDebug="false"
            isWeb="true">

      <assemblies>
        <item>TimEscott.GrassRoots.Core</item>
      </assemblies>

      <config>
        <add key="connection.driver_class" value="NHibernate.Driver.SqlClientDriver" />
        <add key="dialect" value="NHibernate.Dialect.MsSql2000Dialect" />
        <add key="connection.provider" value="NHibernate.Connection.DriverConnectionProvider" />
        <add key="connection.connection_string" value="Data Source=TIMESCOTT-PC\SQLEXPRESS;Initial Catalog=GrassRoots;Integrated Security=SSPI"/>
      </config>
    </facility>

The other thing I am going to do is to get ActiveRecord to create the database schema for me. To do this I have added this line to Application_Start method in Global.asax. Now each time I start the application the tables are going to get dropped and recreated – so unless I want to re-generate the schema because of a change in the domain, I will comment this line out.

ActiveRecordStarter.CreateSchema();

There are much better ways to manage the database schema, but at this stage of the application I am not too worried about it. Something that I want to take some time to look at is Migrations for .Net as a solution to schema management.

A repository is a class that is only concerned with persisting and retrieving an object of a particular type. I have setup a generic interface IRepository<T> and an ActiveRecordRepository which implements it. Currently the interface only defines a Save method as this that is the only requirement I have for this stripe of development. Using the ActiveRecordMediator means that I only have to create this one class and that is all my repository layer needs to consist of. Here is the code:

using TimEscott.GrassRoots.Core.Domain;

namespace TimEscott.GrassRoots.Core.Repositories
{
    public interface IRepository<T> where T : IEntity
    {
        void Save(T instance);
    }
}
using Castle.ActiveRecord;
using TimEscott.GrassRoots.Core.Domain;

namespace TimEscott.GrassRoots.Core.Repositories
{
    public class ActiveRecordRepository<T> : IRepository<T> where T : class, IEntity
    {
        public void Save(T instance)
        {
            ActiveRecordMediator<T>.Save(instance);
        }
    }
}

I don’t have any unit tests on the repositories themselves as they do not appear to be obviously unit testable. Having said that I don’t think this is a huge problem as it is a very small amount of code and this area will be covered by my integration tests.

Mapping the User class to the database

Now I have got my repository sorted I am now ready to wire up some classes to the database. I am going to do this using attributes in the classes. Here is the User class tagged with the necessary ActiveRecord attributes.

using Castle.ActiveRecord;

namespace TimEscott.GrassRoots.Core.Domain
{
    [ActiveRecord("`User`")]
    public class User : EntityBase
    {
        [Property(NotNull = true)]
        public string Email { get; set; }

        [Property(NotNull = true)]
        public string FirstName { get; set; }

        [Property(NotNull = true)]
        public string Surname { get; set; }

        [Property(NotNull = true)]
        public string Phone { get; set; }
    }
}

You might have noticed that the User class does not have an Id field, that is defined in its base class, EntityBase. The IEntity interface and EntityBase class are used to ensure that any object that is mapped to the database has the required fields. Currently all that consists of is an Id of type Guid. Here is the class diagram.

domain

Okay, so all I need to do now is to create the database and run the application!

Just a note on choice of database engine…
I am currently using SQL Server Express 2005, I wanted to have a play with SQLite as it seems far easier to deploy and much more lightweight. Has anyone had any experience with setting this up with ActiveRecord or found a good post about this? I have had a look around and tried to set it up but seemed to be unable to get hibernate to open a connection to the database. Anyway I will continue to try and get SQLite running with this project and will put up a post when I get it working.

TDD with Monorail – Part 5

•6 August 2008 • Leave a Comment

Service Layer

Currently the responsibilities of my UserService are simply are to:

  • Validate the request
  • Map to a domain object
  • Delegate the actual work to fulfil the request to a repository

These requirements are reflected in my test for the Save method in the UserService:

using NUnit.Framework;
using NUnit.Framework.SyntaxHelpers;
using Rhino.Mocks;
using TimEscott.GrassRoots.Core.Domain;
using TimEscott.GrassRoots.Core.Mappers;
using TimEscott.GrassRoots.Core.Messages.Users;
using TimEscott.GrassRoots.Core.Repositories;
using TimEscott.GrassRoots.Core.Services;

namespace TimEscott.GrassRoots.Specs.Unit.Services
{
    [TestFixture]
    public class When_saving_a_user : UnitTestBase
    {
        private MockRepository mockery;
        private IRepository<User> repository;
        private IUserMapper mapper;
        private UsersService service;

        [SetUp]
        public void SetUp()
        {
            mockery = new MockRepository();
            repository = mockery.DynamicMock<IRepository<User>>();
            mapper = mockery.DynamicMock<IUserMapper>();

            service = new UsersService(repository, mapper);
        }

        [Test]
        public void Should_validate_the_save_user_request_save_a_user_and_return_a_valid_response()
        {
            var request = mockery.DynamicMock<ISaveUserRequest>();
            var user = userBuilder.BuildVaildObject();
            SaveUserResponse response;

            using (mockery.Record())
            {
                Expect.Call(() => request.Validate());
                Expect.Call(mapper.MapFrom(request)).Return(user);
                repository.Save(user);
            }

            using (mockery.Playback())
            {
                response = service.Save(request);
            }

            Assert.That(response.Success, Is.True);
        }
    }
}

You’ll notice that I have given up with a convention that I stated using in an earlier post which was to call the system under test ‘subject’. I have chosen to give the fields names that give me some more context.

Writing this test has meant that I have needed to create a couple of other interfaces:

  • IUserMapper – will take a SaveUserRequest and return a valid User object
  • IRepository<User> – will be able to persist users

These were again mocked, to focus the test. Here is the implementation of the service:

using TimEscott.GrassRoots.Core.Domain;
using TimEscott.GrassRoots.Core.Mappers;
using TimEscott.GrassRoots.Core.Messages.Users;
using TimEscott.GrassRoots.Core.Repositories;

namespace TimEscott.GrassRoots.Core.Services
{
    public class UsersService : IUsersService
    {
        private readonly IRepository<User> repository;
        private readonly IUserMapper mapper;

        public UsersService(IRepository<User> repository, IUserMapper mapper)
        {
            this.repository = repository;
            this.mapper = mapper;
        }

        public SaveUserResponse Save(ISaveUserRequest request)
        {
            request.Validate();

            repository.Save(mapper.MapFrom(request) as User);

            return new SaveUserResponse(true);
        }
    }
}

UnitTestBase

A point of interest about the unit test above is that it extends my UnitTestBase. UnitTestBase contains a number of protected fields for building objects used in the unit tests.

Some history behind this, I have worked on projects where the objects used in the tests are created as part of the setup or as part of the test itself each time one is required, resulting in a lot of duplicated code. I think that this approach is great in some respects as it clearly defines the intent of the test. But my concern was that if I were to make a change to the structure of a domain object, for example, then the number of changes that I would have to make to my tests just to get them to compile could be wide reaching. Maybe this is what you actually want because the tests are doing their job of highlighting changes to the behaviour and specifications of the code and forcing you to consider each case.

To counter some of this I am going to experiment with having some builder objects in UnitTestBase which I instantiate in the default constructor, which I can call to create valid or invalid objects of a particular type. As I said this is an experiment so we will have to re-evaluate in a few weeks and see if we can refactor and improve on the initial idea. I can already see that the number of these objects might grow rapidly so the management of them might be an issue, but in the spirit of YAGNI until I have a problem I am not going to try and fix it. I would also rather that the builder objects were instantiated during a setup rather than once in the constructor. I am also considering getting it to create mockery for me as well – more on this when I get round to refactoring it. For reference here is the current code for the TestUnitBase and a builder class and its interface:

UnitTestBase

using TimEscott.GrassRoots.Specs.Builders.Domain;
using TimEscott.GrassRoots.Specs.Builders.Messages;

namespace TimEscott.GrassRoots.Specs.Unit
{
    public abstract class UnitTestBase
    {
        protected UserBuilder userBuilder;
        protected SaveUserRequestBuilder saveUserRequestBuilder;

        protected UnitTestBase()
        {
            userBuilder = new UserBuilder();
            saveUserRequestBuilder = new SaveUserRequestBuilder();
        }
    }
}

IBuilder – Can currently provide an Invalid and Valid object of type T.

namespace TimEscott.GrassRoots.Specs.Builders
{
    public interface IBuilder<T>
    {
        T BuildVaildObject();
        T BuildInVaildObject();
    }
}

SaveUserRequestBuilder

using TimEscott.GrassRoots.Core.Messages.Users;

namespace TimEscott.GrassRoots.Specs.Builders.Messages
{
    public class SaveUserRequestBuilder : IBuilder<SaveUserRequest>
    {
        public SaveUserRequest BuildVaildObject()
        {
            return new SaveUserRequest()
                       {
                           Email = "tim.escott@gmail.com",
                           FirstName = "Tim",
                           Surname = "Escott",
                           Phone = "09988776655"
                       };
        }

        public SaveUserRequest BuildInVaildObject()
        {
            return new SaveUserRequest()
                       {
                           Email = null,
                           FirstName = null,
                           Surname = null,
                           Phone = null
                       };
        }
    }
}

A pretty short post this time looking at the service layer and the builder idea, in part 6 we will look at the repositories and the mappers.