Main

November 03, 2007

Embarassing

Wow - this is embarrassing. Another one of those "I can't believe I haven't posted in so long" posts. But really, it's been 5 months since my last post, and 7 months since my second to last one. Ouch!

That is going to change, especially because I little side project I have going on involves a lot of blogging...

As for what I've been up to...

  • Got married a few weeks ago
  • Sold my company earlier this year (I don't think I ever actually blogged that - whoops!)
  • Been traveling a lot to Boston (50% of the time)
  • Speaking at various conferences (The Ajax Experience, STPCon, StarWest, etc) - mostly QA-related stuff
  • Not too involved in Struts and OpenSymphony, but I hope to be again soon
  • Still fairly involved in OpenQA

I think that's it. More posts soon...

April 11, 2007

Standalone cross-domain XHR interface

Does anyone know of a simple, standalone cross-domain XHR interface that allows for the ability to swap between a real XHR implementation and a cross-domain, iframes-based implementation?

I know Dojo and DWR, among others, have them, but they are all part of a larger framework. Because this is going to be used with Selenium, which needs to avoid polluting common popular JS namespaces, I'd prefer to find something that is standalone.

I'm very surprised one doesn't pop up when I search google.

April 03, 2007

Next gen testing tools: infrastructure

About a month ago I wrote that I thought the two most important things tomorrow's testing tools need to help with are infrastructure and maintenance. I'm about a month late on my promised follow up, but I suppose it's better late than never.

What I wrote was:

By infrastructure, I mean challenges like setting up the test environment, keeping it in a consistent state, ensuring you have all the tools/browsers/databases/whatever always available for automation, running your tests in a timely manner, etc. All of these are much more challenging that JUnit, simply because JUnit only concerned itself with in-memory state and fixtures that could be recreated in milliseconds, not minutes or hours.

As applications become more complex, the work required to automate functional testing also becomes more complex - often more complex than the application itself. For example: it's trivial these days to do Web 2.0 "mash ups" in your app and embed a Google Map in to your page (it's a simple <script> block).

But what about testing that functionality? What about checking the performance of it? Not only does it require a compatible browser (no more HttpUnit or HtmlUnit, now you need to use something like Watir or Selenium). And what if you want to test what your app behaves like when the Google Map service is down or running slow. How do you do that?

The fact is that as we continue to build layers and layers of abstraction and extensible services, our speed at which we can develop rich, complex applications grows and the ability to test those applications becomes a much harder challenge.

Next gen tools must help

This is why I believe that the most fundamental thing that any testing tool (or process) will do in the coming years is to help manage these complexities. It's not an easy problem to solve, but fortunately some ancillary technologies such as virtualization help immensely.

The testing tools of tomorrow can no longer simply assume that automation of the test case (click there, type this, click here, type that, ...) is enough. We are in an age where that type of technology is a commodity (Selenium, Watir, etc). They must take developers to the next level of automation and help automate the process of preparing to run these scripts.

Many QA teams spend a majority of their time not writing automated tests or performing required manual testing, but in fact setting up the application in a QA/testing environment. This is a huge waste of time and is something that is begging to be automated.

Continuous integration is key

Let's pretend tomorrow's tools do this. They now automatically set up your database to a know state. They help you manage snapshots of data that can be used for various automated tests. They reset the state as needed when running automated test cases. They deploy your application properly. They set up a web browser with the cache cleared out. They do it all.

The logical next step is continuous integration. The vision outlined in Martin Fowlers essay can be realized for not just code that can be easily unit tested, but for all the code in your application, even HTML, JavaScript, Flash, etc.

Now when you check in your latest JavaScript changes, you don't have to worry about nagging questions like, "I forget, does IE support hasAttribute()?" (it doesn't). Now all the benefits you got for writing unit tests (instant feedback on failures, etc) can be realized for writing functional tests.

Suddenly there is a huge incentive for getting developers to take part in the process of writing functional tests in addition to the unit tests they write. That's because they are continually reminded of those tests, every time they check in code they are notified if one of those tests fails.

