Testing framework is not just for writing… tests

Quick ques­tion – from the top of your head, with­out run­ning the code, what is the result of:

var foo = -00.053200000m;
var result = foo.ToString("##.##");

Or a dif­fer­ent one:

var foo = "foo";
var bar = "bar";
var foobar = "foo" + "bar";
var concaternated = new StringBuilder(foo).Append(bar).ToString(); 

var result1 = AreEqual(foobar, concaternated);
var result2 = Equals(foobar, concaternated);

public static bool AreEqual(object one, object two)
{
    return one == two;
}

How about this one from NHibernate?

var parent = session.Get<Parent>(1); 

DoSomething(parent.Child.Id); 

var result = NHibernateUtil.IsInitialized(parent.Child);

The point being?

Well, if you can answer all of the above with­out run­ning the code, we’re hir­ing. I don’t, and I sus­pect most peo­ple don’t either. That’s fine. Ques­tion is – what are you going to do about it? What do you do when some 3rd party library, or part of stan­dard library exhibits unex­pected behav­iour? How do you go about learn­ing if what you think should hap­pen, is really what does happen?

Scratch­pad

I’ve seen peo­ple open up Visual Stu­dio, cre­ate ConsoleApplication38, write some code using the API in ques­tion includ­ing plenty of Console.WriteLine along the way (curse who­ever decided Client Pro­file should be the default for Con­sole appli­ca­tions, switch to full .NET pro­file) com­pile, run and dis­card the code. And then repeat the process with ConsoleApplication39 next time.

 

The solu­tion I’m using feels a bit more light­weight, and has worked for me well over the years. It is very sim­ple – I lever­age my exist­ing test frame­work and test run­ner. I cre­ate an empty test fix­ture called Scratchpad.

scratchpad

scratchpad_fixture

This class gets com­mit­ted to the VCS repos­i­tory. That way every mem­ber of the team gets their own scratch­pad to play with and val­i­date their the­o­ries, ideas and assump­tions. How­ever, as the name implies, this all is a one-off throw­away code. After all, you don’t really need to test the BCL. One would hope Microsoft already did a good job at that.

If you’re using git, you can eas­ily tell it not to track changes to the file, by run­ning the fol­low­ing com­mand (after you com­mit the file):

git update-index –assume-unchanged Scratchpad.cs

scratchpad_git

With this sim­ple set up you will have quick place to val­i­date your assump­tions (and answer ques­tions about API behav­iour) with lit­tle friction.

scratchpad_test

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

Tags: , ,

  • http://twitter.com/pecei Pablo Ruiz

    Lin­q­Pad rocks as scrach­pad.. ;)

  • Miguel Madero

    I like the –assume-unchanged switch. That's the main rea­son I didn't like the scratch­pad idea when I saw it in our codebase.

    That said, I still think that there's some value in com­mit­ing 'some' of those assump­tions. For those cases we could move them from 'scratch­pad' and to a more per­sisted area. Maybe an assump­tions folder. Some peo­ple is against test­ing libraries oth­ers than your own, but I see some value on doing that. But I also see value in split­ting them from your tests. Assump­tions can serve as doc­u­men­ta­tion and  to test for regres­sions (e.g. NHiber­nate break­ing our pre­vi­ous assump­tions on every release). We could even make assump­tions about exist­ing bugs on our depen­den­cies and iden­tify when the bug is fixed on a new release.

    For quick and tran­sient assump­tions I like using Mono's REPL or the REPL Add-in for VS. I'll give Lin­q­Pad a go.

  • Anony­mous

    I can answer with­out compilling

    1. -.05

    2. false in both cases, baceuse object.Equals and equal­ity oper­a­tor on objects uses ref­er­ence equal­ity: first string is interned, while sec­ond is not. So they are two dif­fer­ent objects.

    3. false, in case when Id is actual iden­ti­fier of Child.

  • http://rollersmb.myopenid.com/ RollerSMB

    I have to admit to hav­ing many point­less con­sole apps :)

    Hav­ing said that, I don't have THAT many, as a lot of the sim­ple stuff can be tested using the imme­di­ate win­dow directly, eg, had to illus­trate to some­one how the order of logic oper­a­tors worked, and could just declare the bools and run the expres­sions directly in imme­di­ate window.

    (ps, I could answer all of those too!  hon­est.. :P )