Tuesday, November 27, 2012

Testing REST APIs with RESTClient and Selenium IDE

Update: You may also be interested in Testing Express.JS REST APIs with Mocha.

Tools used to test HTTP-based REST APIs include command-line utilities like curl and wget, as well as full-featured test frameworks like Mocha. Another interesting option is RESTClient, a plugin for Firefox that provides a user-friendly interface for testing REST APIs right from your browser.

Since RESTClient is a plugin, its made up of locally stored XML, HTML, CSS, JavaScript and RDF files that Mozilla refers to collectively as "chrome". It turns out that because RESTClient is built mainly with HTML, you can actually use Selenium IDE to control it and run through automated test cases.

Selenium IDE is used to run tests on regular web pages, but I've never seen it used to control another Firefox plugin before.  I gave it a try and discovered that it does this beautifully. Here's a picture of Selenium IDE driving RESTClient.

It's pretty cool to see Selenium IDE driving the RESTClient tool and knocking off all these test cases as it queries the API. I can run through an entire suite of tests, from setup to authentication, creating, retrieving, updating, and deleting resources, to final tear-down. I can drill down into any test cases that are failing and step through them to identify exactly what has gone wrong.  As a bonus, the nicely formatted output can be cut-and-pasted to create some pretty nice looking documentation in my client developer's guide.

Using RESTClient's Favourite Requests

One way to start using Selenium IDE to drive RESTClient is to set up a collection of "Favorite Requests" in RESTClient. Once your favourite requests have been configured, its relatively easy to create test cases in Selenium IDE to drive them.

This is not the best way to combine these tools, however.  It means you'll have to make sure your favourite requests are loaded into RESTClient before starting your Selenium test suite. Your requests will probably be hard-coded so they're not easy to share. And if you do want to run the tests on another system, you'll need to export your RESTClient faves as well as the Selenium tests. 

Driving RESTClient Programmatically

A better way is to drive RESTClient completely programmatically.  Instead of using a list of preconfigured requests in RESTClient, it would be really to just create the requests on-the-fly, programmatically from within your Selenium test suite. And this is completely possible.

Let's run through a few of the steps that you might need to accomplish this.

Selecting the Base URL

When you save your Selenium IDE test suite, the Base URL will define the starting point for your tests. This should be set to chrome://restclient/content/restclient.html

You can also launch RESTClient automatically from the first line of your first test case using the openWindow command:
openWindow | chrome://restclient/content/restclient.html

Making the API Server URL configurable

Depending on who's doing the testing, the server where the API is running will probably be different. If you want other people to be able to run your test suite against different servers you should at least make the hostname semi-configurable. You can do this by storing the hostname in a local variable that gets re-used for subsequent requests, like so:

store | darren.xyzzy.ca:3000 | server
echo | ${server}

That last line is just showing you how to access the stored "server" variable.

Test Preparation

I have a special URI that is available in development mode only, that allows initial set up of test data. This is the Selenese code I use to set up a call to that URI and confirm that test setup is complete:

click | css=i.request-method-icon.icon-chevron-down
click | link=GET
type | id=request-url | https://${server}/test/setup
click | id=request-button
click | link=Response Body 
waitForElementPresent | css=#response-body-raw > pre
waitForTextPresent | test setup complete

Most of those commands were created using the "Record" button in Selenium IDE; then I hand edited a few of them to get the right behaviour.  The most interesting line of the test case above is the "type" command. This enters text into the "request-url" input box, and it uses the ${server} variable to fill in the hostname:port of the API server.

Storing and using variable URL parameters

Just like we did with the "server" variable, you'll probably want to save and re-use other parameters that you get back from your REST API. Here's how you would extract an Account ID from a JSON response, for example after you issue a POST request to create a new account, and store it for use in subsequent requests.

... commands to query the API ...
click | Link=Response Body (Raw)
waitForElementPresent | css=#response-body-raw > pre
verifyTextPresent | Created account
storeText | css=#response-body-raw > pre | response
storeEval | JSON.parse(storedVars['response']).accountId | accountId
echo | ${accountId}

The interesting commands to note here are the "storeText" and "storeEval" commands. The storeText command stores the entire body of the response in a variable called "response".  The next command, storeEval, creates an object from the JSON response by retrieving the response text from storedVars['response'] and passing it into JSON.parse(). Then it selects the accountId property, and stores it in a local variable called, unsurprisingly, "accountId".  If subsequent request URLs are based on the accountId, we can use it just like the server parameter:

