Wednesday, August 17, 2005

Simplifiing NUnitForms: functional testing Windows.Forms applications

Recently, me and my team have just finished the development of a web application. There we could enjoy an extraordinary tool, called selenium (http://selenium.thoughtworks.com). Now that I come back to desktop applications, my quest is for a tool to enable TDD in the same simple and powerfull manner.

NUnitForms

In the past, our desktop applications had many benefits from using NUnitForms, an open source Windows.Forms functional testing framework. The way it works is very simple, in order to be able to simulate an action on a Windows.Forms control on a Form, NUnitForms comes with a series of wrapper classes to help.

Each standard control in System.Windows.Forms has a Tester, so for Label we have a corresponding LabelTester, for Button, ButtonTester, for TextBox, TextBoxTester and so on. Each of these testers (wrappers) make it easy for us to perform certain actions or interact with the controls, for instance we can Click a button, or type a value in a TextBox.

So if you have a very simple for like this:



where you have , two TextBox-es, a Label and a Button named: txtA, txtB, lblResult and btnCompute.

Now in order to write a simple sum test, for this form, using NUnitForms, we need to extend NUnitFormsTest and for each control we want to interact with on our form, we need to create a tester that helps us interact with that control:


public class SumFormTest:NUnitFormTest
{
private SumForm form;
private LabelTester lblResultTester;
private TextBoxTester txtATester;
private TextBoxTester txtBTester;
private ButtonTester btnComputeTester;

public override void Setup()
{
//show form
form = new SumForm();
form.Show();

//initialise testers
txtATester = new TextBoxTester("txtA");
txtBTester = new TextBoxTester("txtB");
lblResultTester = new LabelTester("lblResult");
btnComputeTester = new ButtonTester("btnCompute");
}

public override void TearDown()
{
form.Close();
}


[Test]
public void CheckOneFour()
{
txtATester.Enter("1");
txtBTester.Enter("3");

btnComputeTester.Click();
Assert.AreEqual(lblResultTester.Text,"4");
}
}



As you can see testing with NUnitForms is fairly simple.

Is this simple enough?

Now going back to web applications, there are two functional testing frameworks, that are possible the best known, for ASP.NET: selenium and NUnitAsp (http://nunitasp.sf.net ). The main difference between the two is that selenium is fit like, where you write tests as simple html tables and NUnitAsp is very similar to NUnitForms, having testers and being a strongly typed VB.NET or C# program. Between our developers and other, where I have shown both of them people tend to be more happy with Selenium. Why? The most obvious reason is that tests with selenium are much smaller, taking less time to write and thus, more maintainable. Another reason, is that with Selenium you can really see it performing the test. With NUnitAsp, you do have the advantage of speed, and you can write your own testers, but speed is very good also with Selenium.

So my idea was: Could we simplify NUnitForms? Could we make it even more appealing by being able to write less code?

With this idea in my head and with the list of selenium commands ( http://selenium.thoughtworks.com/seleniumReference.html ) I thought that my test above could be refactored as:


[TestFixture]
public class SumFormFitTest
{
private SumForm form;

[SetUp]
public void Before()
{
//show form
form = new SumForm();
form.Show();
}

[TearDown]
public void After()
{
form.Close();
}

[Test]
public void Test7()
{
NUnitFormsFit.Type(form,"txtA","3");
NUnitFormsFit.Type(form,"txtB","4");

NUnitFormsFit.Click(form,"btnCompute");
NUnitFormsFit.VerifyText(form,"lblResult","7");
}

}

Is there any reason, I should know about the testers? Couldn't I just add what I want to be done, with the form, the name of the control and maybe some arguments? Well it seems that it is possible. I just added two classes, one with some static methods that I call commands (NUnitFormsFit) like Type, Click, VerifyText, Select and a TesterFactory that can instantiate the Tester I need knowing the form it is on and it's name:


public class NUnitFormsFit
{



public static void Type(Form form, string controlName,string text)
{
TextBoxTester tester = (TextBoxTester) ControlTesterFactory.GetControlTester(controlName,form);
tester.Enter(text);
}
public static void Click(Form form, string controlName)
{
ControlTester tester = ControlTesterFactory.GetControlTester(controlName,form);
tester.Click();
}

public static void VerifyText(Form form,string controlName,string text)
{
ControlTester tester = ControlTesterFactory.GetControlTester(controlName,form);
Assert.AreEqual(text, tester.Text);
}


...


}

and:


public class ControlTesterFactory
{
public static ControlTester GetControlTester(string name, Form form)
{
ControlFinder finder = new ControlFinder(name,form);
Control control = finder.Find();

string typeName = "NUnit.Extensions.Forms."+control.GetType().Name+"Tester";

Assembly asm = Assembly.GetAssembly(typeof(ControlFinder));
Type t = asm.GetType(typeName);
ControlTester tester = (ControlTester) Activator.CreateInstance(t,new object[]{name,form});
return tester;
}
}


Only the first step ...

Some tweeks can be done like caching the testers once they have been instantiated, handling more controls with the same name , handling modal forms (which are all supported by NUnitForms, by the way) and integrating with NFit. Now how hard will it be to extend ActionFixture to enable us to simplify us to have a test like:


open || SumForm()
type || txtA || 3
type || txtB || 4
click || btnCompute
verifyText || lblResult || 7


Conclusion

Well, the code is quite simple and the extensions don't seem to be very hard to do either and I belive this can be a good step in the right direction of simplifiing NUnitForms and functional testing on Windows.Forms applications. Or maybe we will be helped by SharpRobo ( http://confluence.public.thoughtworks.org/display/SHRO/Home;jsessionid=6C4D450855CCFDC30EE0D4305D5603CE ) ?

Sunday, August 07, 2005

Building better business software: the scientific methods point of view

The problem

In order to be able to build better software for our customers, we need to be able to discover are their needs and how our software could address those needs. This means applying a scientific method which involves the natural steps of: observation hypothesis and experimentation.

The first thing we need to do is observe what the client or potential client does and from that extract some hypothesis and deductions about what he is doing and see where the shortcomings might be, what his needs are. Then based on those needs analyze them and select those that can be addressed by software. Based now on this experiment by building the software, deploying it and starting with the scientific method's steps again, by observing how the software is used and whether it is useful for the client to achieve his own goal, whether the software helps the client. Again based on these observations, modify and improve the software to help the customer.

Where does software help business processes?

Let's make a short experiment and go back to the roots with software in businesses, to see when and how software can help a client's company business processes. At first most companies did everything on paper, and some of them were very efficient at doing this. A very good study about the big transition from paper based processes to software based business processes has been done by nobody else but Bill Gates in his book: Business @ the speed of thought, the book being his observation and deductions of large companies and corporations especially. The experiment and its results can be seen on NASDAQ or by looking at out computer screen, Microsoft on top everywhere.

Going to the back to withdraw (not ATM) money you see the employee there writing all your details on a withdraw form, then printing it off and maybe asking you to sign it. For performance reasons, I noticed that the amount of time spent to write all those details on a piece of paper or on the computer are about the same, so where's the benefit of using software if using it and not using it in this activity is almost the same. The benefit is in reporting. The benefit is that when you have an audit asking you what you did with the money, or you your boss is asking you how are the same for that particular item, in July this year compared to July last year, using software is infinitely faster, as this report can be given back to you in seconds instead of having days and weeks of looking trough the
piles of paper. Not to mention human error.

Information extraction more important then informatrion gathering?

After this small observation, my hypothesis is that software is beneficial in business processes mostly for getting data out, then for putting it in.

In order to be able to be organized in a business, you need to have information available to you: fast and reliable. In order to improve your business processes you need , as a customer of software to be able to observer, draw conclusions and deduct facts based on these observations and experiment in improving the business processes. So, the most critical part of the business software is the part that gives information for the people that can draw conclusions from it and be able to improve their business. So that's where the software should really point at.

I recently emphasized this in a blog entry Do we, programmers, build sellable software? in the part that says: sell to managers. These are the decision makers, so help them apply scientific methods on their businesses with your software. Help them improve their own business by giving them the relevant information they need fast.

Unfortunately a lot of software is being built and "incredibly" for me, sold, although this theory of mine is not applied. Usually the developers make the program, where the client can add data easily, and from usability point of view the reports are left behind. Now the reports are the ones that decision makers can use for their observations, and these should be standing out for them. They shouldn't have to click seven times until a report is shown. Information should be accessible very easy, because that's what they need.

Experimenting on this hypothesis

Some of the programs lately have started with the dashboard or home page concept. When the user opens the application, the most relevant information for him is being displayed with no clicks for him. An example is Microsoft Outlook, where the home page shows you your appointments and not a form where you can add a new appointment. Many websites also have this concept, so when you login as a user you're presented with a home page where relevant info is summarized and displayed for you. However I think this view is still in it's beginning, although steps are being taken in the right direction.


The idea for adding the scientific point of view to the way we can improve business
software, making it more usable and more sellable, came to me after reading in Kent Beck's book: Extreme Programming Explained: Second Edition, the chapter entitled: Taylorism and software. Kent Beck says that the first man that applied scientific methods to industrial production was Frederick Taylor. He was the first that applied the 3 steps in industrial production, calling his methods: scientific management: observation, hypothesis, experimentation. After reading this chapter, I realized that people that want to improve their business processes apply the same steps, and that our software should be adapted to this need. I reached this conclusion by applying myself the 3 scientific steps, observing how management and decision makers need to use software, drawing the conclusions that info out is more important then info-in, and experimenting in the latest programs I designed, where getting information out has a much higher priority.

Final words ...

Applying the scientific method steps, I realized that in some areas our software must help our customer apply these methods for his business and goals. I strongly believe that software must be build with a goal in our minds, and probably my conclusions about building software that helps decision makers in applying scientific methods are mostly appropiate for products being build and then sold by a software company, but maybe the domain is even larger ... this hypotesis can only be confirmed by experimentayion, isn't it? :)