Code tag cloud

I thought it would be a bit of fun to pass my code through a tag cloud creator. I thought it might give some insights into the domain language.

I used Boomerang for this experiment.

I merged the projects class files into one on the command line;


    for /r ".\boomerang.host" %f in (*.cs) do type %f >>merged_code.txt

Then when over to TagCrowd.com and created the image below.

Tag cloud image

I didn’t learn much about my project but it was a bit of fun and maybe I’ll do some renaming the next time I’m in the code.

What’s the problem with TDD?

Have you ever worked on a system where the tests slow you down?

Do the tests break even with the smallest change?

Are the tests brittle?

Is it really hard to write a test? Lots of setup, mocks and expectations?

I’ve worked on these and I’m pretty sure I’m not alone.

So what’s the problem with TDD?

Feedback loops

To understand the problem we have to understand feedback loops.

The use of feedback loops is crucial in engineering; the components in a system provide feedback that reinforces or reduces change.

There are two types of feedback loops; positive and negative.

Negative feedback

Negative feedback loops move systems towards stability.

Negative feedback loops act as a damper to, or prohibits, change.

An example of a negative feedback loop in engineering is the centrifugal governor. This limits the speed of the engine by limiting fuel supply.

Positive feedback

Positive feedback loops moves systems towards instability.

Positive feedback loops reinforce change. A change reinforces itself and creates more of the same change.

An oscillator is an example of a positive feedback loop.

Tests as a feedback loop

In much the same way, unit tests are an example of a negative feedback loop.  When one breaks we stop and fix it. It is enforcing stability.

However, tests are also providing feedback when you are writing them. If it’s hard to write a test, your design is likely sub-optimal for the change you are trying to make.

For example, if there are lots of dependencies to mock and expectations to set up, we may have missed a needed abstraction that combines them.

The longer we put up with tests that are getting harder to write, the more our software degrades.

Designing feedback loops

We have to be careful how we design our feedback loops. If our tests are too fine grained our feedback loop will be too tight, limiting the changes we can make to our system. This will reduce our ability to change our software.

We need the feedback to ensure we haven’t broken anything while at the same time we want to be able to change the implementation details of our software.

Conclusion

Our tests are feedback loops, telling us, not only when changes are wrong, but also when our changes cannot easily be supported in the design.

If we ignore our tests it will become harder to work within our system over time.

We need to be careful how fine grained we make our tests; too fine and we won’t be able to change our software. Not fine enough and we will inadvertently break some behaviour of our software.

Testing emails

We’ve recently added email notifications to our application.  I really wanted to avoid configuring email servers or setting up email accounts to test our software. Luckily there are a number of tools to help with this for development, and testing.

Development

We’re using .Net so we can configure our application to send all SMTP to a file directory. This can be done in the application configuration file with the below snippet;

<system.net>
    <mailSettings>
        <smtp deliveryMethod="SpecifiedPickupDirectory">
            <specifiedPickupDirectory pickupDirectoryLocation="c:\temp\mailbox\"/>
        </smtp>
   </mailSettings>
</system.net>

Our acceptance tests relied on this mechanism to redirect SMTP traffic to the file system. We then had an interface in our automation framework to parse these files so we could easily check the contents.

Component Testing

For manual testing we wanted to avoid having to change the application configuration so looked for a simple way of setting up SMTP.

We decided to use an SMTP fake. There are a few open source project for this.  Two examples are SMTP4Dev and PaperCut.

I use SMTP4Dev simply because I’ve used it before but will try papercut when I get some time.

System Testing

This is the only time we needed to have a real SMTP server configured.  For this we have a Dogfood environment that our operations department takes care of. Taking this approach completely removed the need to become experts in configuring email servers to test sending emails.

HttpClient performance

I was able to dramatically improve the performance of HttpClient by removing one line of code. Take the below snippet;

 var httpClientHandler = new HttpClientHandler()
 {
      UseDefaultCredentials = true,
      PreAuthenticate = false,
      ClientCertificateOptions = ClientCertificateOption.Automatic
 };
 var webclient = new HttpClient(httpClientHandler);

The offending line of code is highlighted.

This code averaged 20 seconds per 100 requests. Using the default ClientCertificateOption.Manual this improved to 4 seconds.

I couldn’t understand why this would be, so I cracked open HttpClient with Jetbrains dotpeek to take a closer look.

HttpClient eventually calls it’s base class SendAsync method.  This calls SendAsync on the handler and it is here the importance of this property becomes clear.

The handler calls the private method CreateAndPrepareWebRequest().  This in turn calls the innocent sounding SetDefaultOptions(…) method where the below code lurks;

 X509CertificateCollection clientCertificates = UnsafeNclNativeMethods.NativePKI.FindClientCertificates();
 if (clientCertificates.Count <= 0)
    return;
 webRequest.ClientCertificates = clientCertificates;

It turns out the FindClientCertificates() method enumerates the users certificate store on every request.

I found this amazing and it seems extremely wasteful.

I am still trying to figure out if there is a good reason why the certificate store couldn’t be enumerated once and the certificate list stored for future requests.

But that’s for another day!

Faking third party web services

I’ve worked on a number of projects that relied on third party web services or API’s.  Most of these had a test service but didn’t provide a way to return a predetermined response.

This left two choices when testing our software; call the test service or create a fake service of our own

Third party test services

Usually the purpose of a test service is to ensure that your production systems will work with their production systems.  So it is used for testing the integration of two systems.

