Home
News
Documentation
License
Download
Contributors

Source Code

NUnit
NMock
SourceForge

SourceForge.net Logo

Breaking Changes

I've removed a few methods and properties from the base NUnitForm test that were marked obsolete for some time. Your test should no longer override and specify just the type of form under test. Instead you should instantiate your form and invoke the Show() method, either in the test or the override Setup() method of your test class.

The test framework will still clean up as usual.

The code is in better shape now, making more use of generics so fewer Control Testers are necessary to get the benefit of typed access to the underlying controls.

Now built with NUnit 2.4.1 in Subversion. Please let me know if you need any help or have issues. A file release should be coming soon.

.NET 2.0 Alpha 5 / Subversion

Some developers volunteered to bring NUnitForms current with support for .NET 2.0 controls and this initial work has been released under the name .NET 2.0 Alpha 5. Also, the project recently switched from CVS to SVN for source control management. Now I have found a little bit of time and I plan to take a look at where things are and bring some aspects of the project up-to-date including some of this site.

Version 1.3 Released

Version 1.3 includes support for tests running on a hidden desktop, improved documentation, better unit test examples, keyboard controller, Assert (instead of Assertion) support, better databinding support, and an Invoke method for invoking arbitrary methods on a control.

Hidden Desktop

Tests are now run on a separate hidden desktop. This makes them much faster and it works for any tests that are not using the keyboard or mouse controllers. (Those tests require using a desktop enabled for user input.) It is nice to have them on a separate desktop because they are less disruptive and input tests can not interfere with your other applications.

If you want to disable this feature (some have reported problems that I have not tracked down yet) you can set an environment variable called "UseHiddenDesktop" equal to "false" Another option is to override the "UseHidden" property in each of your test fixtures to return false.

There is another property in the base test class called "DisplayHidden" that should be set to return true for tests using the keyboard or mouse controllers. The hidden desktop must be displayed in order to accept input.

To summarize again: There are two properties you can override. They are UseHidden and DisplayHidden. DisplayHidden is only used if UseHidden is true. The default is to use a hidden desktop but not display it. You have to display it if you are using the keyboard or mouse controllers. You can disable the UseHidden if it causes problems on your machine. (Please email me with your configuration if you have problems.. I am looking for a pattern. I expect it is related to the OS or your user rights. Possibly it is related to your version of the .net framework.)

Keyboard Controller

There is a new KeyboardController that lets you send keyboard input to your form under test. The syntax is similar to that for the MouseController.

[Test]
public void TextBox()
{
  new TextBoxTestForm().Show();
  TextBoxTester box = new TextBoxTester( "myTextBox" );
  Assert.AreEqual( "default", box.Text );

  Keyboard.UseOn( box );

  Keyboard.Click( Key.A );
  Keyboard.Click( Key.B );
  Keyboard.Press( Key.SHIFT );
  Keyboard.Click( Key.C );
  Keyboard.Release( Key.SHIFT );

  Assert.AreEqual( "abC", box.Text );
}

Better API Documentation

Click here for MSDN style API docs

Base Test Class No Longer Extends Assertion!

If you want your tests to have built-in Assertion functionality, you should extend the NUnitFormsAssertionTest class.

If you want Assert syntax, extend NUnitFormsAssertTest.

If you don't need either one, extend NUnitFormTest as before.

The next version of NUnit has deprecated the Assertion class and the Assert class has no public or protected constructor so it cannot be extended. This is the best compromise I could come up with and still support both old and new versions of NUnit cleanly. I understand some of you will have to slightly change your test code to extend the new class and there will be some temporary confusion. I tried to minimize the problem as much as I could while still moving the project forward.

MTA version of NUnit-Console

I compiled a special version of nunit-console that removes the STAThread attribute from its main method. This allows the hidden desktop feature to work. In the current CVS version of NUnit (to be released as a beta in the next couple of days) there will be a /thread option to pass into nunit-console that will make this unnecessary.

(Because of this, the console and gui versions of NUnit will be the same and things will be cleaner in the next release..)

