Home » Software Dev

What’s After Unit Testing?

10. January 2010 by Martin Rue 6 Comments

Bugs Back in high school, I remember writing the second version of my IDE program. This was the beginning of 2004 and I had very little experience of writing any sizable piece of software. IDE2 would allow multiple users to connect to a central server where they could work together on code. It would also have some other features too, such as interactive drawing and file transfer.

Once complete, the entire application consisted of a single source code file. There were 11,135 lines of C inside. Today the application still compiles and it works just fine, but holy crap – it’s a mess. Returning to it now, I cannot imagine making any significant changes easily. It’s legacy by any definition.

Back then, IDE2 was simply a 17 year olds excuse to explore the Win32 API and play around with some C code. The concept of supporting users and their changing needs wasn’t even on my mind. Today however, the code I write is for real systems with real users.

Creating unit tests is an important step in ensuring that we have the confidence to change our code in the future. Legacy systems with no unit tests and 11,135 lines of C code cannot safely be changed while knowing that another bug hasn’t been introduced in the process.

However, unit tests only go so far. By definition, a unit test is designed to test the functionality of a single unit of your code. The unit of code is just a cog in a machine; we might know that the cog has all of its teeth, but how do we know that it’s turning the other cog? What comes after unit testing?

Now that you’ve perfected your unit testing strategy and you’re even able to detect when someone sneezes on a check-in, you need to be thinking about testing the system as a whole. This is where acceptance testing tools can help.

For example, how do you verify that your company telephone number is still appearing at the bottom of all pages of your web application? or that all your images still contain alt attributes? The answer is an automated testing tool such as Selenium.

Selenium allows you to define high level tests that make assertions at the presentation layer of your web application. Thanks to a Firefox plug-in, tests can be easily designed and executed in the web browser. But more importantly, Selenium RC can automatically run your test suite, which is particularly useful for integration server scenarios.

To understand how this works, we’ll be writing a few tests for this blog which verify that the RSS links at the very bottom of the page are present and that the twitter updates are still working. If future changes to the blog cause the RSS links to disappear or the twitter updates to stop working, we’ll know about it.

Installing Selenium

First of all, you need to install Selenium. Head over to http://seleniumhq.org/download and download & install Selenium IDE and Selenium RC. Note: Selenium RC is just a directory with some .jar files and requires no formal installation other than extracting the archive (but requires the Java runtime).

Selenium IDE

Having installed Selenium IDE, you should find yourself with a new Firefox extension that looks a little something like:

 image

Notice how the Base URL is set to the page that Selenium is run from (this blog in the example shown). The other thing to be aware of is the big red button in the top right. This is the self destruct button. Good, you’re still listening – the big red button will allow us to begin recording tests.

Manual Testing

Recording tests is easy – click record and then right click on the page that you want to test. You’ll see some menu options that weren’t there before, including a Show All Available Commands option. These are the  various Selenium test commands. For now we’re just interested in the assert commands.

As you add commands, you’ll see them appear in the Selenium IDE window. You can add as many as you like, each of which is constituting a single assertion about the page that is being tested. For the purpose of this example, let’s add the following three tests:

Note: though there are 4 items in the Selenium IDE window, the first isn’t a test. The first item is the command that causes the Selenium test runner to open the root web page. The subsequent three items will each make an assertion about that page. 

image

We now have three assertions that check the following:

  1. Do we have an element on the page that has the text “Entries (RSS)”?
  2. Do we have an element on the page that has the text “Comments (RSS)”?
  3. In the unordered list with an ID of “twitter_update_list”, is there a list item present?

These tests are not bullet proof of course, but they serve the purpose of a simple example well enough. Let’s hit the play button and see what happens.

image

Great – we won’t be buying donuts any time soon. On the other hand, it’s natural to be suspicious when tests work first time – so let’s break them. You go grab 2 coffees while I modify the blog code so that it loads the twitter feed from an incorrect URL.

I’ve successfully broken it. The blog is now failing to load the list of tweets – as annotated with the help of my steady hand:

