Rich Clients are all about user experience…
We’re not talking about our customers and their wallets. Whether on the web, desktop, or elsewhere, eye-pleasing user interfaces that present information in intuitive and richly engaging ways are now what users expect. In fact, it’s often the user interface that sells an application or software service. If done well, the richness of an interface leaves a user happy to have used it – sometimes fanatically so.
But with Rich Clients also comes difficult-to-test complexity in the underlying software. By using test-first practices and a set of complementary techniques, however, it’s very possible to create well tested and very usable interfaces.
If designed and implemented well, even rich clients can be tested in an automated fashion. When we say automated, we don’t mean scripted “clickers” that simulate mouse events. Rather, we’re talking about full-on Test-Driven Development and system, integration, and unit regression test suites.
Interaction-based Testing
Any piece of software is composed of multiple interacting modules. We’ve found that beyond simple unit test assertions on expected return results from functions and methods, the interactions among those functions and methods are incredibly important to test. Enter Mocks and Dependency Injection. Object Oriented languages like Java, Ruby, C++, and C# ease the implementation of these concepts. However, even in a procedural language like C, these same concepts can be employed in automated testing.
Mock Objects
Mocking is the practice of creating test-empowering, “fake” versions of the modules around a piece of code under test. Each Mock has functionality to return any set of results the programmer needs for testing. Additionally, each Mock is able to capture which of its functions or methods have been called and with what parameters. Test assertions within a unit test are then able to verify that the code under test has interacted with other modules as expected.
Dependency Injection
Dependency Injection (also referred to as Inversion of Control) is a design pattern geared towards creating loosely coupled and testable objects. It’s very complementary to Mock Objects.
Rather than instantiating within Object A the object whose services it will use (Object B) we instead design Object A to accept a reference to Object B. Interfaces allow us to define contracts among objects. As such, we can pass into an object under test an object that conforms to the interface it expects. The same interface allows a particular object to make use of a production object or a Mock Object for testing. Loose coupling and better design inevitably results.
Presenter First
The key to usable interfaces is good interface design. The key to reliable, well functioning interfaces is test-first software development. Creating testable user interface software requires decoupling of the presentation logic, business logic, and on-screen widgets. We’ve found the ideas of the Model View Presenter design pattern to be very helpful. We decompose interface requirements into testable Model, View, and Presenter components using a technique we helped develop called Presenter First. Presenter First guides the transformation of user requirements into user interface programming tested under automation.
Mock Objects, Dependency Injection, and Presenter First are a synergistic set of practices that drive good user interface testing. These automated tests guide the overall design and produce well functioning user interfaces.
System Testing
Beyond unit testing comes integration testing and system testing. Integration testing generally takes the form of groups of modules being exercised together in a unit testing framework. System testing, however, exercises the whole system from end to end externally. System testing is test-first as well. We implement a system test before the system actually supports the feature(s) under test. It drives good design and provides a means to exercise our unit test assumptions and ensure that as the code evolves or is maintained that nothing breaks.
Resources
Test-Driven Development
- We have written about our devotion to TDD.
- Code the Unit Test First provides a gentle introduction with a sample.
Mock Objects
- The Wikipedia entry on Mock Objects includes a great list of further reading and Mock Object libraries for various languages.
- mockobjects.com provides the latest thoughts on Mock Objects.
- LaszloMock – For unit testing in OpenLaszlo, we created LaszloMock.
- HardMock – One of our developers, Dave Crosby, created HardMock for Mocking in Ruby
- JSMock – Another of our developers, Justin DeWind, created JSMock for Mocking in JavaScript.
System Testing
- Systir is System Testing in Ruby. This doesn’t mean it’s system testing for Ruby; rather, we use the power of the Ruby language to allow us to write system tests that exercise nearly any type of software system externally.
Web Applications
- Ruby on Rails tools & techniques – Please see our collection of practices and tools that bring Test Driven Development to web-based rich clients.

