Monthly Archives: November 2009

Simplified Testing

I’ve been struggling with the collision of worlds from the waterfall approach to testing and the agile approach to testing.  There really isn’t a good solid statement being made about what “end to end” and “system testing” look like in agile. It’s time we simplified testing.

In concordance with keeping things simple, let’s break it down starting with the end goal: to produce shippable code at the end of an iteration.

This comes from the agile principle of:

Deliver working software frequently, from a

couple of weeks to a couple of months, with a

preference to the shorter timescale.

In order to deliver working software, that software must be usable or complete at that point.  Almost every agile process involves completing a user story before moving on to the next (at least all the user stories in an iteration.)

Shippable software is software that has been completely tested.   Getting to that point in one iteration is not something that is attainable if you hold onto the fallacy of “system testing.”  What is “system” or “end to end testing,” anyway?  I have never seen a true system level defect that did not exist also at a functional level.  What value are you getting by testing the whole system when you only changed a small part of the functionality?  And when you find defects at this high level of testing you end up having to triage them down to a root cause.

So what if we cut that out?  What if instead we said all desired functionality in the system is represented by automated tests which are produced in conjunction with the code?

What if we did 2 very simple things:

  1. For each user story we write automated tests that define what we expect from the system; when those pass the story is done. Check out Kent Beck’s book, Test-Driven Development.
  2. Each time we finish a story we run all the previous automated tests to ensure nothing is broken. A good general book on testing is Testing Computer Software.

If we do those 2 things and we make sure the user of the system (or person representing the user) has agreed that the automated tests adequately cover what they want the story to accomplish, is there a need to do anything else?  Or is it perhaps that this very complex methodology of testing really is just that simple?

Importunate Permutations

Here is an interesting programming problem: Calculate all the permutations of a string.

For example, the permutations of “abc” are:

abc

acb

bac

bca

cab

cba

It is not as easy of a problem as it seems, but it has a rather simple solution.

Many times recursion is actually more complex to understand than a non-recursive solution, but in this case recursion is an elegant and simple solution.

A good way to solve these kinds of problems is to start with N, N+1, N+2, then solve for N+x.

Let’s start with N; we will define a function permutation which will give us the permutations of any string.

permutation(“a”) =

“a”

permutation(“ab”) =

“a” + permutation(“b”)

“b” + permutation(“a”)

permutation(“abc”) =

“a” + permutation(“bc”)

“b” + permutation(“ac”)

“c” + permutation(“ab”)

permutation(x)

foreach character c in x

c + permutation(x remove c)

Looking at it in C# code, it would look something like:

public static List<string> Permutations(string s)
{
      if (s.Length == 1)
      {
            return new List<string> { s };
      }

      List<string> permutations = new List<string>();

      foreach (char c in s)
      {
            string leftOver = s.Replace(c.ToString, "");
            List<string> stringsReturned = Permutations(leftOver);
            foreach (string permutation in stringsReturned)
            {
                 permutations.Add(c + permutation);
            }
       }
       return permutations;

}

Update: Here is a pretty slick example in LINQ that I got from a stackoverflow.com question.

public static IEnumerable<string> GetPermutations(string s)
{
    if (s.Count() > 1)
        return from ch in s
               from permutation in GetPermutations(s.Remove(s.IndexOf(ch), 1))
               select string.Format("{0}{1}", ch, permutation);

    else
        return new string[] { s };
}

For a better understanding of permutations, check out this short booklet on How to Understand Permutations and Computations .

Making the Complex Simple

I thought it rather appropriate to make my first blog post be about making the complex simple, since that is the central theme of the blog.

What do I mean by making the complex simple?

In my mind this is the single most important quality of a software developer.  The ability to take something that is complicated and too large to fit inside a skull and make it simple and understandable.  This concept is applicable at many different levels of abstraction, just as the practice is.

For example:  When we are writing code, what we are doing is taking a complex world and dissolving it to a simpler abstraction of rules which govern how it works.  The world is often “fuzzy” and requires judgement and intuition.  As developers we take that “fuzzy” world and make generalizations about it and make it concrete for our problem domain.

Taking it a step further, simply writing software or code is simplifying the complex world into black and white, but even that is complex.  I can write a bunch of assembler code or even machine language and I may have technically made the complex world simple, but I may have actually made it more complex to the next programmer who reads my code.  As a good developer, I would strive to make the expression of those rules of the system to be simple itself so that another developer or myself could easily understand this complex concept.  This is what I mean when I say elegant code.

Being able to write code that is easy to understand or “fit in your head” is such a quintessential part to development that without that skill even the most genius developer is bound for failure.  I would equate this with the difference between writing intelligent code versus wise code.

Simple vs complex is such an important concept that it transcends programming and really touches many areas of our lives.  Think about your car.  How simple is it to use such a complicated piece of machinery?  There is a large amount going on which we don’t know or care about when we drive a car, but someone came up with a simple interface which makes this really complex thing very simple.  Consider Apple’s success.  I have had a smart phone since HP first came out with the IPac phone, but did I ever really use any of the features on the phone?  Apple came along and took this complex interface for most of the competing phones and didn’t make it stupider, they just made it simpler.  In fact, they gave it more capabilities but made the user interface so simple to use.

If you are interested in finding out more about this mindset, I would recommend checking out Eric Evan’s book, Domain-Driven Design: Tackling Complexity in the Heart of Software .