Web UI regression testing using CFSelenium, MXUnit, and ImageMagick

| No comments :
Regression testing's goal is to make sure that future changes do not produce new bugs. I went about applying this principle to the look and feel of a site. So that if a css or text change moves away from the baseline the differences can be seen.

Tools used

Mac 10.6 Snow Leopard with built-in Apache server
Coldfusion 9 developer edition
MXUnit 2.1.1
CFSelenium 1.7
ImageMagick 6.7.4-6
Firefox 3.6.25

Set up

So first you need access to a ColdFusion server. Then install MXUnit. As of this posting, the latest stable version is 2.1.1. I followed the docs and installed it to my webroot so I wouldn't have to configure it. Next, I added a mapping to Coldfusion Administrator named mxunit that points to the mxunit folder.

CFSelenium was just as easy to install. I downloaded the latest version which at the time of this posting is 1.7. And extracted it to my webroot in a folder named cfselenium. Then I added another mapping named cfselenium.

For ImageMagick I followed the instructions and installed it using MacPorts. It took about 10 minutes to finish installing as there were a lot of dependencies.

The Test

My sample uses a simple registration form, register.htm, with four fields for first, last, phone, and email.


My sample site has the following file structure:

register
    tests
        testsuite
            RegisterTest.cfc
        runTests.cfm
      register.htm

The component I use to test this form is RegisterTest.cfc. It extends cfselenium.CFSeleniumTestCase which extends mxunit.framework.TestCase. The mappings I created earlier allow these prefixes to resolve correctly. It contains the test functions that run selenium commands and mxunit functions. You will need to replace absolutePathToWebRoot with yours.


In the formPageLooksRight function are the lines that take and compare the screenshots.

This cfexecute tag executes the ImageMagick compare command which compares baseline.png and screenshot.png and creates an image with the differences as compare.png.
<cfexecute name="/opt/local/bin/compare" timeout="60" arguments="""/absolutePathToWebRoot/register/tests/baseline.png"" ""/absolutePathToWebRoot/register/tests/screenshot.png"" ""/absolutePathToWebRoot/register/tests/compare.png""" />

The next cfexecute tag again runs the compare command, but this time it outputs the number of pixels that differ between the two images. For some reason the cfexecute tag thinks the output from this command is error output, so instead of storing it in the variable attribute it puts it in the errorvariable attribute.
<cfexecute name="/opt/local/bin/compare" timeout="60" arguments="-metric AE ""/absolutePathToWebRoot/register/tests/baseline.png"" ""/absolutePathToWebRoot/register/tests/screenshot.png"" null: 2>&1" errorvariable="diffVal" />

You can read about comparing images using ImageMagick here.

To run the tests navigate to runTests.cfm?debug=true in the browser. The debug variable allows the debug messages to show in the test output. This page runs the test functions inside any cfc in the testsuite folder that either starts or ends its name with "Test". Our example only has one, RegisterTest.cfc.


When you run the tests CFSelenium starts the selenium RC server automatically for you. Sometimes you might get a timeout error when you try to run your tests. Killing any running instances of Selenium fixed this for me. ps -A | grep "selenium". Gives the process id (pid). kill pid. To kill it.

The first time you run the tests the formPageLooksRight test fails because it is looking for a file "baseline.png" in the tests folder that does not exist. It does create screenshot.png of what the page looks like. So this will be used as the baseline so rename it to "baseline.png".

If you don't set the background color for the page the screenshot shows it as black. Specifying the background-color of the body tag fixed this.

<body style="background-color: #ffffff">

Run the tests again by refreshing the page. Now the test should pass. The links in the test output show the baseline (exp), the screenshot taken by the test (act), and any differences between the two (dif).

mxunit test results showing all tests passed

Now make a change to the UI in register.htm. I removed the "N" from the "First Name" label.

This time after you rerun the tests you will see that formPageLooksRight has failed with a message that shows how many pixels differ between expected and actual screenshots. Clicking on the dif link highlights the pixels that differ between the two images.

mxunit test results showing failed test

Expected:
expected screenshot

Actual:
actual screenshot

Difference:
differences between two images

Application last modified date

| No comments :
Our web development team has a requirement that we include a date the site was last updated. Since we primarily develop three tier web applications and not static web pages our html pages don't change much as they are views for database data. Instead of a date on each page giving when it was last updated like this article shows how to do, our date shows when the last update was made to the entire application. To do this, I created a cfc function that uses cfdirectory to look at all the files in my application folder on the web server and get the last modified date.



Then I call this function in application.cfc's onSessionStart and store the result in a session variable:



Then to display the result I put the following in my site's footer.

AppLayout: A simple starting layout for a web application

| No comments :
OK, first post. I've been delaying this for awhile, but it's a new year and I couldn't wait. I am starting this blog to contribute to the online web development community from which I've received so much knowledge. I am often googling for a solution to a technical problem and quickly find someone has tackled it and posted it on their blog or website.

AppLayout
AppLayout

I've been working on developing a fluid, lightweight application layout that is 508 compliant. The design of this blog is based on it. It uses percentage based widths to adjust to the user's viewport width (browser window). EM-based sizing keeps text and images within containers and correctly proportioned through font size changes. Other than a couple of optional images, it uses CSS entirely. The navigation is keyboard accessible even with javascript disabled (although not as visually sound) Update: I updated the submenus to use code from Twitter Bootstrap so they are not usable with javascript disabled anymore. The HTML is W3C validated and I tried to reduce the number of tags to make it as semantically accurate as possible. I used the WAVE toolbar to fix any accessibility concerns. The layout has been tested in a number of browsers and versions on both Mac and PC including Chrome, IE, Firefox, and Safari.

The code and documentation is available on GitHub and contains everything needed to put on a webserver and display. It is provided under the MIT license.

Any issues or bugs can go in the issue tracker.

I couldn't have made this layout without help from the community. Here's a few that I can remember. If I forgot you, let me know and I'll add you to the list.

Blake Haswell for keyboard accessible dropdowns Replaced with Twitter Bootstrap dropdowns.
Matthew Tayler for keeping footers at the bottom of the page
Yahoo! developers for YUI reset and other tips
Chris Coyier for CSS triangles

Stay Connected

Subscribe to feed Get email updates Follow @linecomments on Twitter Facebook

Archives