Tuesday, 11 November 2008

The Future of Unit testing

I’ve recently watched the PDC 2008 panel Session on the future of unit testing. The feeling I took from this session is that Automated testing is here to stay.

What gave me the indication that this is true is the fact that although the panel tried to focus on unit level testing, the audience tended to shift the discussion into other zones.Most of the audience questions were dealing with more complex scenarios, going beyond the unit level, that they encounter in real life.

For me this gives a good indication that automated unit testing has taken its hold. I’m not sure if my interpretation is not Mistaken, but it seems to me that the available tooling solutions for writing unit tests has matured enough (yes even if you don’t like using mock frameworks) to the point where people are now trying to  leverage them into other testing areas.

As the panel mostly agreed, there is still a shortage of good tools for doing integration/User acceptance testing, and if one listened closely enough it looks like at least some progress is being made on those areas.

Another fact, that most of the of the panel agreed upon, is that unit testing is not enough, at then end there’s still a gap between the user requirements level and the unit level that must be bridged by other sort of testing (integration tests/UAT).

If you want to get some more info on the session but don’t have the time to watch it fully try reading this post by Eli or this one by Andrew

Sunday, 9 November 2008

How to know which unit test calls a specific method

From time to time one faces the situation that one of the unit tests written fails inconsistently. The usual scenario is that when run alone the test passes, but when run as part of the entre suite the test blows up.

In a lot of cases this results from some left over from previous tests. Here is an example of such a case (taken from Typemock-Isolator support forums - AAA tests pass individually, fail in suite). The reported error in this case indicates that for a mock setup in a given test was accessed in some other test which kind of confused the given test.

Solving such an issue usually involves a lengthy Search&Destroy in which most of the work involves finding out which of the test is the one which is interfering with the given test.

So here’s some code that should save most of the leg work. I’m using one of the more powerful features of the Isolator framework – Custom Decorator, which allows adding interception points before and after a given method call.

Here’s the code:

public class TraceTestAttribute : DecoratorAttribute
{
//I'm using a dictionary of lists to store for
//each method all the tests in which the code
//was called
static IDictionary<MethodBase,List<String>> _TestNames
= new Dictionary<MethodBase, List<string>>();

public static string GetData()
{
StringBuilder output = new StringBuilder();
foreach(KeyValuePair<MethodBase,List<string>> entry in _TestNames)
{
output.Append(entry.Key.Name + ": ");
foreach (string testName in entry.Value)
{
output.Append(testName + " ");
}
output.Append(Environment.NewLine);
}
return output.ToString();
}

//this is where all the works get done
public override object Execute()
{
List<string> data;
if (!_TestNames.TryGetValue(OriginalMethod,out data) )
{
data = new List<string>();
_TestNames[OriginalMethod] = data;
}
data.Add(GetTestName());
return null;
}

//going over the stack to locate the test name
//we use reflection to find the method decorated
//with some sort of [Test*]
private string GetTestName()
{
StackTrace trace = new StackTrace();
foreach (StackFrame frame in trace.GetFrames())
{
foreach(object attribute in frame.GetMethod().GetCustomAttributes(false))
{
if (attribute.GetType().Name.StartsWith("Test"))
{
return frame.GetMethod().Name;
}
}
}
return "not from test";
}

//this instructs the framework to apply
//the attibute ALL methods (and not just tests)
protected override bool DecorateMethodWhenAttributeIsClass(MethodBase methodBase)
{
return true;
}
}
As you can see this is quite trivial, when applied to a given method at time the method get calls the attribute Execute method is invoked before the call. In that call I’m going over the stack searching for the test method in which we are running and storing it in a big dictionary keyed by the method we are tracking.

At the end this gives me the ability to stop the execution at each point and easily see the table of all the tests that during their execution a specific method was called (directly or indirectly).

(For good measure I’ve added a GetData method which build a string of the entire dictionary)

I hope you find this one useful, leave a comment if you do or if you have related question.

A warning: currently the isolator contains a defect that will cause an exception to be thrown when the method with this attribute is mocked. I’m sure that this problem will be fixed very shortly by the Isolator team.

Thursday, 6 November 2008

The Fifth Value – Respect

There’s a lot to be said about respect but for some reason this value is not stressed enough. I think that much of what troubling the software development world today can be traced back to this value. Lets face it most developers are arrogant bastards(and yes I’m a developer too).

Taken from Kent book:

Every person whose life is touched by software development has equal value as a human being. No one is intrinsically worth more than anyone else. For software development to simultaneously improve in humanity and productivity, the contributions of each person on the team need to be respected. I am important and so are you.

lets take a few examples I’ve encountered (ok, ok I’ve said those):

  • “our customers does not know what they want. Ill tell you what they want”
  • “our test team don’t have a clue on what they are doing and how to test the system”
  • “I don’t trust our system deployment team to properly configure the system in at the customer site”

and the list goes on.

The problem is that this kind of attitude, even if its backed up with real hard facts, leads to a basic lack of respect, and this will effect the project outcome.

I try to treat everyone the same (with partial success I admit), when facing incompetency, I first try to see if this can be fixed (in many cases what looks like incompetency is a result of a simple lack of knowledge) and if it cant, I will look for a replacement. Most project I’ve worked on don’t have the luxury with the less capable.

Wednesday, 5 November 2008

The Funny side of Metrics

From time to time I do stumble upon some great post. The following post (yes its an old one):

Is it Wise To Aim for 100% NTF?

did not only made me laugh it really made me think.

Lesson learnt – Using humor to mask Wisdom is really effective.

Monday, 3 November 2008

The power of combining Unit tests with Integration Tests (conclusion)

Here and Here I explained why I think that unit tests alone or integration tests alone does not do a good enough job at assuring the quality of the product. However, that combining the two test  levels, i.e. investing some of the effort in integration tests and in unit tests is what I call a winning solution.

Investing effort on both levels allow one to benefit from both worlds

on one side integration test will help in:

  • formulizing the user requirements.
  • make sure that system is working end to end.
  • test non functional requirements

on the other side unit tests will help in:

  • driving the design of the system to a better one.
  • give a good coverage of all parts of the system
  • eliminating defects that get shipped with the system.

I have been suing this approach in a TDD style in which the development process of a new feature(user story) started out by writing a few (failing) integration tests then followed by writing some more (failing) unit tests and only then starting to implement. this kind of process has worked for us.

The million dollar question is of course “how much do invest at each level?”, and the real answer is I don’t know. I think that it really depends on the specifics of the project and the system under test. In some cases it makes more sense to invest more time on the unit level while in other its better to spend more effort on the integration level. I really think that the best guide to that will be to use common sense and see how things works out.

 
Design by Free WordPress Themes | Bloggerized by Lasantha - Premium Blogger Themes | Walgreens Printable Coupons