October 2004 - Posts

Integrating NUnit into Continuous Integration and Frustration

Boy, did I have a frustrating couple of days. I started what I thought would be a really simple task, everyone's done it millions of times, no problem. I wanted to integrate the NUnit tests that I have written for my initial set of classes into my continuous integration system. In reading up on this there are two ways to do this

  1. Add NUnit support via CruiseControl.Net and the NUnit Task
  2. Add NUnit support via NAnt and the NUnit2 Task

CruiseControl.Net recommends against using the CruiseControl.Net's version

We recommend not using this task, and using your builder to run your tests if possible. This way if the tests fail and you don't know why, it is a lot easier to try and replicate the problem on another machine.

Therefore, I decided to add the following <nunit2> task to my default.build files for all of my Lorengo.VirtualCellar.*.Tests assemblies

<target name="build" depends="clean">
	<tstamp>
		<formatter property="DSTAMP" pattern="yyyy-MM-dd"/>
		<formatter property="TSTAMP" pattern="HH:mm"/>
	</tstamp>
	<echo message="Build started at : ${DSTAMP} - ${TSTAMP}"/>
	<solution configuration="debug">
		<projects>
			<include name="..\Lorengo.Framework\Lorengo.Framework.csproj"/>
			<include name="..\Lorengo.VirtualCellar.Data\Lorengo.VirtualCellar.Data.csproj"/>
			<include name="..\Lorengo.VirtualCellar.Business\Lorengo.VirtualCellar.Business.csproj"/>
			<include name="${basename}.csproj"/>
		</projects>
	</solution>
	<nunit2>
		<formatter type="Xml" usefile="false"/>
		<test assemblyname="${build.dir}\${basename}"/>
	</nunit2>
</target>

Of course after I did this and ran NAnt, I got the following error.

BUILD FAILED

D:\VirtualCellar\Lorengo.VirtualCellar.Business.Tests\default.build(26,4):
Failure executing test(s). If you assembly is not built using NUnit version 2.2.0.0, then ensure you have redirected assembly bindin
gs. Consult the documentation of the  task for more information.
    File or assembly name 'Lorengo.VirtualCellar.Business', or one of its dependencies, was not found.
        The system cannot find the file specified.

Total time: 3.8 seconds.

New Version of Nant

Great, so I do some research and find this entry which points to a problem in the 0.84 version, and that it is fixed in version 0.85. So off I go to download the latest build. I run it again, and I still get the same error. Dang!

Runtime Assembly Binding

More research, this time I read the nightly build version of the NAnt help file for the NUnit task, and it recommends that I add the following to my .config for my test assembly (Lorengo.VirtualCellar.Business.Tests.dll.config). Ok, no problem, I updated it and run the build again. Aaargh! Same error.

Multiple nunit.framework.dlls

Now I begin to suspect that it's not finding the right nunit.framework.dll, so I do a search on my machine for all nunit.framework.dll's. I end up with a bunch because I've been messing around with:

  • TestDriven.Net - The NUnit Add-In for VS200x and MbUnit. I still haven't got this working successfully, but James Cansdale, is getting closer to fixing my issues with running as a Non-Administrator.
  • ZaneDebug - A similar tool to TestDriven.Net (although no addin) that also adds performance metrics. However I haven't been able to run this successfully, and it only supports NUnit 2.1 right now.

In looking at the versions of nunit.framework.dll, I notice I have version 2.1.04, 2.2.0.0, and 2.3.00 (what? I didn't know NUnit was at 2.3. It turns out this was installed by TestDriven.Net, I'll have to find out more about that). So now I think it has something to do with my multiple installations of nunit.framework.dll, I begin uninstalling those tools, since they didn't really pass this rule for running software (I'll continue to revisit them because they do look promising). But I digress, did uninstalling this work? NO!

Using NAnt -verbose+

That's it, I'm beginning to get depressed so what do I do? I remember the -verbose+ option of NAnt, so now I get the following out put.

