Click here to Skip to main content
11,702,396 members (73,428 online)
Click here to Skip to main content

Article Two: Building a UI Platform in C# - Testing via UI Animation

, , 3 Mar 2005 44.1K 817 33
Rate this:
Please Sign up or sign in to vote.
Describes an implementation of UI animation for the support of Test-Driven Development.

Article Selector

Exotic Database technology?

Most databases do something rather wonderful: they log stuff. Now, this doesn’t seem like a big deal until you consider the fact that the log consists of the commands used to define and modify the database. Further consider that the log can be played back to recreate the entire database and you’ve got something well beyond a big deal: it is pure genius. Little bits of genius like this exist throughout software. Often disguised as technology applicable to only a single problem, these bits wait patiently for someone to reevaluate them in a way that recognizes the greatness of the concepts behind them.

Let’s do some of that reevaluation now: What if an application worked just like a database? That is, everything the user did was logged and the log was defined such that playing it back caused the application to return to the same state it had reached during the initial user session? Such a capability could be used as a safety net for the user, providing a backup in case a document was lost or corrupted. It could be useful for tech support: with the log providing a detailed recounting of all users actions. It could be useful for training: where animated walk-throughs show the user how to do something. It could be useful in the development of the application itself: where each log functions as a test.

UI animation: The Player

We are particularly interested in this last variant: testing. Mindful of the many potential uses for this technology, we will code a simple, abstract infrastructure which could support any of them. Here is our first crack at it:

  • ControlSystem – heart of the Platform, routes Windows.Form events to handling objects.
  • Player – Runs a set of instructions, animating the UI.
  • StopWatch – adapter for System.Threading.Timer.
  • Instruction – Represents an individual action a user can take (MouseMove, LeftButttonDown, etc.).

We want the UI to look like a user is actually manipulating it: the cursor should move, buttons should go down and up, controls should change position during a drag. To create these effects, the Player must have access to all of the methods which drive the ControlSystem. The Player must also handle timing. Though we certainly want to run a set of instructions quickly when verifying multiple tests, we also want to run tests at normal speed to make sure they are executing correctly. StopWatch, which adapts a System.Threading.Timer, can give us control over this part of the solution. And finally Instruction, which emulates user actions, will give us the ability to manipulate parts of the UI programmatically. Let’s code a test and see how these might be defined:

ControlSystem.Player.Add(new MouseMoveInstruction(10, 10));

ControlSystem.Player.Add(new LeftMouseDownInstruction(10, 10));

ControlSystem.Player.Add(new MouseMoveInstruction(100, 100));

ControlSystem.Player.Add(new LeftMouseUpInstruction(100, 100));

By default the Player will execute each instruction every half second. We can change that by passing an additional argument (Speed) in the constructor. This code is valid and represents one kind of test. We can also get more “meta” if you like, passing the control to be dragged and the target DropSite in alternate constructors of these same instructions:

ControlSystem.Player.Add(new MouseMoveInstruction(dragSourceControl));

ControlSystem.Player.Add(new LeftMouseDownInstruction(dragSourceControl));

ControlSystem.Player.Add(new MouseMoveInstruction(dragTargetControl));

ControlSystem.Player.Add(new LeftMouseUpInstruction(dragTargetControl));

Assuming we have such capabilities, we could run the exact same tests introduced in the previous article via the Player. These tests will run more slowly, due to the delay, but they would also test the mouse handling system (the very same system which will process the mouse events of the Windows Form.) The net result is that these tests exercise more code, more realistically than direct calls on the classes themselves.

The development experience

After coding the initial implementation and watching the first test run, we noticed that it was difficult to determine when the test was complete. The cursor would sit over some control, leaving us to wonder: Is there one more instruction to go, or is this test done? To resolve this problem, we enhanced the Monitor to include an instruction log. An entry is added to the log each time an instruction starts and updated when the instruction completes. The new Monitor:

Using the Player

The drag cases from the previous article are coded as direct calls on infrastructure objects. For example:

protected override void Test()
{
    ControlSystem.Mouse.Move(50, 50);
    
    ControlSystem.Mouse.LeftButtonDown(50, 50);

    ControlSystem.Mouse.Move(350, 350);

    ControlSystem.Mouse.LeftButtonUp(350, 350);
}

These need to be changed to UI animation tests, by converting the code to this:

protected override void Test()
{
    ControlSystem.Player.Add(new MouseMoveInstruction(50, 50));
    
    ControlSystem.Player.Add(new LeftMouseDownInstruction(50, 50));
    
    ControlSystem.Player.Add(new MouseMoveInstruction(350, 350));
    
    ControlSystem.Player.Add(new LeftMouseUpInstruction(350, 350));

    ControlSystem.Player.Play();
}

With the conversion complete, we run the tests and verify:

Once again we move forward under full green. We now have enough infrastructure in place to start coding controls - that will be the topic of the next article.

Thanks!