Thank you to the NUnit team and specifically to Charlie Poole for making this happen!

Version 1.2 Released

Version 1.2 includes support for modal forms, modal message boxes, dynamic controls with duplicate names, list boxes, and mouse interactions.

Solution / Project files

I simplified the organization of the project quite a lot, removing the separate solution for the example application and consolidating the assemblies. Things should be more logical now. The Nant script is simpler and it should be easier to find where everything is.

Mouse Controller

There is now a mouse controller checked into CVS for people that need an easy way to simulate mouse movement. This will be useful to people who need to test a specific control and how it responds to the mouse (by firing events, etc..)

Here is a test that demonstrates mouse usage.

[Test]
public void MouseClickingSimplifiedAPI()
{
  new ButtonTestForm().Show();
 
  Mouse.UseOn( "myButton" ); //mouse position relative to myButton
  Mouse.Click( 1, 3 );       //default unit is pixels
  Mouse.Click( 1, 3 );

  AssertEquals(new ControlTester( "myLabel" )["Text"], "2" );
}

The mouse support is extensive and supports positioning relative to any control or form. It can be measured in pixels, inches, etc.. You can click, double click, drag, hold down key modifiers, etc.

(The example above also shows accessing a property by name rather than through the convenience method.)

If you are not testing the mouse handling specifically (and why would you, for built in controls like button?) then you should still use the standard nunitforms technique of calling button.Click() or FireEvent("MouseEnter") Also in this case you should actually use a LabelTester and the "Text" property as well... This example is meant to illustrate the API, not to model a well written test..

Tests that use this new mouse support actually grab hold of your mouse making it more difficult to work on computer while it is running your tests. I have sometimes seen a test randomly fail if you are actively working while the tests run. Use the mouse controller only when you really need it. When you do, it is really nice.

See the MouseControllerTest.cs and SimpleAPIMouseTest.cs tests for more complete examples.

Thanks to Richard Schneider for the code making this possible!

Dynamic Controls Without Unique Names

I added the ability to find controls even when they do not have a unique name.

This happens when you add controls dynamically and don't implement a way to keep the names unique.

In the original tests for dynamically added controls, the form kept a counter and named each new control accordingly (like button1, button2, etc..)

But now you don't have to do this.

You can write a test like this.

[Test]
public void DynamicControlsWithDuplicateNameWorksByIndex()
{
  ButtonTester addButton = new ButtonTester("btnAddDuplicate");
  ButtonTester duplicate = new ButtonTester( "duplicate" );

  addButton.Click(); //add a button named "duplicate"
  addButton.Click(); //add another button named "duplicate"

  duplicate[0].Click(); //click the 1st non-uniquely named button
  duplicate[1].Click(); //click the 2nd non-uniquely named button
}

The indexers ([0], and [1]) specify to find the 1st and 2nd controls with that name (duplicate) and click them. You can avoid the AmbiguousNameException this way.

Next steps on this feature: a way to access the count of controls with a particular name and possibly an enumerator so that you can use foreach() on it.

Message Boxes

Modal dialogs displayed with MessageBox.Show() are now supported! (Code in CVS includes unit tests that can serve as examples) Here is a snippet:

[Test]
public void TestMessageBoxOK()
{
  ExpectModal( "caption", "MessageBoxOkHandler" );
  MessageBox.Show( "test string", "caption" );
}

public void MessageBoxOkHandler()
{
  MessageBoxTester messageBox = new MessageBoxTester( "caption" );
  AssertEquals( "test string", messageBox.Text );
  AssertEquals( "caption", messageBox.Title );
  messageBox.ClickOk();
}

Still to do: implement the rest of the built in modal dialogs (file open / file save.. etc)