D:\VirtualCellar\Lorengo.VirtualCellar.Business.Tests\default.build(26,4):
Failure executing test(s). If you assembly is not built using NUnit version 2.2.0.0, then ensure you have redirected assembly bindin
gs. Consult the documentation of the <nunit2> task for more information.:
NAnt.Core.BuildException: D:\VirtualCellar\Lorengo.VirtualCellar.Business.Tests\default.build(26,4):
Failure executing test(s). If you assembly is not built using NUnit version 2.2.0.0, then ensure you have redirected assembly bindin
gs. Consult the documentation of the <nunit2> task for more information. ---> System.IO.FileNotFoundException: File or assembly name
'Lorengo.VirtualCellar.Business', or one of its dependencies, was not found.
File name: 'Lorengo.VirtualCellar.Business' ---> System.IO.FileNotFoundException: The system cannot find the file specified.

What! Oh my god do I feel stupid. If only I would have looked at the original error message a little more closely. The problem has to do with the fact that I did not include the ".dll" after my assembly in my NUnit2 task.

...
	<nunit2>
		<formatter type="Xml" usefile="false"/>
		<test assemblyname="${build.dir}\${basename}.dll"/>
	</nunit2>
...

Run NAnt again and Voila! It worked. All of my tests run and pass.

Lessons Learned

So, what have I learned?

  1. Read the error message more closely
  2. If something goes wrong, and you don't find a lot of other people having a similar problem, it's probably something you are doing
  3. Use the -verbose+ switch on NAnt sooner rather than later
  4. Have another set of eyes take a look at your problem. (This is something that I miss, working at home there's not too many people around here to have a second look, unless you count my cats, if they could ever get there lazy eyes open long enough to look at something).

The good news is that I now have NUnit integration in CruiseControl.Net working, and I can get back to coding up some more functionality in the Virtual Cellar.

 

with 0 Comments

Incorporating a Repository in the Virtual Cellar

A couple of quick links to throw out there

NCover - Code Coverage Tool.
NCoverBrowser - A tool created by Jeff Key to easily see your code coverage file.
Michael Swanson has a post about integrating MSBuild into a Continuous Integration environment

Virtual Cellar

So, I've been busy over the last few days implementing some classes in my architecture so I really haven't had time to post to my blog. In this post I'll discuss my implementation. I've been following the Repository discussions put forth by Steve Maine and Steve Eichert, as well as re-reading some sections in Martin Fowler's PoEAA book. Incidentally he's been busy adding further information here.

As you may (or may not recall), I laid out my initial application architecture in this post. I'd like to revisit that architecture in this post and add some concrete code samples as well. The figure below illustrates my "version 2" of the Virtual Cellar architecture, and it illustrates what I've currently coded so far

As you can see there is not much change in the lower data layers, these classes belong to the Lorengo.VirtualCellar.Data namespace, and use the provider model for isolating the data storage specific code. In the figure above, the ProducerRepository uses the IProducerDataProvider interface for handling the CRUD operations on Producer instances. The AccessVirtualCellarDataProvider uses System.Data.OleDb classes in it's implementation.

The ProducerRepository sets it's IProducerDataProvider _producerDataProvider member by calling the GetProducerDataProvider method.

_producerDataProvider = (VirtualCellarDataProviderBase.Instance()).GetProducerDataProvider();

The GetProducerDataProvider looks at the .config file for the application and loads the appropriate class (in this case the AccessVirtualCellarDataProvider). This code was patterned after the model used in .Text

<virtualCellar defaultProvider="AccessVirtualCellarDataProvider" defaultLanguage="en-en" >
  <providers>
    <clear/>
    <add name = "AccessVirtualCellarDataProvider" 
	 type = "Lorengo.VirtualCellar.Data.AccessVirtualCellarDataProvider, Lorengo.VirtualCellar.Data" 
	 connectionString = "Provider=Microsoft.Jet.OLEDB.4.0;User ID=Admin;Data Source=Lorengo.VirtualCellar.DB.Access\VirtualCellar.mdb;"
    />
  </providers>
</virtualCellar>

The ProducerRepository implements the IRepository interface. Currently only two methods are defined

public interface IRepository
{
    RepositoryItemBase Load( int id );
    void Save( RepositoryItemBase ri );
}

You'll notice that these methods reference the RepositoryItemBase class, which all classes wishing to be stored in a repository must inherit from. Looking at the class diagram you can see that the RepositoryItemBase class declares two attributes that support <<get>> and <<set>> operations. The "Id" property which is unique by repository for that specific instance, and the RepositoryState (I'll have to think of a better name, perhaps ItemState) which is an enum as defined below.