Contrast this to today, where most teams barely even write functional tests, and those that do usually relegate that job to the QA team to run near the end of the release cycle. The difference is like night and day.

Some are doing it today...

The good news is that some people are already doing this. Projects like HSQL (an in-memory database) and Cargo (automatic J2EE deployment tools) help considerably. I recently "blogged":... about how Atlassian is using these tools to get close to tomorrow's development and testing process today.

HSQL and other in-memory databases help here because they allow for your functional tests to have clean fixtures. That is: they provide a simple and quick way to reset the data in your application so you can run the next functional test. And because they are in-memory, you can reset the state for every test, ensuring you get zero conflicts between test X and test Y.

Cargo is another great tool because it does all the heavy lifting required to deploy a J2EE application to a specific app server (Tomcat, Resin, JBoss, etc) and even allows you to programatically configure it, such as define database connection pools. In fact, Cargo recently began to add support for deployment and configuration of databases as well, so you could use it to set up your entire application deployment just before you run a test.

... but soon they will need more

While HSQL and Cargo are nice, they still are merely emulations of the real thing. That is, you likely won't use HSQL in production and you likely won't deploy on the same configuration of Tomcat that Cargo provides. Just as jWebUnit served as an acceptable browser emulator until AJAX arrived, these projects too do their job well for the time being.

However, as deployments become more complicated, so too will we again need to test on the real thing. So just as Selenium is to jWebUnit, tomorrow's testing tools will need to provide an ability for technologies like HSQL and Cargo.

For example, just last week I had first hand experience with this challenge. Our functional tests use HSQL, but our production environment runs on Postgres. I had checked in some new code that executed a query that was passing just fine in our continuous integration process, but when it came time to push to staging, it broke.

The truth is that in a perfect world, we should be testing on the same environment as our production one, and things like HSQL just don't cut the mustard. The reason we use them, however, is pure pragmatism: it costs too much and takes too long to develop a testing environment/functional testing fixture that works with a clone of your production environment.

Rising infrastructure costs

In fact, even those that are doing this today run in to challenges: Atlassian's full integration test suite takes hours to run. Some teams have reported to me that their suites take over a day to complete. And this is all while using shortcuts in their fixtures such as HSQL.

This is where parallelization comes in. The reason these test suites take so long is that they almost always run in sequence. That is: test X runs, then test Y runs, etc. To save time, some teams cut out the heavy lifting in their fixtures (such as deploying the application, setting up the DB, etc) to only happen at the start of the suite rather than each test.

This almost always leads to tests that end up conflicting with other tests (ie: test X and test Y both try to create the same user with a unique username of "bob"). But on top of that, it also begins to introduce dependencies between tests and a preference towards test ordering.

That's because, after a while, developers begin to take advance of this sequential order and do even more nefarious shorts. No longer does test Y need to create a new "Widget ABC", because test X did. Of course, if test X ever changes, test Y suffers for it.

So why do even the best teams do this? Because there really isn't another option today. That's because the cost in terms of hardware/infrastructure as well as developer time are orders of magnitude larger.

If you currently have 500 functional tests and it takes, on average, 10 seconds per test, plus a one-time 5 minute fixture setup time, then you can run all your tests in about 90 minutes. But if you reset your fixture for each test, it would take 43 hours. Pragmatism takes hold usually right when people realize this.

Even at the much smaller 90 minutes, it's often too long to place in to a continuous integration process that runs on every commit. The solution is parallelization. Now image those 500 tests running in parallel. The entire suite could run in 5 minutes and 10 seconds - or a short enough time that you could introduce a complete, reliable, real functional test suite that runs as often as you need.

The limitation today is the hardware costs: 500 build machines would cost a team $1,000,000, plus multiple times more maintaining it, powering it, etc. It's just not possible... today.

The next gen testing tool isn't a tool at all

Assuming that a "next gen testing tool" must be something that radically improves the software development process, it is my belief that tomorrow's next gen testing tool will in fact not just be a tool, but an entire infrastructure, most likely offered as a service that you can rent on an as-needed basis.

