Pathfinder Blog
Topic Archive: Testing

iPhone SDK: UIViewController Testing & TDD

iPhone in Dock

Unfortunately there are not enough examples out there on how to test view controllers with the iPhone SDK. My hope is to remedy that a bit by sharing some techniques I have been using to tackle the problem, particularly in keeping with the spirit of TDD along the way.

First, If you have not already done so, configure your project to use GTM. This is a bit of a no-brainer as it currently stands. Until Apple comes up with something better, GTM is the way to go. It works as advertised, and is a credit to the folks at Google for providing this toolkit.

Now then, many tutorials on the web seem to imply that one should test somewhere in the middle by suggesting to add a few outlets to your controller, fire up IB and wire up your view to your view controller before you even start to think about testing any of it.

Testing controller logic means working under the assumption that you have wired up your view components correctly to match the controller's actions and outlets. Wire up an element to the wrong action (or worse, forget to wire it up at all) and you can easily learn to rely too heavily on manual testing. While this might be acceptable for small one-off applications, within a team of developers practicing collective code ownership, this kind of error can cost real money over time. "Thanks for caring, but I'd rather have a unit test."

Now then, let's take a look at some code!

Continue reading »

Review of fixture_replacement2 plugin

We have been using fixture_replacement2 on some of our Ruby on Rails projects. I am writing an internal application and finally switched over from using fixtures. It took a bit of time to get the tests that I had written modified to stop using the fixture data, but now I am completely fixture free. The tests are a lot easier to write, and I created a few helper methods that setup common datasets. This way, I can call a setup method to configure my data, and then - it's all good. At first I called the method test_data_blah, and was wondering why I was getting an error running any test, so now it's called data_blah.  Doh!

At first I didn't like the fact that I needed to explicitly create the data for what I was working on, but then I realized that (especially for unit tests)  you don't need much dependent data; usually it's one or two records. For functional tests, I found that the data setup methods rocked, as I could quickly get the data set up that I needed.I could quickly assert the content of the response, based on the data in my setup. I missed fixtures at first, but now realize that over time, they are a pain.

Continue reading »

Managing vs Creating Test Data

This is my first blog post at Pathfinder. I m excited to be a part of the Pathfinder team and look forward to working on a number of different diverse projects. I had a tough time trying to decide what the subject for my first post was going to be.  I finally zeroed in on "Test Data Management vs Creation".

In one of my earlier jobs at a reputed insurance company's IT organization, We came across this problem that posed a big challenge. We were building a real-time policy servicing application. The problem was finding the right test data to test the application. The QA folks were spending so many man-hours trying to find the right test data or set-up test data. "Test Data Management" was becoming a big pain and was hurting the project badly in terms of time and costs. The solution?

"Test Data creation" was proposed a viable solution to this problem. The idea was to build reusable tools that would use the application to generate test data to suit the QA organisation's needs. These tools determined what the tester's test policy needs were, used the application services to generate test policies and provided them to the tester.  It was a great idea! The application that was to be tested was SOA driven which made it easier for this solution to work. I was a part of the team that worked on developing these tools. Some of the tangible benefits that everyone saw with this approach were:

  • Life of QA became much much easier.
  • Imagine the amount of time and money the company was going to save.
  • The application was being tested repeatedly when it was used for creating the test data.
  • Test Automation became easier.

The QA organization's mantra became "Forget about managing and reusing test data, create new test data the way you want it!"

 

 

Agile Development and Testing: Unit or Montecarlo?

I've had a running debate with my colleague John McCaffrey on the question of testing. He is a big fan of unit testing and testing in general that examines the smallest possible units to be tested, then assembles them in every larger integration tests. The idea is that if you get the small stuff right, then the larger stuff has a greater chance of being right too.

Come to think of it, I'm a big fan of this approach too. But there are some times that this sort of strict constructionism is insufficient. There are a few instances that a comprehensive system test is necessary. Some instances that come to mind are:

Continue reading »

Ajax Testing: Doubling Down with Selenium and JMeter

This idea comes from my colleague John McCaffrey, but since he's having a bad case of blogger's block, I get to post about it.

For anyone who has developed tests for web applications with a tool like Selenium (or Watir), you know it is a sysiphean task, rolling the boulder of automated tests up the hill of a constantly changing application. The DOM changes, the text changes, the url's and parameter's change, iframes and onload events don't always play nice with your test recorder. Depending on the framework you are using, id's may change in unpredictable ways, forcing you to hack together brittle xpath expressions. Still, functional testing is important, so you persevere, spending countless hours in making those tests run clean.

