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 ) ?

1 comment:

trinity31marquis said...

='Brand New News From The Timber Industry!!'=

========Latest Profile==========
Energy & Asset Technology, Inc. (EGTY)
Current Price $0.15
================================

Recognize this undiscovered gem which is poised to jump!!

Please read the following Announcement in its Entierty and
Consider the Possibilities
Watch this One to Trade!

Because, EGTY has secured the global rights to market
genetically enhanced fast growing, hard-wood trees!

EGTY trading volume is beginning to surge with landslide Announcement.
The value of this Stock appears poised for growth! This one will not
remain on the ground floor for long.

Keep Reading!!!!

===============
"BREAKING NEWS"
===============

-Energy and Asset Technology, Inc. (EGTY) owns a global license to market
the genetically enhanced Global Cedar growth trees, with plans to
REVOLUTIONIZE the forest-timber industry.

These newly enhanced Global Cedar trees require only 9-12 years of growth before they can
be harvested for lumber, whereas worldwide growth time for lumber is 30-50 years.

Other than growing at an astonishing rate, the Global Cedar has a number of other benefits.
Its natural elements make it resistant to termites, and the lack of oils and sap found in the wood
make it resistant to forest fire, ensuring higher returns on investments.

the wood is very lightweight and strong, lighter than Poplar and over twice
as strong as Balsa, which makes it great for construction. It also has
the unique ability to regrow itself from the stump, minimizing the land and
time to replant and develop new root systems.

Based on current resources and agreements, EGTY projects revenues of $140 Million
with an approximate profit margin of 40% for each 9-year cycle. With anticipated
growth, EGTY is expected to challenge Deltic Timber Corp. during its initial 9-year cycle.

Deltic Timber Corp. currently trades at over $38.00 a share with about $153 Million in revenues.
As the reputation and demand for the Global Cedar tree continues to grow around the world
EGTY believes additional multi-million dollar agreements will be forthcoming. The Global Cedar nursery has produced
about 100,000 infant plants and is developing a production growth target of 250,000 infant plants per month.

Energy and Asset Technology is currently in negotiations with land and business owners in New Zealand,
Greece and Malaysia regarding the purchase of their popular and profitable fast growing infant tree plants.
Inquiries from the governments of Brazil and Ecuador are also being evaluated.

Conclusion:

The examples above show the Awesome, Earning Potential of little
known Companies That Explode onto Investor�s Radar Screens.
This stock will not be a Secret for long. Then You May Feel the Desire to Act Right
Now! And Please Watch This One Trade!!


GO EGTY!


All statements made are our express opinion only and should be treated as such.
We may own, take position and sell any securities mentioned at any time. Any statements that express or involve discussions with respect
to predictions, goals, expectations, beliefs, plans, projections, objectives, assumptions or future events or performance are
not statements of historical fact and may be "forward, looking
statements." forward, looking statements are based on expectations, estimates
and projections at the time the statements are made that involve a number of risks and uncertainties which could cause actual results
or events to differ materially from those presently anticipated. This newsletter was paid $3,000 from third party (IR Marketing).
Forward,|ooking statements in this action may be identified through the use of words such as: "projects", "foresee", "expects". in compliance with Se'ction 17. {b), we disclose the holding of EGTY shares prior to the publication of this report. Be aware of an inherent conflict of interest resulting from such holdings due to our intent to profit from the liquidation of these shares. Shares may be sold at any time, even after positive statements have been made regarding the above company. Since we own shares, there is an inherent conflict of interest in our statements and opinions. Readers of this publication are cautioned not to place undue reliance on forward,looking statements, which are based on certain assumptions and expectations involving various risks and uncertainties that could cause results to
differ materially from those set forth in the forward- looking statements. This is not solicitation to buy or sell stocks, this text is
or informational purpose only and you should seek professional advice from registered financial advisor before you do anything related with buying or selling stocks, penny stocks are very high risk and you can lose your entire investment.