It would let you run your 500 functional tests in as many as 500 parallel tasks, or as little as 1. It would let you ramp up the parallel tests as your needs and budget evolve. It would finally allow you to run all your tests after every commit, giving you the maximum level of confidence after each commit.

... and it might even be called HostedQA ;)

February 27, 2007

Do it: use ridiculously long test method names

"Dan North" (tastapod!) has a good write-up on what he is calling "BDD": Behavior Drive-Development.

He does a much better job than I can do discussing all these items, but the thing that struck me is that almost all his conclusions can be reached by following just one piece of advice: make your test methods really expressive.

I started doing this in 2004 and it has been a huge help. My tests are more focussed, and because of that, I write more tests because it doesn't take as much thought/energy. And in writing more tests, I often design my code better, and ultimately produce software faster. As a nice side effect, quality has gone up, but that is not the primary reason for TDD or BDD.

Unfortunately, Dan's examples of test methods were rather weak - often the agiledox crowd uses really simplistic examples. So I thought I'd give some examples of some of my methods from HostedQA:

  • parsingHostHandlesHttpAndHttpsAsWellAsOptionalPorts
  • findingAnAccountByNameWorksAfterCreatingAnAccountOfTheSameName
  • creatingNewAppConfigReturnsSameIdAsTheIdSetOnTheAppConfigReference
  • findingAppConfigsForAProjectReturnsThemInAlphabeticalOrderByName

And my personal favorites (broken up with a space because they are so long):

  • updatingAppConfigWithoutResourcesThat UsedToBeAssociatedWithItCausesThoseReferencesToBeDeleted
  • deletingAPopulatedProjectCausesAllChild EntitiesToAlsoBeDeletedAndTheProjectIsCompletelyDeleted

Kind of annoyingly long methods? Absolutely. But not only, as Dan points out, is it easier to know what went wrong when a failure occurs, it is also almost brainless to implement these tests (and thereby design your application in the most direct manner possible).

If my test requires that I test that "updating an app config without resources that used to be associated with it causes those references to be deleted", it's really easy to know what I need to test - it's literally spelled out for me.