Continue reading »

Lesser Known Test Processes

Testtube
While Test-Driven Development (TDD) and Behavior-Driven Development (BDD) get all the headlines, thousands if not millions of developers have worked out their own ad-hoc variations on these processes. This is a list of alternate testing processes, some of which are useful, some of which less so. It's a different way of thinking about the benefits of doing testing -- at the very least, it's a way to think about the costs of backsliding on TDD.

Data Driven Testing (DDT)

Also Known As: Begging The Question, Blank Box Testing

Process Description: Write your tests first as in normal TDD, however instead of actually asserting an expected value, assert against a blank value (as in assert_equal(nil, user.batting_average)). The test, of course, fails. You then fill in the expected value based on the result of the failing test. Bingo! The test passes.

Pitfalls: If you aren't careful, this turns in to Tautology Based Testing. Specifically, you need to verify that the returned value really is what you expect. If you are doing this too often, it may mean you don't really understand what your code is doing.

Actual Uses: There are a couple of benefits to this testing process. First off, it guarantees a failed test the first time around, which is proof that the basic test setup is correct, and that you are testing the item that you think. This is also useful in cases where the correct answer is easier to verify than to generate by hand (a long string, for example). It's preferable to use the literal result of the actual program then a separate non-literal calculation of the answer, even if you paste in the literal result.

Continue reading »

A UXD Lesson from the Gas Station

This past weekend I was up on Howell Mountain in Napa, tasting the ultra tasty wines there and taking in the gorgeous views. On the way back to SF, we stopped at a Shell gas station. It took me a good 20 minutes to gas up. Why? Lousy user experience. Let me explain.

This was a new, fancy pump. It had a TV up top, a 4"x6" LCD screen just below crotch level (I'm 6'4"), a numeric keypad with a credit card reader about a foot to the right, and three fuel selectors another foot above. It was about 11:30, and the sun was shining right at the LCD screen. First I thought the TV was saying something relevant about my fueling my car. The Doppler effect of several other TV's saying the same thing at slight offsets around the gas station was also a little disconcerting. I finally figured out that the TV was just polishing the Shell brand and flogging sitcoms (aren't the writers on strike?).

Continue reading »

GWT Testing With Groovy? (Heck yeah!)

Speaking of GroovyTestCase, I experimented a bit with using both it and JMockit as an alternative to GWTTestCase.  This may sound strange at first-- after all, the point of GWTTestCase is to exercise your code in the way it will eventually execute as JS at runtime.  What I've effectively done is to run my tests from within Groovy against GWT classes compiled-as-Java.  First I will go through an example of what I'm talking about, then I will summarize some of the thoughts I had as a result of going through this exercise.

Below I have an implementation of KeyboardListener which modifies the contents of a TextArea based on keypress.  I want to test the behavior of this listener.  Here's what I did:

1) Write a test.  I did this using Groovy, but you could just as easily write it in Java using JUnitTestCase if you prefer.  This particular test verifies that my listener will append an equal amount of whitespace to the next line when the <enter> key is pressed, and position the cursor at the end of that new line.  Very simple stuff, but worth testing even outside of GWTTestCase.  I find that the Groovy style keeps this test case a lot shorter than it would otherwise be in Java.

class SampleTest extends GroovyTestCase {
    private static final char KEY_ENTER = (char) KeyboardListener.KEY_ENTER
    private static final int NO_MODIFIERS = 0;

    protected void setUp() throws Exception {
        Mockit.redefineMethods(GWT, MockGWT)
    }

    public void testEnterKey() {
        def keyListener = new MyKeyListener()
        def textArea = new TextAreaFixture(text: "    abcd", cursorPos: 8 )

        keyListener.onKeyPress(textArea, KEY_ENTER, NO_MODIFIERS)

        assertEquals "Content is incorrect", "    abcd\r    ", textArea.text
        assertEquals "Cursor position is incorrect", 13, textArea.cursorPos
    }
}

class TextAreaFixture extends TextArea {
    String text;
    int cursorPos;
}

2) Mock out com.google.gwt.core.client.GWT.  This ultimately comes down to mocking out the 'create' method.  Notice below that we make a special case for 'DOMImpl.class'.  The reason for this is that the actual DOMImpl is decided at runtime.  It is also referenced in the constructors of the widget we are testing (i.e. 'TextArea()').  Note that this class needs to be a Java class (i.e. non-Groovy) due to the way in which JMockit redefines methods on existing Java classes.  As for why I return 'null' for everything else, I do this to fail fast in any cases I'm not testing.  As it turns out, this is all I need for the testcase above.

