Archive for the ‘TDD’ Category

Approval testing – value for the money

Monday, January 16th, 2012

I am a believer in the value of test­ing. How­ever not all tests are equal, and actu­ally not all tests pro­vide value at all. Raise your hand if you’ve ever seen (unit) tests that tested every cor­ner case of triv­ial piece of code that’s used once in a blue moon in an obscure part of the sys­tem. Raise your other hand if that test code was not writ­ten by human but generated.

 

As with any type of code, test code is a lia­bil­ity. It takes time to write it, and then it takes even more time to read it and main­tain it. Con­sid­er­ing time is money, rather then blindly unit test­ing every­thing we need to con­stantly ask our­selves how do we get the best value for the money – what’s the best way to spend time writ­ing code, to write the least amount of it, to best cover the widest range of pos­si­ble fail­ures in the most main­tain­able fashion.

Notice we’re opti­mis­ing quite a few vari­ables here. We don’t want to blindly write plenty of code, we don’t want to write sloppy code, and we want the test code to prop­erly ful­fil its role as our safety net, alarm­ing us early when things are about to go belly up.

Test­ing conventions

What many peo­ple seem to find chal­leng­ing to test is con­ven­tions in their code. When all you have is a ham­mer (unit test­ing) it’s hard to hit a nail, that not only isn’t really a nail, but isn’t really explic­itly there to being with. To make mat­ters worse the com­piler is not going to help you really either. How would it know that Login­Con­troller not imple­ment­ing ICon­troller is a prob­lem? How would it know that the new depen­dency you intro­duced onto the con­troller is not reg­is­tered in your IoC con­tainer? How would it know that the pub­lic method on your NHiber­nate entity needs to be virtual?

 

In some cases the tool you’re using will pro­vide some level of val­i­da­tion itself. NHiber­nate knows the meth­ods ought to be vir­tual and will give you quite good excep­tion mes­sage when you set it up. You can ver­ify that quite eas­ily in a sim­ple test. Not every­thing is so black and white how­ever. One of diag­nos­tics pro­vided by Cas­tle Wind­sor is called “Poten­tially mis­con­fig­ured com­po­nents”. Notice the vague­ness of the first word. They might be mis­con­fig­ured, but not nec­es­sar­ily are – it all depends on how you’re using them and the tool itself can­not know that. How do you test that efficiently?

Enter approval testing

One pos­si­ble solu­tion to that, which we’ve been quite suc­cess­fully using on my cur­rent project is approval test­ing. The con­cept is very sim­ple. You write a test that runs pro­duc­ing an out­put. Then the out­put is reviewed by some­one, and assum­ing it’s cor­rect, it’s marked as approved and com­mit­ted to the VCS repos­i­tory. On sub­se­quent runs the out­put is gen­er­ated again, and com­pared against approved ver­sion. If they are dif­fer­ent the test fails, at which point some­one needs to review the change and either mark the new ver­sion as approved (when the change is legit­i­mate) or fix the code, if the change is a bug.

 

If the expla­na­tion above seems dry and abstract let’s go through an exam­ple. Wind­sor 3 intro­duced way to pro­gram­mat­i­cally access its diag­nos­tics. We can there­fore write a test look­ing through the poten­tially mis­con­fig­ured com­po­nents, so that we get noti­fied if some­thing on the list changes. I’ll be using Approval­Tests library for that.

[Test]
pub­lic void Approved_potentially_misconfigured_components()
{
    var con­tainer = new Wind­sor­Con­tainer();
    container.Install(FromAssembly.Containing<HomeController>());

    var han­dlers = GetPotentiallyMisconfiguredComponents(container);
    var mes­sage = new String­Builder();
    var inspec­tor = new DependencyInspector(message);
    fore­ach (IEx­poseDe­pen­den­cy­Info han­dler in han­dlers)
    {
        handler.ObtainDependencyDetails(inspector);
    }
    Approvals.Approve(message.ToString());
}