Modal Forms Modal forms (user written and displayed with ShowDialog() are now supported! (Code in CVS includes unit tests that can serve as examples) Here is a snippet:

[Test]
public void TestModalFormByString()
{
  new ModalMultiForm().Show();
  ExpectModal( "Form-0", "ModalFormHandler" );
  ButtonTester buttonOne = new ButtonTester( "myButton", "Form" );
  buttonOne.Click();
}

public void ModalFormHandler()
{
  ButtonTester btnClose = new ButtonTester( "btnClose", "Form-0" );
  btnClose.Click();
}

Notice how this works.. You say ExpectModal, pass the name of the modal form to expect, and specify a method to run when it is displayed.

The test will fail if your supplied method fails or if the expected modal form is never display.

Still to come, recorder support.

Version 1.1 Released

Version 1.1 includes support for testing multiple forms interaction and an improved recorder. The API has been simplified as shown in earlier news stories below. (Modal forms are not yet supported directly, although the mock / stub approaches are still possible. Look for more documentation / advice on testing Modal forms soon if I can't find a quick solution.

NUnitForms always needs more work on documentation.

I created a new page here for documentation. It is a pretty rough draft but I think it covers the features of NUnitForms pretty well. Please send feedback if you find it useful or lacking.

Maintaining good documentation is high on my priority list. Of course I would not mind help if you are using this and can send something.

Please also look at the (very simple) Example Application provided with the source code. The unit tests there should also give a good idea of how you can use this project. The core library should be simple and easy to figure out with some time in the code. Because control support is still limited, you will likely need to spend some time in the code anyway!

Thanks for your patience and feedback.

New Simplified API in CVS

You no longer need to specify the form or the name of the form when using the Testers. The base unit test class handles clean up of any forms created during each test. Here is a complete test example that uses the new API features. Everything will be cleaned up by the teardown in the base test class.

Example:

[TestFixture]
public class ButtonTest : NUnitFormTest
{
  [Test]
  public void ButtonClick()
  {
    new ExampleForm().Show();

    ButtonTester button = new ButtonTester("button");
    LabelTester label = new LabelTester("label");

    Assertion.AssertEquals("0", label.Text);
    button.Click(); //this button click increments the label.

    Assertion.AssertEquals("1", label.Text);
  }
}

New Multiple Form Support in CVS

As far as new features, I am adding support for multiple forms in one test. Forms can be referenced by name just like controls. This is checked into CVS now. I would like feedback.

Example from the included unit tests.


//the teardown method of the base class closes all the open windows!!
//You don't have to keep track of anything.

[TestFixture]
public class MultipleFormsTest : NUnitFormTest
{
  [Test]
  public void TestMultipleForms()
  {
    //a "multiform" has one button that opens another "multiform"
    MultiForm form = new MultiForm();
    form.Show();

    //"Form" here references the "Name" property of an open form.
    //NUnitForms should find this form if it is open and displayed
    //These testers can be created any time, even before the form
    //they relate to is active. They will only be "looked up" when
    //you perform some action (click) on them.


    ButtonTester button1 = new ButtonTester("myButton", "Form");
    ButtonTester button2 = new ButtonTester("myButton", "Form-0");
    ButtonTester button2 = new ButtonTester("myButton", "Form-0-0");
    ButtonTester button4 = new ButtonTester("myButton", "Form-1");

    button1.Click(); //this button click opens a 2nd form

    button2.Click(); //this button is on the 2nd form
    button3.Click(); //this button is on the 3rd form
    button1.Click(); //this button click opens a 4th form
    button4.Click(); //this button is on the 4th form
  }
}

ASP.NET Unit Testing (IN PROCESS)

I also have a working prototype of using this to test individual ASP.NET pages in process using the same API. Hooks for your unit test are provided to check the state of individual controls (actual control instances) at different 'phases' in the page life cycle.

If you are interested in this feature, let me know and I will prioritize merging that code into the tree.

NFit

I have had an idea to write an NFit test fixture to NUnitForms. NFit tests could take advantage of the NUnitForms library to do functional tests through the GUI The recorder application could be extended to record tests in a table format.

If you are interested in this feature, let me know and I will prioritize it accordingly.

Copyright 2003-2007 Luke T. Maxon. All Rights Reserved.