As a small note: Dan recommends that tests usually have "should" in front of them. I prefer to think that all my test methods (I use TestNG, so I don't have "test" in the method names) have "test that" prepended in front of the sentence. Ie: "test that adding X and Y results in Z" becomes addingXAndYResultsInZ.

Next Gen Testing Tools

What Problem Would Next-Generation Functional Testing Tools Solve?:

Various people have tried various structures including table driven things (like FIT/FITnesse) and Domain Specific Languages. But none of these approaches has quite succeeded in transforming the state of the practice the way JUnit did for unit testing.

(Via Ruminations.)

Elisabeth Hendrickson has posted several posts on next gen testing tools recently.

With HostedQA, which, by the way, recently had some major developments I'll be announcing soon, I tried to attack two main problems that crop up when writing very rich tests like functional and acceptance tests: infrastructure and * maintenance*. I'm sure that there is a lot to do on the reporting front as well, but I'm leaving that alone for now. :)

By infrastructure, I mean challenges like setting up the test environment, keeping it in a consistent state, ensuring you have all the tools/browsers/databases/whatever always available for automation, running your tests in a timely manner, etc. All of these are much more challenging that JUnit, simply because JUnit only concerned itself with in-memory state and fixtures that could be recreated in milliseconds, not minutes or hours.

When I talk about maintenance, I mean the issue of describing tests in a way that is usable by the test writer and evolving the test as the product and requirements evolve. Again, with JUnit test description was easy: the test writer had intimate knowledge with the item being tested and was able to write it in the same language. For complex testing, there are literally a handful of languages being tested (SQL, Java/Perl/Ruby/etc, HTML, JavaScript, Flash, PL/SQL, etc), so right off the bat there is a big disconnect between the simplicity of JUnit and this problem.

I'd like to dive in to the solutions I've come up with for both of these, but it's getting late and I'm already in the wrong time zone. But I promise to follow up in the next day or two on how HostedQA has addressed infrastructure and maintenance problems, all with the goal of making functional testing as ubiquitous as JUnit is.

For now, I leave you with this: These are the two biggest challenges that I see with this type of testing. Do you agree? Disagree? What is your biggest barrier to entry for this type of testing?

October 05, 2006

Apache MyFaces is using HostedQA

I just recently discovered that HostedQA usage is picking up: now Apache MyFaces is using it too!

I'm personally really excited about this because it is one of the first cases where an opensource project has integrated with our products without any help directly from me. Very cool!

October 04, 2006

Selenium RC now supports HTTPS

As of a couple days ago, I added HTTPS support to Selenium RC. This is a major addition, as it has been pretty much the only large feature missing from Selenium products. The result is that you can now remotely drive web browsers on sites that use HTTP or HTTPS protocols. Just as Selenium Remote Control was, this code was originally created as part of our HostedQA product.

Using this feature

To get started with testing on HTTPS, you have to use the custom browser launcher for now (we'll add support for it for the specific browser launchers as time goes on). The reason for this is that you need to import a Certificate Authority in to the main browser profile. Look in the advanced/security settings in Firefox/IE for this option.

You can find the CA at http://dangerous-certificate-authority.openqa.org/

Once you have the CA imported to the browser and have changed your tests to use the custom browser launcher, you can begin testing against HTTPS. Everything should just work.

How it works

Unlike other similar web testing tools, this solution doesn't require you to prepare the web browser for each domain you want to test. Rather, you only need to prepare the browser once by importing the CA.

What happens behind the schenes is that as each HTTPS connection is opened to a unique server/host combination, a mini-instance of Jetty is spawned off and used to tunnel SSL connections to the server. However, that Jetty instance needs a keystore that is signed by a trusted CA and is associated with the domain in question.

That keystore could be generated through a series of keytool and openssl commands, but we didn't want you to have to install these locally, since that can be a pain, especially for openssl. So instead, we created a web service at the dangerous-certificate-authority.openqa.org domain that generates the keystore for you.

The downside to this approach is that you must be online for HTTPS support to work. In the future we may offer a fallback that issues the keytool/openssl commands if the online service can't be accessed.

Give it a shot

The latest SNAPSHOT builds at maven.openqa.org should have SSL support available. Give it a shot, or wait for Selenium RC 0.8.2 to come out.

Or, alternative, sign up for HostedQA and start using these features (plus a ton more) today.

October 03, 2006

Pre-loading VMs to optimize automated testing

A really cool feature we recently added to HostedQA was the ability to pre-load virtual machines in order to optimize automated testing. At first, I wasn't sure if this was going to have any real user experience impact. But after having built it, I wish I'd done it sooner.

It turns out, if you have the RAM and you're using VMs for automated testing, you should really think about pre-loading your VMs ahead of time. Then instead of waiting several minutes to kick off your automated tests, they can begin right away.

Now granted that if your test suite takes 10 hours, then a 3 minute gain isn't that important. But that's not the use case that this is designed to optimize. Instead, this feature, and the general concept of pre-loading VMs, is all based around the use case of creating new tests.

Why creating? Often when someone writes a complex test case that depends on the entire system being deployed and working properly, they don't want to go too far without verifying they are on the right track. They do this by running the test. Now your 10 second test actually takes 10 seconds to run, instead of 3 minutes and 10 seconds. Suddenly, the environment is much more hospitable for test creators.

September 28, 2006

Selenium 0.8 Released

Selenium 0.8 Released:

Version 0.8 of the web application functional testing tool Selenium has been released.

Jeff Xiong explaing the new features...

(Via Ajaxian Blog.)

I'm especially excited about this release because of the implications with our HostedQA and AutoQ products. The reason is because I started the initial work on the multiWindow mode (though, admittedly, the rest of the Selenium dev team was absolutely required to make it finally work properly) for the very purpose of providing a frameless testing infrastructure for HostedQA.

We've actually been using this multiWindow/frameless mode in our products for a while in our products. The result is that instead of seeing your application inside of an iframe, your app runs in its own window, more accurately reflecting the real world usage.

You can see some example screenshots of what it looks like by checking out some of our opensource projects reports.