pri­vate sta­tic IHan­dler[] GetPotentiallyMisconfiguredComponents(WindsorContainer con­tainer)
{
    var host = container.Kernel.GetSubSystem(SubSystemConstants.DiagnosticsKey) as IDi­ag­nos­tic­sHost;
    var diag­nos­tic = host.GetDiagnostic<IPotentiallyMisconfiguredComponentsDiagnostic>();
    var han­dlers = diagnostic.Inspect();
    return han­dlers;
}

What’s impor­tant here is we’re set­ting up the con­tainer, get­ting the mis­con­fig­ured com­po­nents out of it, pro­duce read­able out­put from the list and pass­ing it down to the approval frame­work to do the rest of the job.

Now if you’ve set up the frame­work to pup-up a diff tool when the approval fails you will be greeted with some­thing like this:

approval_diff

You have all the power of your diff tool to inspect the change. In this case we have one new mis­con­fig­ured com­po­nent (Home­Con­troller) which has a new para­me­ter, appro­pri­ately named miss­ing­Pa­ra­me­ter that the con­tainer doesn’t know how to pro­vide to it. Now you either slap your­self in the fore­head and fix the issue, if that really is an issue, or approve that depen­dency, by copy­ing the diff chunk from the left pane to the right, approved pane. By doing the lat­ter you’re noti­fy­ing the test­ing frame­work and your team­mates that you do know what’s going on and you know it’s not an issue the way things are going to work. Cou­pled with a sen­si­ble com­mit mes­sage explain­ing why you chose to approve this dif­fer­ence you get a pretty good trail of excep­tion to the rule and rea­sons behind them.

 

That’s quite an ele­gant approach to a quite hard prob­lem. We’re using it for quite a few things, and it’s been giv­ing us really good value for lit­tle effort it took to write those tests, and main­tain them as we keep devel­op­ing the app, and the approved files change.

 

So there you have it, a new, use­ful tool in your toolbelt.

Unit tests are overrated

Monday, February 28th, 2011

Some­thing is rot­ten in the state of Devel­op­ment. It seems to me we (devel­op­ers) either ignore test­ing alto­gether, leav­ing it to the Q&A team when we throw them the app over the wall, or we con­cen­trate on unit tests only. Let me make one thing clear before we go any fur­ther – unit tests are a fan­tas­tic and extremely valu­able tool in many cases, and I by no means am try­ing to dis­cour­age any­one from writ­ing unit tests. They have their place in the devel­op­ment pipeline (espe­cially if you’re doing TDD).

While I still usu­ally write a fair amount of unit tests I find the per­cent­age of unit tests in the code I write is get­ting smaller. I just find unit tests are not the best value for the buck in many cases where pre­vi­ously I would write unit tests uncon­di­tion­ally, not really giv­ing it any thought.

Where would that be?

Let’s stop and think for a sec­ond – what unit tests are good at. Unit tests exer­cise sin­gle units of func­tion­al­ity, and they’re the most fine grained tests you write. They tests a method pro­duces the right out­put. They test a class responds in expected man­ner to results of invo­ca­tion of another method, poten­tially on another object. And they really shine if those algo­rithms and small scale inter­ac­tions are com­plex and/or part of API that is going to be used exten­sively where they do a really great job at being an exe­cutable documentation.

How­ever, for quite a few sce­nar­ios unit tests just aren’t the best approach and that’s my goal with this blog post – to make you stop and think – should I write a unit test, or per­haps an inte­gra­tion test, with real, not stubbed out dependencies?