public class MockGWT {
    public static Object create(Class classLiteral) {
        try {
            if (classLiteral.equals(DOMImpl.class)) {
                return new MockDOMImpl();
            }
            return null;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}

3) Subclass com.google.gwt.user.client.impl.DOMImplAh-hah!  Here's the catch... This step provides us just enough code to satisfy construction of our Widgets.  For my purposes, I let my IDE generate this subclass for me, and stuck with the default implementations it generated.  I return an instance of it above.

public class MockDOMImpl extends DOMImpl {
    public Element createElement(String tag) {
        return null;
    }
    [...]
}

The approach to this style of testing intercepts any calls on the Widgets themselves before anything is allowed to hit the underlying DOM implementation.  What I provide above is just an example of how this could be done, specifically when testing behavior of custom classes that happen to inherit or reference GWT classes.  Testing things like layout or UI concerns is another matter, but one which I would not consider 'interesting' enough for unit testing, since most of the behavior on the UI can be easily inspected by viewing Widgets as simple beans.

So why would you want to attempt this anyway?  First, I happen to like working in Groovy, so I crave more reasons to do exactly that.  Second (and more pertinent), much of behavior I find interesting in GWT apps revolves around simple message passing.  I trust GWT enough to do its job once I leave the Java space.  Beyond this are some philosophical differences I have with GWTTestCase, particularly since GWTTestCase makes it hard to maintain a larger body of unit tests, requires additional configuration in your module file (or as I've done before, constructed a different "test-only" module file that inherited from two module files), did not let me set up tests the way I would like to, etc.  I could go on.  When unit testing, very little of the logic I write is made less interesting or less relevant outside of a JS runtime environment, so where possible I would like to gain some benefits from treating everything as Java.

There are other benefits.  There's the noticeable speedup in execution time when running entirely within the JVM.  There's also less restrictions on the test class itself with regards to instance variables, language (i.e. Groovy), dependencies in outside packages, etc.  Why wouldn't I want such flexibility in my test code?  I really want my test code to be as concise and expressive as possible, particularly as my apps get larger and more complex.  I think having alternative ways of approaching this kind of testing brings a lot of these types of benefits.

Rails, Ajax, RJS, and Testing

As promised, today’s entry is Agile and Ajax. Also, it’s a dessert topping.

Ajax in Rails

The initial support for Ajax calls in Rails was centered on two framework methods called link_to_remote and remote_form_tag. The basic functionality of these methods is to allow a remote call to be triggered by a link or form submit and have the result of that call be used to update a DOM element somewhere on the page.

Moving outside that simple behavior, however, quickly got messy. Both methods specify a series of callbacks where arbitrary JavaScript can get implemented at various points in the call life-cycle. However, writing dynamic JavaScript in an ERB template is awkward, and the resulting method calls could get ugly.

Enter Ruby JavaScript (RJS), sometimes described as “training wheels for JavaScript”. RJS allows a very simple subset of JavaScript to be written in Ruby and translated to JavaScript as the result of a Rails Ajax Request.

Here’s what a sample RJS template looks like:

page.visual_effect(:fade, 'recipes_to_show',  :duration => 0.5)
page.visual_effect(:fade, 'category_being_shown', :duration => 0.5)
page.delay 0.5 do
page.replace_html("category_being_shown",
"Recipies For: #{@category.capitalize}")
page.replace_html("recipes_to_show", :partial => "recipes")
page.visual_effect(:appear, 'recipes_to_show', :duration => 0.5)
page.visual_effect(:appear, 'category_being_shown', :duration => 0.5)
end

The page variable is automatically provided by Rails and represents the page that is going to receive the JavaScript. There are about a dozen or so instance methods that page can receive, mostly having to do with the basic Ajax-y features of replacing HTML in a DOM element and calling Scriptaculous visual effects. This particular snippet fades out two elements, changes their text, and fades them back in for a crossfade effect.

(There’s a certain similarity of concept with Google Web Toolkit, but RJS is going after a much smaller and more focused piece of functionality, optimized towards what you would do in a single Ajax call in an otherwise standard interface. GWT, on the other hand, is trying to be the entire application on both the client and server side.)

How useful this is depends on your relative level of comfort with Ruby and JavaScript. I’m personally much more comfortable in Ruby, so I think this is just great. It’s especially nice since I can use Ruby blocks to abstract this crossfade function into something I can use generically.

def crossfade(page, *dom_ids)
dom_ids.each do |dom_id|
page.visual_effect(:fade, dom_id, :duration => 0.5)
end
page.delay 0.5 do
yield
dom_ids.each do |dom_id|
page.visual_effect(:appear, dom_id, :duration => 0.5)
end
end
end

The generic function takes a list of DOM ids and a block — the assumption is that all the content changing will be managed in the block. So the original snippet would now be changed to:

crossfade(page, 'recipes_to_show', 'category_being_shown') do
page.replace_html("category_being_shown",
"Recipies For: #{@category.capitalize}")
page.replace_html("recipes_to_show", :partial => "recipes")
end

If you’re feeling more adventurous, you can patch the crossfade method directly into the JavaScriptHelper class and change the call to page.crossfade, making it more consistent with the other calls performed in an RJS template.

Testing RJS

Now for the Agile portion — how do you test this thing? RJS templates can be tested pretty thoroughly based on the content of the JavaScript code being generated. It’s much harder at the moment to test based on the actual results of the JavaScript — for example, it’s hard to test that the DOM elements being referenced actually exist in the client page.

There are two mechanisms for testing RJS that I’ve found useful. The first is mock object testing. Using the flexmock package to set up the page as a mock object, a sample test for the crossfade method looks like this:

def test_crossfade
page = flexmock("page")
page.should_receive(:visual_effect).with(:fade, "dom_1", :duration => 0.5).once.ordered(:first)
page.should_receive(:visual_effect).with(:fade, "dom_2", :duration => 0.5).once.ordered(:first)
page.should_receive(:delay).and_yield.once.ordered
page.should_receive(:replace_html).once.ordered
page.should_receive(:visual_effect).with(:appear, "dom_1", :duration => 0.5).once.ordered(:last)
page.should_receive(:visual_effect).with(:appear, "dom_2", :duration => 0.5).once.ordered(:last)
crossfade(page, "dom_1", "dom_2") do
page.replace_html()
end
end

Without going into the details of flexmock because, hey, future blog post, the idea is that the mocked page object keeps track of the method calls it receives and checks them against an expected set of method calls. In this case, I’m telling the mock object that it should get two calls to the visual_effect method with various arguments, and that those calls should come before the other calls.

The interesting thing about this method is that on the face of it, it contains no assertions. Implicitly, though, each should_receive call sets up an assertion about the messages coming to the object that is validated at the end of the test.

The other mechanism uses a plugin called ARTS (Another RJS Testing System), which defines a method called assert_rjs, which checks the outgoing JavaScript for a method call matching a set of parameters.

Using ARTS, the following method tests whether an individual DOM element is in the crossfade:

def assert_crossfade(dom_id, replacement)
assert_rjs :visual_effect, :fade, dom_id, :duration => 0.5
assert_rjs :visual_effect, :appear, dom_id, :duration => 0.5
assert_rjs :replace_html, dom_id, replacement
end

And a full test of the example would look like this:

def test_one_crossfade
assert_crossfade 'recipes_to_show', /Recipe/
assert_crossfade 'category_being_shown', /Category/
end

The replacement argument can be either a string, in which case the output needs to match exactly, or a regular expression, in which case a Regex match is performed. In general, assert_rjs works by recreating what the JavaScript looks like from the assert call, and checking the actual output for the existence of that call. Again, this is most helpful when you can bundle calls together in a single assertion.

ARTS is a nice little plugin, and it does let you do some syntactic testing of your RJS templates, but semantic testing along the lines of, is the recipes_to_show element visible at the end of the RJS and what text is actually in the element is still elusive. I think that’s doable, but it would require a much more complex mock object representing the page, one that keeps track of a pseduo-DOM tree and can manage at least some of the effects of RJS calls. Another project for another day…

All Things FIT

I just noticed the FITpro plugin for Eclipse has reached its 1.0 release (here).  While I am not an Eclipse user, it is still good to see testing tools and utilities get some press-- particularly something which has proved to be so useful to myself and others such as FIT.

On the topic of testing (and FIT in particular), while there are a lot of things I like about FitNesse, it has never fully hit the mark for me completely.  It's still great, but it would be interesting to consider an alternative written entirely in Groovy, for Groovy.  Why Groovy, you may ask?  Those who know me have probably heard me mention this from time to time, but I think it would be useful to author FIT fixtures directly alongside the kind of markup which FitNesse provides-- and I think a more dynamic language such as Groovy would fit the bill quite well, while allowing support for existing fixtures.

Topics:

GWTTestCase and Server Side Mocking

While I like the fact that GWT supplies a mechanism for unit testing your applications, there is room for improvement on testing the interactions between the UI and server-side components.  Based on everything I have read so far, testing GWT applications is an area which many people tend to gloss over or merely pay lip service to, leaving developers to fend for themselves on issues such as how to incorporate the use of mocks, or how to test GWT applications while keeping the test code clean and maintainable.

For the moment, let's consider a simple application where a client requests data from the server, and updates some content on the UI.  We would like to assert that some content on the client can be updated with data returned by the server.  For purposes of testing, the client code contains a package-level method which executes a remote call and updates the content area (asynchronously, of course).  Here is a test case as we would like to write it:

      public void testRemoteCallPopulatesContentArea() {         // Mock out server call         server.willReturn("Foo data");         // Client invocation         client.executeCall();          // Assert client is updated         assertContentArea("Foo data", client.getContentArea());     } 

You can imagine additional testcases that assert behavior when the server throws an exception, returns an empty string, etc.  Looks like a great test case so far (short & sweet), but as you have probably guessed, there are hoops to jump through in order to get this code to actually do what we intend it to do, each hoop deserving of a much longer, in-depth discussion of its own.

This test case should look pretty familiar to anyone who has used mocks before.  In this test, we want to (1) mock out the behavior of the server component, (2) execute the call from the client's side, and (3) assert that the "content area" of the client contains the data we defined when we mocked out the behavior of the server component.

The work we will need to do breaks down as follows:

  • Define a service that will support 'willReturn(String data)'
  • Implement a mechanism for mocking out the actual implementation of the service method.
  • Implement our assertion logic, taking into consideration the asynchronous nature of the client code, the use of GWT's Timer mechanism, etc.

The third item is the easiest to envision-- the method 'assertContentArea' wraps all of the Timer logic, defering execution of the actual 'assertEquals' invocation until the client has had a chance to execute the remote call and update the content area under test.

I have a few solutions in mind for the first two items, one of which involves using Spring to intercept calls to GWTShellServlet during execution of each test case.  Can you guess how that one would work?

I'll delve into that side of things in following posts, but I hope this gets you thinking a bit more about readability of your test cases, and what test cases that extend GWTTestCase should really look like when they involve interactions with a back end component.

The awesome state of JavaScript development tools

Dietrich's post on the depressing state of IE develpment tools got me to thinking about the generally wonderful state of JavaScript tooling. Compared to just a few short years ago, we've got a wealth of productivity-enhancing browser add-ons, TDD frameworks and static-analysis tools at our disposal - most of them open-source. For those who want to get their hands dirty writing POJ, this is a golden era.

Like most developers, my code circa 1998 was filled with commented-out alert() statements. I spent way too many hours cursing IE4's inability to report accurate line numbers in its error dialogs. I relied heavily on Netscape's built-in debugger. Within a couple of years I had graduated to a primitive logging utility that spawned a separate browser window and output messages into it using simple DHTML. At the time, it seemed like a huge advance.

Then came the Firefox era, with its host of disparate add-ons. You could edit your CSS in the sidebar, selectively disable JavaScript and CSS, inspect the DOM .... Once again, the possibilities seemed endless. Now, thanks to Firebug, most of my grab-bag of browser add-ons are gone. Firebug is so powerful and wide-ranging that the only other add-on I use regularly is the venerable Web Developer Toolbar. Yahoo's new Firebug extension YSlow adds some really useful optimization benchmarks to the suite. When a plug-in begins to spawn its own plug-ins, you know you've got a winner.

I'd be interested to know, though, what kind of process UI developers use to debug their JavaScript. Most of us are using similar tools, but how are we using them? (That's an invitation to jump in on the comments, folks.) Every UI person I know develops prototypes in Firefox and Firebug, crossing his or her fingers that there won't be too many implementation-specific issues to tackle in the other browsers. Many rely on a logging utility - heir to that long-ago popup window - to grind away at any such browser bugs.

But beyond that kind of hunt-and-peck debugging, have we arrived at an industry-standard practice for client-side code maintenance? Who's doing true TDD with one of the flavors of JsUnit? Who's using Selenium to test their entire webapp in the browser? Who's picking apart the details of their syntax with Douglas Crockford's JsLint? Who's busting out Fangs or another accessibility test tool on a regular basis? The tools are out there. It would be interesting to know who's using them, and how.

When you're banging your head against a wall trying to figure out why a certain DOM element won't return the same node type from one browser to the next, it's easy to see why there are a hundred competing Ajax frameworks promising to solve all your cross-browser issues for you. Let's just remember how far we've come - and how important it is for real-deal UI developers to maintain the skills that they've honed for over a decade. The more trust we put in frameworks, the more helpless we'll feel when our code fails and we've lost the ability to figure out why.

Javascript, Unit Testing and Code Coverage

Q: Why are there no good Open Source dental practice management software packages? A: Because there are so few dentists who are C++ programmers.

Paul Watson raises the question of why there are no decent code coverage tools available for Javascript:

Am I to think that all those millions of lines of Javascript out there on all those Web 2.0 sites that espouse agile practies with TDD influences don't have code coverage? Sure, some may have unit testing but unit testing without code coverage is a less than ideal situation. You simply don't know if you have tested all functions and all paths in your functions. Unit testing and code coverage go hand in hand, they back each other up.

He has found one commercial tool that is currently in beta, but nothing else. It apparently takes the approach of hooking into the various browser platforms by means of a DLL? I know that there has been some talk about hooking code coverage into Venkman, Rhino and the Komodo IDE. But so far no one is offering a Javascript only, cross-browser solution.

So what are you to do? Venkman at least can give you function level code coverage with profiling, but that's only good for Firefox. Same with the commercial profiler from Tito Software for IE.

Unless the Mozialla and Microsoft guys provide something like this, I don't see it happening in open source. The best open source software is always made by users for users. How many Javascript developers also have the skillset to develop the necessary IE, Firefox, Opera and Safari plugins?



Technorati : , ,

Improving Test Coverage of Ajax Applications

It has been recognized for some time that Ajax applications are a different animal when it comes to testing. In the world of pre-AJAX web applications, the state of the art involved recording HTTP transactions and scraping the resultant HTML pages to check for correct results. That was fine as long as the application was the typical form based, rectangular HTML webapp. With Ajax, all sorts of other considerations come into place, like whether a particular drag and drop action works, not just if the recorded HTTP Request that it's supposed to generate results in the right HTML page or XML message.

The shortcomings of the protocol and screen scraping approach have lead to more sophisticated solutions such as Selenium, a browser based testing solution. With Selenium, all that Javascript can execute and all of those DOM changes can happen and your test scripts can excercise the application through the much more fine grained issuing of interface events. Problem solved, right?

Well, not really. If you're implementing a document based rather than a form based application, getting good test coverage of an Ajax application can be problematic. In the case of a form based application, you have a limited number of paths, so path based, statement based or condition based code coverage measures can all work fine. Now imaging trying to do path based code coverage for Microsoft Word or Excel; the number of interface choices at each point can mushroom like crazy. If the number of UI event choices at each point are no more than 10, then the number of paths after n operations is 10^n.

Fortunatley, this problem of code coverage has been faced once before -- during the move from form-based and command-line based applications to GUI applications. Lots of good research has been done on this topic. Take for instance Coverage criteria for GUI testing by Atif M. Memon, Mary Lou Soffa and Martha E. Pollack (September 2001, ACM SIGSOFT Software Engineering Notes , Proceedings of the 8th European software engineering conference held jointly with 9th ACM SIGSOFT international symposium on Foundations of software engineering ESEC/FSE-9, Volume 26 Issue 5). They propose an approach of dividing up the user interface into a number of components that can be tested independently. They point out that large GUI's are haeirarchicacal, made up of dialogs, panes, etc.

Once an application has been divided into components, all possible events available for a component are identified and an event flow graph is constructed that reflects all possible compositions of events. Then inter-component interactions are identified and an "integration tree" is constructed, i.e. a tree rooted at the main or starting point of the application and connecting to components that are activated via events from another component (restricted-focus, unrestricted-focus and termination events in the parlace of the paper). The paper goes on to describe metrics and testing approaches based on this application decomposition. It also points out how statement-based code coverage can be very misleading.

There are other approaches to testing GUI's, but I hope this one has given you a notion that there is more to testing an Ajax application than turning a Use Case into a test scenario, or that a statement-based code coverage tool will let you sleep well at night over the adequacy of your functional tests.


Technorati : , ,

About Pathfinder

  • We design and build extraordinary applications for companies looking to make the next great idea a reality.
  • learn more

Topics