2009-02-10

Ultimate integration testing

I am just creating some classes that allow the user of an app to specify date/time validity. As I am modeling them it reminded me of some recurring event classes I once wrote to schedule payments between bank accounts.

One day my customer phoned me up. "Has your invoice been paid this month?" he asked.
"Yes" I said.
"Ah good, your code works then!"

2009-02-09

Onion architecture

Jeff seems to have put it very well in his blog. Much better than I did myself back in December 2006 when I blogged about my "Onion" idea.

My mistakes were
01: I was missing a domain services layer.
02: I tried to explain it using a specific example (wizard app with a "process stack" aka "task stack"), and later decided I didn't like the example :-)
03: When I drew my diagrams I showed them as a typical stacked diagram, because my graphics skills are crap :-)

Here's my badly put idea of onion layered applications:
http://mrpmorris.blogspot.com/2006/12/net-onion-part-1.html

Here's Jeffrey's
http://jeffreypalermo.com/blog/the-onion-architecture-part-1/

Well done Jeff, very nicely put!

Rhino Mocks, returning a different result every time

[TestMethod]
public void Meh()
{
var mockFileSystem = MockRepository.GenerateMock<IFileSystemService>();
mockFileSystem.Stub(fs => fs.CreateFileStream(null, FileMode.Append, FileAccess.Write, FileShare.None))
.IgnoreArguments()
.Return(new MemoryStream());

var result1 = mockFileSystem.CreateFileStream(null, FileMode.Append, FileAccess.Write, FileShare.None);
var result2 = mockFileSystem.CreateFileStream(null, FileMode.Append, FileAccess.Write, FileShare.None);
Assert.AreNotSame(result1, result2);
}


This test case shows a problem I was having. The return value of the stubbed CreateFileStream method isn't calculated each time it is called, it is calculated once at the point you defined the stub method and then returned for every subsequent call. The problem with this is that my real test needed to call CreateFileStream twice and get two different streams, the test was failing because the method being tested disposes of the stream it uses; this was resulting in an ObjectDisposedException in my test.

The correct way to implement this is to override the return value using WhenExecuted()

[TestMethod]
public void Meh()
{
var mockFileSystem = MockRepository.GenerateMock<IFileSystemService>();
mockFileSystem.Stub(fs => fs.CreateFileStream(null, FileMode.Append, FileAccess.Write, FileShare.None))
.IgnoreArguments()
.Return(null)

//*****The return value is replaced in the next line!
.WhenCalled(invocation => invocation.ReturnValue = new MemoryStream());

var result1 = mockFileSystem.CreateFileStream(null, FileMode.Append, FileAccess.Write, FileShare.None);
var result2 = mockFileSystem.CreateFileStream(null, FileMode.Append, FileAccess.Write, FileShare.None);
Assert.AreNotSame(result1, result2);
}

2009-02-08

Why are all my Visual Studio unit test results "Not executed"

When I run my unit tests in my project I am seeing a result "Not executed" for every one. I have restarted my computer so I doubt this is some kind of hung process issue.

Google has revealed nothing that is not related to load balancing, and I am not load balancing!

Solved

In order to determine the error you have to do this

  1. Open the Visual Studio command prompt
  2. Change to the directory where the binary output of your test project is.
  3. Type mstest /testcontainer:The.Name.Of.Your.Test.Assembly.dll

At the bottom of the output you will see the following text

Run has the following issue(s):

In my case it was the following:

Failed to queue test run 'Peter Morris@PETERMORRIS-PC 2009-02-09 10:00:37': Test Run deployment issue: The location of the file or directory 'C:\SomePath\SomeProject.Tests\bin\Debug\Rhino.Mocks.dll' is not trusted.

Now if VS had told me this in the IDE I could have fixed it in minutes! All you have to do is open Windows Explorer and find that DLL. Right-click on it and go to Properties. Then click the "Unblock" button.

If the IDE had told me the reason then it would have taken me 5 minutes to fix (as it did once I knew what it was)

2009-02-06

Silent errors

I'm working on an app which uses a 3rd party library for producing SWF and FLV files. For some reason the trial worked perfectly but when I switched my app to the full version there was no audio output.

We'd been looking at this problem for a while, emailing support etc, but just couldn't see what was wrong. It wasn't until I went back to my proof of concept app and ran it that we realised the full version did produce audio, it was just my main app that wouldn't work properly. Then I spotted the error...

var compressor = new TVE4();
compressor.LoadSettings(SettingsPath);
compressor.SetOutputFile(outputFileName);
compressor.EncodeSequenceAudio(Composition.EffectiveProductionAudioFileName);
compressor.Key1 = 12345;
compressor.Key2 = 54321;
(loop to encode frames)


Do you see the error? It was only as I switched between the proof of concept code and my app code in the IDE that I noticed the two following lines moving up and down...

compressor.Key1 = 12345;
compressor.Key2 = 54321;
Once I spotted it the problem was obvious! If I don't set my license key before encoding anything (including audio) it is not going to work. Moving the key up a couple of lines fixed the problem. It was a simple absent minded mistake to have made, but why did it take over a day to solve?

There were so many factors involved. We aren't using the "full edition" of the tool we are using a feature restricted version so we thought it might be that for a while. Then we thought it might be our settings files. Then their support department kept talking about missing codecs (which made no sense to be honest.) Then there was the fact that in the app it runs in a thread. All sorts of variables that seemed much more likely than a simple 2 line coding error.

The thing is, the EncodeSequenceAudio method returns a bool to indicate success or failure. I hadn't even spotted this. I am so accustomed to experiencing exceptions that I didn't even think to expect a boolean return type. In addition to this the examples that ship with the product don't check for a result either.