public enum RepositoryItemState
{
    New = 0,	// Item is new and not yet stored in the repository
    Dirty = 1,	// Item has changed since it was last retrieved from the repository
    Clean = 2	// Item is unchanged since it was last retrieved from the repository
}

The RepositoryItemState enum is used by the class implementing the IRepository interface to determine whether the RepositoryItem should be created or updated in the repository.

The RepositoryItemBase class allows the setting of these two attributes while the Producer class uses the c# "new" modifier to provide a new implementation which prevents this. Only the Repository for this class should be able to modify these attributes. This scheme only works if the developer of new business domain classes chooses to add the new implementation, it is not enforced by the design. A better solution would be to derive a new class from RepositoryItemBase which already hides the setter and move the Repository classes to their own assembly, then mark the RepositoryItemBase classes as protected internal to prevent business domain classes from overriding their behavior, for now however I will leave these classes as is.

So looking at some inital code for the ProducerRepository.Save()

/// <summary>
/// Saves the Producer to the repository
/// </summary>
/// <param name="ri"></param>
public void Save( RepositoryItemBase ri )
{
    Producer p = (Producer)ri;

    if( p == null )
    {
        throw new ArgumentNullException( "Object to save cannot be null." );
    }

    switch( ri.RepositoryState )
    {
        case RepositoryItemState.New:
        {
            ri.Id = this.ProducerDataProvider.Add( p.Name );
            ri.RepositoryState = RepositoryItemState.Clean
            break;
        }

        case RepositoryItemState.Dirty:
        {
            this.ProducerDataProvider.Update( p.Id, p.Name);
            ri.RepositoryState = RepositoryItemState.Clean
            break;
        }

        case RepositoryItemState.Clean:
        {
            // No need to do anything
            break;
        }

        default:
        {
           break;
        }
    }
}

Based on the RepositoryState we call either the Add() or Update method. Also since we are referencing the RepositoryItemBase class this allows us to set the .Id for newly created objects and modify the .RepositoryState for reflecting its Clean state. We also know that since this is a ProducerRepository we can upcast the ri instance to a Producer instance for the purpose of retrieving the Producer.Name information.

Now, this code is not perfect, we should be doing a check to make sure we are indeed getting a Producer object and throw an exception if we did not get one. I should break out refactor the different cases into their own private methods, and enclose the calls to the DataProviders in try...catch blocks to ensure that RepositoryState is updated correctly.

So what would some code look like? Well I've written multiple test cases for each of these new classes (actually I wrote those first). Here's the Save tests for the ProducerRepository class.

/// <summary>
/// Tests to make sure a newly created Producer can be saved
/// </summary>
[Test]
public void SaveProducer()
{
    Producer p1 = new Producer();
    p1.Name = "Hightower Cellars";
    _repository.Save( p1 );

    Producer p2 = (Producer)_repository.Load( p1.Id ); 

    Assert.IsNotNull( p2 );
    Assert.AreEqual( p1.Id, p2.Id );
}