image

If we run the test suite again, hopefully it will fail:

image

Excellent’. The test has picked up the problem.

You should now have a better understanding of what Selenium offers in terms of testing the higher level aspects of your web application. The question is who the hell is going to sit there all day clicking the run button? In a world where I don’t even have to make my own coffee, I certainly shouldn’t have to click that button myself.

Automatic Testing

With the help of Selenium RC, we can integrate this test suite into our automated testing workflow by way of standard unit tests. The unit tests are compiled and executed like any other unit tests, but during execution, Selenium RC will fire up a browser instance and essentially perform the same functionality as seen above. Now we’re talking.

The first step is to write the unit test that talks to Selenium RC. Fortunately Selenium IDE can do this for us, saving us from writing a single line of code – kind of. You may proceed to excitedly find the Options, Format, C#  menu item and observe the magical transformation.

Those of you who have managed to keep their composure will notice the generated code uses NUnit. Feel free to adjust accordingly if you use a different unit testing tool. The next job is to create a C# class library to house the generated test code. I slightly adjusted the tests to include a second argument to the NUnit Assert calls, so that I know exactly where in the unit test execution reached before it broke (since there’s just a single unit test with three assertions inside). You also need to change the address of the web application in the test set up.

So you have a unit test project with the generated code and references to the NUnit assemblies. You also need to reference the Selenium assemblies which you’ll find in the archive of Selenium RC that you downloaded earlier. Add references to the following:

  • ThoughtWorks.Selenium.Core.dll
  • ThoughtWorks.Selenium.IntegrationTests.dll
  • ThoughtWorks.Selenium.UnitTests.dll

Finally, you need to make sure there is a running instance of the Selenium RC server. Open a prompt and change the current directory to the path of your extracted Selenium RC download. Then execute:

C:\Users\Martin\Desktop\selenium-remote-control-1.0.1\selenium-server-1.0.1>java -jar selenium-server.jar

Everything is now ready for the Selenium test suite to be run as a unit test. Let’s give it a shot:

image

Perfect. The test reached the same stage as earlier, but now through automatic execution via NUnit. I’ll just go and fix that twitter URL and let’s see what happens:

image

Phew.

The End

Having solid unit tests and good code coverage gives you confidence that your code is behaving the way you expect and allows you greater flexibility to change it. However, some aspects of a system can only be tested once all the individual units are tied together. These other testing requirements usually relate to UI and must happen at a higher level.

Selenium makes creating presentation layer tests easy and provides the tools you need to integrate them into your automated testing workflow. Having a suite of automated acceptance tests takes you one step closer to knowing about problems when they happen, not simply when they’re noticed (usually by a customer).

Try it out and see if you can make your life easier. Until next time, it’s been emotional.

Comments

pingback
blog.cwa.me.uk said:

Pingback from blog.cwa.me.uk

The Morning Brew - Chris Alcock  » The Morning Brew #514

Lee Englestone
United Kingdom Lee Englestone said:

This is actually quite exciting.. I've been using Selenium IDE for a while but never new it could output NUnit Unit Tests. doh!

May be slightly better if a Selenium RC Server instance was started and stopped automatically rather than relying on the current manual process of starting the server.

pingback
twittertweet.freecartshop.com said:

Pingback from twittertweet.freecartshop.com

Invalid Cast | What's After Unit Testing? | Best resource for twitter and tweets

trackback
uberVU - social comments said:

Social comments and analytics for this post

This post was mentioned on Twitter by martinrue: Blogged: What's After Unit Testing? http://is.gd/5ZpRA

Snakey McOil
Yemen Snakey McOil said:

There's a good discussion here about how testing with automated UI tools such as Selenium are traditionally difficult to maintain.

blog.objectmentor.com/.../ui-test-automation-tools-are-snake-oil

pingback
jaceju.net said:

Pingback from jaceju.net

網站製作學習誌 » [Web] 連結分享

Add comment




  Country flag

biuquote
  • Comment
  • Preview
Loading