This usually means the only difference is the data is not real or is a sub-set of the live data.  Using it still requires calls across service boundaries (HTTP), expensive computation and storage (like databases).

This creates a number of issues when executing an automated test suite for your software;

  • Calls across services boundaries are expensive, resulting in slow tests and slow feedback
  • Tests will be brittle because the data can change, leading to different results over time
  • You may not have access even to the test service in the environment you are running your tests

Faking services

The solution is invariably to create a fake service that can be configured to return a specific response.

I’ve done this a few times and without exception the solution has become a maintenance burden. Some  of the problems I’ve experienced are below;

  • Fake is not re-usable across projects
  • Duplication of fakes across teams
  • Different fakes for different third party services

This leads to a lot of duplication of effort and lost time.

Proxy servers

After realising this could be solved with a proxy server I created Boomerang to make this easier.  This enables developers to set predetermined responses for HTTP requests.

For example, I can specify a json object should be returned from a GET for a specific relative address;

var dictionary = new Dictionary<string, string>() { { "content-type", "application/json" } };
Boomerang.Server(5100).Get("/api/products").Returns(products.SerialiseToJsonString(), 200, dictionary);

This creates a proxy server on port 5100 and specifies the response to a HTTP GET request to the relative uri /api/products should be a list of Products formatted as json.

I created an extension method to help with the json serialisation;

public static string SerialiseToJsonString(this object target)
        {
            string str;

            var dataContractJsonSerializer = new DataContractJsonSerializer(target.GetType());

            using (var mem = new MemoryStream())
            {
                dataContractJsonSerializer.WriteObject(mem, target);
                mem.Flush();
                mem.Position = 0;
                str = Encoding.Default.GetString(mem.ToArray());
                Console.WriteLine(str);
            }

            return str;
        }

Conclusion

GET, POST, PUT and delete are supported and the base address is ignored.  If Boomerang receives a request it hasn’t got a response for it will return an error response.

I hope this makes testing with third party services a bit easier!

Mistake proofing

In previous posts I described how I test serialization of objects.

However, I still forget to do this. So, I’ve written tests to remind me. This is an idea from Lean engineering called poka yoke (see http://en.wikipedia.org/wiki/Poka-yoke).

The concept is simple – make it impossible or hard for someone to make mistakes that go unnoticed.

I use the convention of putting all the classes that need to be serialized in a contracts namespace. This makes it simple to write a test to check all these classes are defined with the DataContract attribute.

        [Test]
        public void All_classes_in_contract_namespace_should_implement_datacontract()
        {
            IList allClassesInContractsNamespace = ReflectionHelper.GetAllTypesWhere(x=>x.Namespace.Contains("Contracts") && x.IsClass).ToList();

            allClassesInContractsNamespace.Count.ShouldBeGreaterThan(0);

            foreach (object obj in allClassesInContractsNamespace)
            {
                var dataContract = obj.GetType().GetCustomAttributes(typeof(DataContractAttribute), false).OfType().FirstOrDefault();
                dataContract.ShouldNotBe(null);
            }
        }

The ReflectionHelper extension method encapsulates how I’m using Autofac to get a list of types. This makes it simpler to re-use in my tests as well as change the method of reflecting over types in the future;

public static IEnumerable GetAllTypesWhere(Func predicate)
        {
            var builder = new ContainerBuilder();
            builder.RegisterAssemblyTypes(typeof(Invoice).Assembly)
                   .Where(predicate.Invoke)
                   .As();

            IContainer container = builder.Build();
            var controllers = container.Resolve<IEnumerable>();

            return controllers;
        }

This technique can be extended to any frequent mistake.

Conclusion

We have a lot of tools to help us not make mistakes; modern development tools help a lot. Third party tools exist such as re-sharper, style-cop, and FxCop. Our build systems run our unit tests and these static analysis tools.

We can take this further by writing tests that check for our most common mistakes.

Reading Xml files

On a recent project we needed to read data from a file. We couldn’t simply de-serialize using the built in .net serialization as the file format had already been defined and we didn’t have the time to write custom serialization. So our problem was that given an xml file format such as the one below, how best to consume it?

<Products>
<Product name="Name1" manufacturer="Manufacturer1"/>
<Product  name="Name2" manufacturer=""Manufacturer2"/>
</Products>

This had been solved in a few places by using an xml parser. I didn’t like this as it seemed fragile.

Auto generate classes

After some thought I realised we could create the classes from the xml using the xml schema definition tool. First create an xml schema from the visual studio command prompt using xsd.exe;

xsd.exe products.xml

Then we create the classes from the schema;

xsd.exe /classes products.xsd

Deserialize files into objects

We now have the classes required to de-serialize the file into .net objects.  The below code and utility class can now handle the de-serialization;

[Test]
public void Should_load_products()
{
     var p = new XmlEntityReader<Products>();
     var productList = p.Read("blog\\productdata.xml");

     productList.Items.Length.ShouldBe(2);
}

public class XmlEntityReader<T> where T : class
{
    public T Read(string storeFullPath)
    {
       return Read(new FileStream(storeFullPath, FileMode.Open));
    }

    public T Read(Stream storeStream)
    {  
        storeStream.Position = 0;
        T settings;
        var serializer = new XmlSerializer(typeof(T));
        using (TextReader tr = new StreamReader(storeStream))
        {
           settings = serializer.Deserialize(tr) as T;
           tr.Close();
        }
        return settings;
    }
}