/// <summary>
/// Tests to make sure a null argument exception is thrown
/// for a null producer
/// </summary>
[Test]
[ExpectedException( typeof(ArgumentNullException) )]
public void SaveNullProducer()
{
    Producer p = null;
    _repository.Save( p );
}

You'll notice that I explicitly cast the returned value from the Load() method because the IRepository signatures only return types of RepositoryItemBase. For this test, I really don't have to do that because I'm not checking any specific Producer values, but I did anyway. I could also investigate using the "as" operator or wait until C# 2.0 and use generics. Another option would be to perform an Encapsulate Downcast refactor. So many options!

For this post I just wanted get my first implementation of the design done. I'll look at adding overloads to the Load and Save methods to deal with collections, and deal with the problems of multiple aggregate roots. Furthermore I will want to add some instrumentation to the code.

with 1 Comments

Interesting Topics on Domain Repositories

I've been following some interesting posts about Domain Driven Design. Steve Maine's has expanded on his initial posts about creating a Repository. His latest post uses the idea of an Associate class sparked by Steve Eichert's post to allow for the saving of root aggregates from within one another. He's implementing is approach in VS2005 using Generics and Partial Classes. This latest flurry of posts got me thinking about my current architecture for the Virtual Cellar.

As you may recall, my initial design allowed me to write some code like this

ProducerGateway pg = VirtualCellarManager.GetProducerGateway();
Producer p = new Producer( "Hightower Cellars" );
pg.Add( p );
// Lookup the producer by the ID
Producer p2 = pg.FindByID( p.ID );
WineGateway wg = VirtualCellarManager.GetWineGateway();
Wine w = new Wine( 2001, "Cabernet Sauvignon" );
//Add the wine for the producer
wg.Add( p2, w );
// or I could do something like this
p2.Wines.Add( w );

After looking at the posts, I thought to me self, self what would it look like under this new model

RepositoryFactor rf = new RepositoryFactory();
IRepository r = rf.GetRepository( typeof(Producer) );
Producer p = Producer.Factory.Create( "Hightower", rf );
r.Save(p);
// Lookup the producer by the ID
Producer p2 = r.Load( p.ID );
Wine w = Wine.Factory.Create( 2001, "Cabernet Sauvignon", rf );
p2.Wines.Add( w );

This isn't much different codewise, but it will give me some power as later on I can begin to ask for repositories based on the object's type rather than "hardcoding" the type. For example

Producer p = Producer.Factory.Create( "Columbia Winery" );

IRepository r = rf.GetRepository( p.GetType() ); 

So, I've begun creating NUnit Tests for my RepositoryFactory class. Here's what I've come up with

/// <summary>
/// Tests to make sure a ProducerRepository is returned
/// </summary>
[Test]
public void GetRepositoryForProducer()
{
	IRepository r = _rf.GetRepository( typeof(Producer) );
	Assert.AreEqual( typeof( Lorengo.VirtualCellar.Business.ProducerRepository), r.GetType() );
}

/// <summary>
/// Test to make sure an exception is thrown when a null type is passed
/// </summary>
[Test]
[ExpectedException( typeof(ArgumentNullException) )]
public void GetRepositoryForNull()
{
	IRepository r = _rf.GetRepository( null );
}

/// <summary>
/// Tests to make sure an exception is thrown when a invalid type is passed
/// </summary>
[Test]
[ExpectedException( typeof(ArgumentOutOfRangeException) )]
public void GetRepositoryForInvalidType()
{
	IRepository r = _rf.GetRepository( typeof(RepositoryFactory) );
}

So, I have a question, is the ArgumentOutOfRangeException, the correct exception to throw in this case? Or is there another Exception that better matches the fact that no Repository exists for the System.Type being passed in?

 

with 0 Comments

Domain Modeling with The Virtual Cellar and Repositories

I did some initial modeling on the business domain for my Virtual Cellar application. I was mainly focusing on two major classes. Producers of Wines (Wineries) and Wines. Here's my initial set of requirements that I need to model.