To all of you who are sticking with us in this article series, we say thank you! How are you holding up? We are at about 14,000 lines of source (both tests and code) at this point. The UI Platform proper sits at about 5,500 lines across 118 types). That’s a lot to keep up with; yes, we know. Obviously we can’t discuss every single line of code, but rest assured: all of the fundamental concepts have been covered. If it seems like the train is leaving the station without you, please feel free to provide feedback or send us an e-mail – we’d be glad to discuss anything that is on your mind.

Downloads

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

Share

About the Authors

Tom Ollar
CEO Sagerion, LLC
United States United States
I read About Face by Alan Cooper in 1995 and immediately recognized it as a founding document for the future of software. I also recognized we had a long, long way to go - and yes, even with the advent of iOS, we are still not there yet.

At my company, Sagerion (say-jair-ee-on), we can take a look at your planned or existing software and suggest ways of making it better - lots better. We can develop down-to-the-pixel blueprints showing exactly what our suggestions mean. We can help manage on-going development to make sure the top-notch user-experience we've suggested really does get built. Now, honestly, how often have you ever seen all those things happen?

You may or may not already have great development going on - but what does that matter if you don't have great design driving it?

Feel free to contact me at tom@sagerion.com, I would love to hear about your next ground-breaking project.

Jim Bennett
Founder Sagerion LLC
United States United States
www.filoshare.com
-It is a fresh and free distributed source control system.

You may also be interested in...

Comments and Discussions

 
GeneralQuestion regarding the Control System.. Pin
varun2cool200023-Mar-05 19:22
membervarun2cool200023-Mar-05 19:22 
GeneralRe: Question regarding the Control System.. Pin
Jim Bennett24-Mar-05 6:48
memberJim Bennett24-Mar-05 6:48 
Hi Varun,

Thank you and we're glad you enjoyed the article!

Excellent questions you have! First, you say that you have a C# application that you want to test, this is with WinForms I presume. Our control system does not use native windows controls and therfore our instructions are not designed to manipulate WinForms UserControl descendents. Our goal is universal- we need to test our application's UI. So, to do this without limitations or having to jump hurdles with UserControls, we are building our own control infrastructure and frameworks to test a new library of our own controls.

We have not built a recorder at this time, but we will in the future. A short answer to creating recording is to wait until we have created one in a future article. The longer answer begins with: It shouldn't be terribly difficult and may actually be quite easy to get a first version of a recorder working, but the article series is not quite mature to the point in which we want to jump straight into implementing UI recordings.

A recorder is a very interesting idea and so a discussion of one possible implementation follows: In order to build a simple recorder for our control system, you will need to create all of the recorder infrastructure, of course. This would include adding a recorder on the control system as an embedded object and the UI in the form's toolbar to start and stop recording (there are no toolbar or button classes defined in the article source yet, so that is one limitation- we will show how to build a button in a future article). The recorder should be called directly inside of the control system inside the form's mouse event handlers so that it can interpret what instructions to create. You'll also have to code a factory class to create the instructions based on the type of mouse event that is coming from the form, and add the instructions to a collection. The collection is the recording and you can replay those instructions at a later time by adding the individual instructions on the ControlSystem.Player and calling Player.Play(). That is pretty high level. Also, keep in mind that the constructor for each instruction would need to have a time interval set so that they can be replayed with the exact same time taken as done during the recording. The instruction implementation already supports this delay interval, although you will have to overload some instructions which do not have this alternate constructor at this time. In summary, the control system is designed to support recordings and we will create a recorder in the future as the source continues to mature in the article series, but for now if you want to create a recorder, you would need a more complete implementation of the controls for this control system.

Given that there are no buttons in the source base yet to create a recorder, this article series is not yet complete enough to build a real application (only Container and Label have been presented at this time- and EditBox is right around the corner). Even so, the concepts presented are real and can be used to build a control system to build a C# windows application. If you want to explore a more complete version of a control system and its API, we've actually built a complete commercial product (the commercial version 1.0 does not have a recorder) that has a well built object oriented set of controls using a similar control system approach that we are presenting in the article series www.blix.net.

As the article series moves forward, you'll want to download the Testing Framework from the latest articles, as we are continually moving the source base forward- including the Testing Framework. Use the menu at the top of each article to navigate to our latest article- http://www.codeproject.com/useritems/ArticleFour.asp[^]





Jim Bennett

GeneralDownload links... Pin
Martin Dionne24-Feb-05 9:29
memberMartin Dionne24-Feb-05 9:29 
GeneralRe: Download links... Pin
Tom Ollar24-Feb-05 13:20
memberTom Ollar24-Feb-05 13:20 
GeneralRe: Download links... Pin
Martin Dionne25-Feb-05 9:02
memberMartin Dionne25-Feb-05 9:02 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web03 | 2.8.150819.1 | Last Updated 3 Mar 2005
Article Copyright 2005 by Tom Ollar, Jim Bennett
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid