Are You Still Not Testing Your Site’s UI Because of Your Database?

by Michael Scepaniak on September 4, 2014 in software development

Nature Mimicking Life

Just like peanut butter plus jelly is a satisfying and delicious combination of two otherwise individual ingredients, CasperJS plus data-mocking is a powerful and effective pairing of two otherwise individual tools. However, whereas bringing peanut butter and jelly together in a sandwich is pretty straight-forward and requires a bare minimum of instructions, getting CasperJS and data-mocking libraries like Sinon.JS and Mockjax to play well together takes some effort. However, the awesomeness that you get when putting CasperJS and these data-mocking libraries together dwarfs the amount of information available explaining exactly how to do that. I’m going to take a stab at fixing that.

Before we get into it, let’s make sure we’re on the same page – especially with regard to when and why you’d want to go the CasperJS plus data-mocking route.

CasperJS, Sinon.JS, and Mockjax

CasperJS is a navigational (click-driven) scripting and testing tool for web browsers. In other words, with it, you can write scripts (in JavaScript) that interact with your web site in the manner a real user would.

Sinon.JS is a library that provides a collection of testing-related constructs (spies, stubs, and mocks) intended to be used with other full-fledged JavaScript-based testing frameworks. In my mind, the coolest part of Sinon.JS (and the only part on which I’m going to focus) is the fake server.

Mockjax is a library that provides the ability to mock or simulate Ajax requests and responses, making a server unnecessary (when testing).

Divided Highway

Browser-based automated testing has been around for a while (exhibit A – Selenium). However, as a developer, I’ve always found such tools lacking. Ignoring their suspect ability to truly handle rich JavaScript-based GUI’s, they require a full-stack web site to walk through. That includes back-end datasources and infrastructure of all stripes. Outside of standing-up and tearing-down all of the dependent datasources with each test run, I’ve never heard of a lean and clean way to resolve the data-fragility issue.

In unit-testing land, mocking-out your datasources or data-access components to create truly data-independent tests is a common practice. But, this is a common developer practice. Data-mocking is not something that I see many test engineers practice or pursue.

And so, for a long time, we’ve seen the evolution of a divided highway. On one side, developers build and tend to their low-level, data-independent unit tests. On the other, testers build and tend to their high-level, browser-based, data-dependent automation tests.

The Power of CasperJS

In recent years, though, tools have come along to bridge that divide. CasperJS is one such tool. When you hand a script to CasperJS, it steps through the script using it’s self-contained invisible web browser. It doesn’t use a web browser installed on your desktop. It is a web browser. And your scripts can access and manipulate the JavaScript runtime of each web page “rendered” in that browser. This is very cool.

But, in order to tap even more coolness, you need more than just CasperJS. Yes, you have access to the JavaScript runtime of each web page, but simply asserting against its state isn’t going to push you much beyond where Selenium will get you. You’ll still be stuck with data dependencies. But, what if we could mock-out the data requests right at the browser level? All of them. Replace all of that fragile, ever-changing, datasource-resident data with robust, developer-controlled, unchanging hard-coded data. But just the data requests – not image requests, script requests, or HTML requests. It’s the dynamic data requests that we want to mock, not the requests for static or nearly-static assets. And, to reiterate, these are data requests made directly from the browser.

Anyway, cut to the chase – we can. What you want to do is toss Sinon.JS and/or Mockjax in there to mock all of your data requests.

For Ajax-Driven Sites

Now, as you might have guessed, this capability begs for a certain sort of web site. For web 1.0 server-generated web pages, the combination of CasperJS plus Sinon.JS and/or Mockjax doesn’t present a game-changing opportunity. However, given a web 2.0 JavaScript-rendered, client-generated, Ajax-heavy single-page application, that same combination of CasperJS plus Sinon.JS and/or Mockjax opens up a largely unexplored world of developer-driven, data-independent automated functional testing.

No longer is the developer’s testing world of rational, self-contained, repeatable, build-integrated tests limited to unit tests. Now, that testing world can be opened-up to a higher level view of the system – to include what the user sees and uses. And yet, we’re still isolating ourselves to an understandable and limited portion of the overall system. When a CasperJS-driven functional test fails, we know that it isn’t because of server-side processing. Our debugging can be restricted to the front-end JavaScript and Ajax-delivered data payloads (typically XML or JSON). And as long as the functional tests reflect- and the server-side code abides by- the contracts represented by that Ajax-delivered data, we’re good.

Just like a well-constructed and well-tended suite of unit tests breeds confidence among developers when it comes time to refactor or modify user-invisible components, a similarly-loved suite of functional tests does the same with respect to those components with which your users are intimately familiar. That’s why you want this ability.

Alternatives

In case you’re wondering, yes, I understand that unit tests do not have to be limited to server-side components. Unit-testing can (and should) be extended to client-side components written in JavaScript. I don’t believe anything I’ve written reflects an opposition to that.

But, front-end unit testing can only take you so far. A significant portion (the majority, I’d say) of that front-end code is impacted by and/or dependent on complicating factors such as the browser runtime, timing issues, the prior sequence of actions taken by the user, rendering of the markup, etc. Being able to account for all of that, in a controlled manner, brings your focus in much closer alignment with that of your users.

I also understand that Capybara provides similar developer-centric abilities (especially when you consider Poltergeist). However, Capybara’s support for JavaScript expressions is, self-admittedly, limited. I have doubts it could handle the amount of mocking of which I’m speaking. (If I’m wrong, please let me know.)

Capybara also has a Ruby on Rails bias, which imparts on it a bias toward full-stack, database-dependent tests. If your site is backed by a clean, unified, rational database, you should be good to go with Capybara. Stand-up and tear-down your test database to your heart’s content. But, for sites backed by a convoluted mess of multiple legacy datasources, the stand-up/tear-down thing just isn’t feasible. If you’re in this boat, the CasperJS plus data-mocking route is probably the route best taken.

In Conclusion

If you’ve got a site where most/all of the data is being delivered straight to the browser via Ajax-delivered payloads, you’re going to want to start functionally-testing it using a combination of CasperJS and data-mocking. Because having the same level of confidence in- and focus on- the high-level interactivity of your GUI that you have always had in/on the lower-level logic of your user-invisible components is just plain powerful – in a way that most benefits your users.

That’s it for the “when” and “why”. Hopefully, you have a site that can benefit from being tested with CasperJS plus data-mocking – and I’ve convinced you that doing so is very much worth your while. In my next article, I’ll set about explaining the “how”.

Read the follow-up to this article – How To Use CasperJS with Mocked Data to Test Your Site’s UI

Mike

Many thanks to Jonathan Julian for reviewing a draft of this article.

Want to be notified when new articles are posted?
Enter your email address:

{ 0 comments… add one now }

Leave a Comment

{ 1 trackback }

Previous post:

Next post:

Member of The Internet Defense League