October 2004 - Posts
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
- Add NUnit support via CruiseControl.Net and the
NUnit Task
- 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?
- Read the error message more closely
- 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
- Use the -verbose+ switch on NAnt sooner rather than later
- 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.
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.
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?
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
- A Producer has a Name
- A Producer has Contact Information consisting of an Address (including
City, StateOrProvince, PostalCode), Telephone Number, Fax Number, Email
Address and Website
- A Producer must produce anywhere from 1 to many distinct wines over the
Producer's existence
- A Producer can produce anywhere from 0 to many distinct wines per year
- A Producer can produce Wine made from 1 or More Varieties of Grape
For the Wine
- A Wine has a Name
- A Wine has a Vintage
- A Wine can have only 1 Region
- A Wine may have a Description
- A Wine is made from one or more grape Varieties
- 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
- A Region has a name
- A Region can contain one or more other Regions
- A Region may have a particular classification (DOC, DOCG, DO, DAO etc)
- A Region may have a Description
Varietal
- A Varietal has a name
- 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).
- 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.
- 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