type | id=request-url | https://${server}/accounts/${accountId}/messages

If there are other properties of the JSON response body that we want to store for later use, we can use the same technique to get them, too.

Off to the races...

With these basic techniques you should be up and running RESTClient queries with Selenium IDE in no time.  Then you can launch your test suite and go grab a nice cup of coffee while your computer merrily churns out one test case after another and your browser magically performs the steps in sequence.  It's highly entertaining. But it has real practical value, too, as you're sure to find out when developing a client app and you need to troubleshoot the API communication.

Have fun!


Anonymous said...

Another tool that is useful for testing a JSON restful API is www.Quadrillian.com you can run the tests from your browser and give other people access to them.

Anonymous said...

very useful article integrating RESTclient with Selenium(being my favorite)! thanks.

Unknown said...

Great post. Thank you for the useful information. I'm currently having a problem with it though, where I can't get Selenium IDE to open RESTClient. When it hits the open command, I get the error: [error] Unexpected Exception: fileName -> chrome://selenium-ide/content/selenium-core/scripts/selenium-browserbot.js, lineNumber -> 686, columnNumber -> 12

Any tips on how I might solve this problem?


Darren said...

possibly the configuration of selenium IDE or a different path to the REST Client add on on your system

Anonymous said...

why not use soapUI? it is open source and powerful.

Darren said...

Yes, I've used SoapUI and it's quite good. It has a ton of features. RESTClient has a very limited focus by comparison. Some people will like that, or the fact that it runs in the browser and can be driven by Selenium IDE, if they're familiar with that already. I use the Selenium + RESTClient combination once every couple of weeks as a sort of regression / sanity test in my dev environment. For complete automated functional and unit testing I have a rather large Mocha test suite. That gives me both ends of the spectrum - a simplistic graphical tool for developer testing and debugging when I need it, and a server-based, fully automated test suite for build integration.

Anonymous said...

Can you please explain about restapi client along with selenium integration.How to start.I am in the intial phase.do help

Darren said...

Anonymous, to get started with the technique I described in this article, you would need to install the RESTClient and Selenium IDE plugins in Firefox. Learn how to use these tools separately, and then you can try using Selenium IDE to drive the RESTClient.

Bear in mind that this technique is aimed at occasional developer testing, not fully automated integration testing. It's a good way to start learning about it though. Have fun!

Anonymous said...

Thanks for the awesome info!

However, I find that Selenium IDE fails to open chrome://restclient/content/restclient.html if we don't have an empty tab/window already open in Firefox (some Firefox limitation, it seems).

[error] Unexpected Exception: Error: Access to 'chrome://restclient/content/restclient.html' from script denied.

Is there any way around this?

Darren said...

Yes, you may try the openWindow command instead.

Anonymous said...

Thank you, Darren.

Yes, that's what I ended up doing also. openWindow and then focus on the new window seems to work just fine.

I found that if I don't focus on the newly open window, the script fails to find the elements.

Anonymous said...

I have used openWindow command, then selected the new window, but i am still getting the following message returned "[error] Unexpected Exception: Error: Access to 'chrome://restclient/content/restclient.html' from script denied."

Has anyone found an alternative workaround to this at all?

Darren said...

@anonymous unfortunately that stopped working a while ago so you can't open a chrome URL from another plugin. The workaround is just to open up RESTClient in a tab before you run the Selenium-IDE tests.

Tiny Shark said...

Thank you for potentially saving me a TON of hassle. I was struggling to come up with something unnecessarily elegant using Selenium WebDriver and node.js. Looks like this will help solve the problem much more quickly.

Unknown said...

I was looking for a way to mix the benefits of test generation with Selenium Builder/IDE and the benefits of rapid setup/teardown of required data.
Without this you have to waste time using selenium IDE to drive the creation of the data via the web interface or export the code to a framework that allows you to issue REST commands programmatically and then you are back to programming and maintaining code again!.
I cant believe I didnt think of using a REST GUI before and driving that automatically instead!. I am very thankful for the inspiration.
Now all I need is a GUI to modify the flow control so that I don't have to export the code to add if/else/for statements. Selenium Builder have outright stated they dont want to open that "can of worms".

Ankita Somani said...

Hi Can you please explain more how we are going to test this? Do I need to right all the command in selenium IDE aur need to run recored and play functionality

Productivity and Note-taking

I told a friend of mine that I wasn't really happy with the amount of time that gets taken up by Slack and "communication and sched...