To illus­trate the point let me tell you a (real) story. I was called to a client recently to have a look at the issue they were hav­ing in their sys­tem. The sys­tem was com­posed of an admin­is­tra­tion web­site, and a client appli­ca­tion that was com­mu­ni­cat­ing with the server side via a WCF ser­vice. The issue they were hav­ing is that some infor­ma­tion that was entered on the admin­is­tra­tive web­site, wasn’t dis­played prop­erly in the client appli­ca­tion. How­ever all the unit tests were pass­ing, for all three ele­ments of the sys­tem. As I dug into the code­base I noticed that some trans­for­ma­tion was being done to the infor­ma­tion com­ing from the web UI on the web-app end before it was being saved, and them what was sup­posed to be the same process in reverse was hap­pen­ing on the WCF Ser­vice side. Except it wasn’t. The trans­for­ma­tion being done changed, and was updated every­where except for the web­site (this also rein­forces the point I made in my pre­vi­ous blog­post, that changes in appli­ca­tion code should almost always be accom­pa­nied by changes to tests). So the unit tests between two parts of the sys­tem were out of sync, as were their imple­men­ta­tions yet unit tests weren’t able to detect that. Only a grander scale, inte­gra­tion test, that would cover both ends of the spec­trum, the sav­ing of the infor­ma­tion on the web­site site, and read­ing it from the same repos­i­tory on the ser­vice side would have caught this kind of change.

At the end, let me share a secret with you – Wind­sor, has very few unit tests. Most tests there are (and we have close to 1000 of them) exer­cise entire con­tainer with no part stubbed out in sim­u­la­tions of real life sce­nar­ios. And that works excep­tion­ally well for us, and lets us cover broad range of func­tion­al­ity from the per­spec­tive of some­one who is actu­ally using the con­tainer in their real application.

So that’s it – do write tests, and do remem­ber to have more than just a sin­gle ham­mer in your tool belt.

Unit tests – keep it simple (KISS)!

Friday, February 6th, 2009

I have a ten­dency to over­com­pli­cate things some­times. Unit tests, are one such piece of code, that you want to keep as sim­ple and clean as pos­si­ble, so that other devel­op­ers can eas­ily find out how your class-or-method-under-test is sup­posed to work. There’s a prin­ci­ple for that that says it very strongly – “Keep it sim­ple, stupid.”

Don’t make it flex­i­ble when it does not have to be (just … hard code it). For exam­ple, when I was work­ing on IIn­ter­cep­torS­e­lec­tor sup­port for Cas­tle Dynam­icProxy, I had to test prox­ies with­out tar­get, where return value is set by an interceptor.

My first attempt at it was to cre­ate Return­De­fault­OfT­In­ter­cep­tor class that for any given return type, would instan­ti­ate it with para­me­ter­less con­struc­tor. This solu­tion would pro­vide what I needed, but it was unnec­es­sar­ily com­pli­cated and made the test less read­able. I didn’t need a helper class (that’s what the inter­cep­tor was in this test) that would han­dle just any return type of just any method. For the test I was call­ing one method, with one return type, and that’s all I needed from my helper interceptor.

Once I real­ize that I changed the test to some­thing like this:

[Test]
public void SelectorWorksForInterfacesOfInterfaceProxyWithoutTarget()
{
    var options = new ProxyGenerationOptions
    {
        Selector = new TypeInterceptorSelector<ReturnFiveInterceptor>()
    };
    var proxy = generator.CreateInterfaceProxyWithoutTarget(
    typeof(ISimpleInterface),
        new[] { typeof(ISimpleInterfaceWithProperty) }, 
        options,
        new ReturnFiveInterceptor()) 
    as ISimpleInterfaceWithProperty;
    Assert.IsNotNull(proxy);
    var i = proxy.Age;
    Assert.AreEqual(5, i);
} 

The Return­FiveIn­ter­cep­tor class name clearly sais what the class does. Also the asser­tion in the last line is more obvi­ous now.

So, keep your tests sim­ple and read­able, don’t gen­er­al­ize where you don’t really need to, but know your lim­its, because when you cross the line you’re on the frag­ile tests territory.

Tech­no­rati Tags: , ,