2009-01-28

Perceived speed

I'm writing an app which basically performs the following steps in a wizard-like interface:
  1. Select an audio file of someone speaking + loads a text script in.
  2. Process the audio file and the script, can take about 5 seconds for a minute of audio.
  3. Select a character to use in the animation.
  4. Select some additional graphics and scene settings.
  5. Use the data generated in step #2.
Sitting there for 5 seconds wasn't really a problem, not to process a 1 minute audio file. A longer audio file would take a little longer, but 10-15 seconds is okay, isn't it? Well, what if I could make it take no time at all?

Obviously I can't, but I can make it look like it takes no time at all. The fact is that I don't need the processed data until Step 5. The user will probably spend at least 30 seconds twiddling settings in each Step 3 and 4. How much processing power does a bit of GUI interaction take? Hardly any at all!

So I made Step 2 run in a separate thread. As soon as the user clicks "Next" on step 1 they instantly see Step 3. They spend some time there and move onto Step 4. By this point the processing is probably already complete, if however it isn't I simply disable Step #4's "Next" button with a flashing label at the top of the form "* Processing Lip Sync". A 0.5 second timer keeps checking for the completed flag to be set, when it is the label disappears and the button enables.

Unless the user is rushing through the steps they are unlikely to get held up at all. The processing takes just as long as before (maybe a tad longer), but from the user's perspective it takes no time at all.

2009-01-27

Data Transfer Objects

My observations on data transfer objects

  1. They should not be a one to one representation of your domain classes.
    Sometimes you want a subset of the information of a single instance, sometimes your DTO will collect data from various instances (starting with an aggregate root). You might create different types of DTO from the same domain classes based on what the user needs to do. Sometimes the user only wants OrderNumber + DateRaised + TotalValue (to show as a list of orders), sometimes they want the entire order details (including lines) for editing.

  2. The domain classes should have no knowledge of your DTO classes.
    So you shouldn't have any methods such as

    pubic PersonDto CreateDto();
    public UpdateFromDto(personDto);

    DTO's are not part of the business domain, so you should never do this!

  3. The DTO you send out might not be the same type as you get back.
    For example you don't want the user to edit the order number or the date raised. If there are only a couple of properties like this you might opt to use the same DTO class but just ignore those properties when updating the domain instances, or you might decide on Request/Response DTOs

  4. The DTOs should have no knowledge of the domain classes.
    This is because the DTO classes will be shared between the client and the server, and the client will have no domain class knowledge. If you have domain classes on the client then you probably don't need DTOs.

  5. There is only one way to update domain instances from a specific DTO.
    A DTO doesn't always update domain classes, but when you receive a specific kind of DTO and need it to update domain instances it will always update in the same fasion.
So, how do you create DTOs from domain instances and how do you update domain instances from DTOs? The first thing to be aware of is that this code belongs in a layer above the domain layer, in a services layer or the app layer itself. Then we need some way of saying

  "I want to convert this Order to an OrderSummaryDto"

or

  "I want to convert this Order to an OrderDto, which includes its order lines"

and then finally

  "I have received a DTO, I need to update the relevant domain instances"

We need to do this in a reusable way, because the same DTOs may be reused in various parts of the application layer. To achieve this I used the Dependency Injection Container from Microsoft named "Unity".

Naming conventions I used are
  • xxxDtoFactory - Creates a DTO of a specific type from a specific domain instance.
  • xxxDtoTranslater - Takes a DTO of a specific type and translates its values back into the domain instances (updating existing instances, creating new instances, or whatever is required.)
The example model has a class named "Template" which has only a "string Name" property. It is an aggregate root so it owns multiple TemplateProperty instances. TemplateProperty is an abstract class with two concrete descendants; TemplateStringProperty and TemplateBooleanProperty.

When I create a DTO I want a TemplateDto and added to its Properties I want TemplateStringPropertyDto and TemplateBooleanPropertyDto. When I translate TemplateDto I want to update the existing object.

To register a factory
container.RegisterType<IDtoFactory<Template, TemplateDto>, TemplateDtoFactory>(
    new ContainerControlledLifetimeManager()
    );


The structure is IDtoFactory<TDomainClass, TDataTransferObject> to identify the domain class and desired DTO class, followed by the type that implements the interface to perform this DTO creation. This code registers a factory that takes a Template domain class and creates a TemplateDto data transfer object.

To register a translater
container.RegisterType<IDtoTranslater<TemplateDto>, TemplateDtoTranslater>(
    new ContainerControlledLifetimeManager()
    );


The structure is more simple. A DTO can only be translated in one way, so the generic IDtoTranslater interface only requires a single type, TDataTransferObject. This code registers a translater that takes a data transfer object and maps it to the domain.

Once registered the services are used like so:
//Create a template
Template template1 = new Template();

//Create a DTO from the template
TemplateDto template1Dto = container.Resolve<IDtoFactory<Template, TemplateDto>>().CreateDto(template1);

//Update the template from the DTO
container.Resolve<IDtoTranslater<TemplateDto>>().UpdateBusinessObjects(null, null, template1Dto);


Note that the "container.Resolve" code wouldn't really be there, you would use dependency injection. I have used it in this example to avoid turning it into a dependency-injection-container blog :-)

The "null, null" here are
  • The object space that the app layer has created and is using for your domain instances to work inside. Also known as your unit of work, transaction, or other.
  • An addition context. For example when updating a Template the TemplateDtoTranslater will resolve services to translate each PropertyDto it encounters, and pass the Template as the context so that we know which aggregate root we are working with.
For now I will link to the full source code for the example. If I get time I will blog some more explaining how the code works.