For the Producer
  1. A Producer has a Name
  2. A Producer has Contact Information consisting of an Address (including City, StateOrProvince, PostalCode), Telephone Number, Fax Number, Email Address and Website
  3. A Producer must produce anywhere from 1 to many distinct wines over the Producer's existence
  4. A Producer can produce anywhere from 0 to many distinct wines per year
  5. A Producer can produce Wine made from 1 or More Varieties of Grape
For the Wine
  1. A Wine has a Name
  2. A Wine has a Vintage
  3. A Wine can have only 1 Region
  4. A Wine may have a Description
  5. A Wine is made from one or more grape Varieties
  6. A Wine may be designated as a Reserve, Estate Bottled, Estate Grown etc...

By looking at these initial sets of attributes, I can think of  some other possible classes that I need.

Region
  1. A Region has a name
  2. A Region can contain one or more other Regions
  3. A Region may have a particular classification (DOC, DOCG, DO, DAO etc)
  4. A Region may have a Description
Varietal
  1. A Varietal has a name
  2. A Varietal may have a description

Based on the above initial set of rules, I've come up with the following class diagram.

I'm unsure about a couple things on this picture, (I also got lazy and neglected to make the private references available via public properties, just assume that they are there for now).

  1. Should I break out the Address information into a separate class? Some Producers may have multiple locations, such as a Tasting Room, or other Corporate Locations. I don't think I'll do that for now, version 1 will only support a primary location.
  2. I don't have any methods defined for these classes. I haven't described some of the operations that I'll want to do with these classes, but at a minimum I'll want to

    Do CRUD operations on Wines available for a Producer
    Do CRUD operations on Producers
    Do CRUD operations on Regions and Varietals

How do I go about doing this? Well, I laid out my applications architecture in this post, So I see having an overall Manager class that provides TableDataGateway objects which perform CRUD operations using coarse grained (mainly classes in the business domain) interfaces. However, I've been reading a couple of interesting blog entries discussing different implementations of the Repository pattern.

Steve Maine presented a VS2005 Solution demonstrating his implementation. I took that and created a class diagram and sequence diagram so as to better illustrate his proposal. Please read his most excellent post before continuing.

His solution uses the generics enhancement in C# 2.0. This helps clean up the coding around the RepositoryFactory which is responsible for getting a Class Factory of the appropriate type. I have no problem with this.

The other interesting thing that he does is use Nested Classes to allow the Repository Access to private Customer Key field. This means that you essentially tie all these classes together in one class which can be a huge unwieldy mess. To get around having on big .cs file he uses C# 2.0 Partial classes. Instead of using Nested Clasess and C# 2.0 features, I think a better solution would be to use the internal modifier to make the field accessible to classes in the same assembly.

After looking further at the code I did a quick Sequence Diagram, please let me know if you find any errors (Right Click & Open in a New Window)...

There is only one thing that bothers me about this, and it may just be an oversight (of course I could have misread it as well). It appears that a new <Customer>Repository is getting created each time the GetRepository<>() method is being called. Here's the code from his post...

public IRepository<T> GetRepository<T>()
{
	IRepository<T> repository = null;

	if( typeof( T ) == typeof( Customer ) )
	{
		repository = (IRepository<T>) new Customer.CustomerRepository( this );
	}
	else if( typeof( T ) == typeof( Address ) )
	{
	repository = (IRepository<T>) new Address.AddressRespository( this );
	}

	return repository;
}

A better solution may be to cache the newly created instance in the RespositoryFactory class so that it can be reused, rather than creating new ones.

I like Jimmy Nilsson's approach as well. This corresponds more to the TableDataGateway pattern I've been thinking about but adds a more cohesive (to me) way of thinking about it. Most likely I'll use a synthesis of multiple models for my implementation.

More on that later.

Update: Added link for Jimmy Nilsson's post

with 0 Comments