Posts tagged TDD

The video introduces isomorphic applications and their unique benefits and challenges, and then jumps straight into the architecture of React/Redux applications from a testability perspective. Hany follows test-driven development (TDD) principles while building a real-world example–a search application–to demonstrate effective end-to-end testing. Popular testing tools for React/Redux applications, including Enzyme, SinonJS, Expect, Nock and Mountebank, are highlighted.

The need for building highly performant and maintainable user interfaces is now greater than ever. React, a library designed and developed by Facebook, can solve many of the existing problems users face today–including poor browser performance while handling dynamic interactions with high loads of data. React also solves a lot of challenges for front-end developers. Due to its popularity, other supporting frameworks, such as Redux, came into the picture to make applications more predictable, testable, and easier to debug. However, they come with a different approach to front-end development and testing.

Testability is key to maintaining the quality of any application while building confidence in the code as developers refactor their work. Writing proper tests can be a lengthy process, especially for newer frameworks such as React/Redux. Test-Driven Development for React/Redux in an Isomorphic Application LiveLessons quickly gets you up-to-speed on when to build isomorphic applications, how to effectively test your React and Redux code, and how to confidently refactor code while ensuring that business functionality is maintained.

The hardest part about writing testable JavaScript code is actually re-imagining your front-end as isolated modules, where the reality is, the pieces of the UI are intertwined. Can a button or hyperlink be a module? What about a content section on the page? It’s not always clear what to consider “self-contained” on a webpage of related content. Though it might be easier in some cases than others.

For instance, a tab panel widget is easy to unit test. For one, it’s an established pattern, but more importantly, it doesn’t interact with other content on the page. It’s truly self-contained. But how often do you need to write your own implementation of tab panels when there is no shortage of UI frameworks? What developers often focus on is business logic. That’s what I intend to cover in this article by looking at a real example from an application I’m working on at OCLC.

Problem

To give a little bit of context, I’m working on a search engine application for library catalogs. Though the main feature to be covered here is that, when users search for a book, let’s say “The Hunger Games,” we would like to know whether a “full” or “partial” preview of the book is available on Google. If so, we should display it. This is an example of book preview for The Hunger Games on Google.

Identifying Functionality

As a first step, we need to identify functionality at a very high level:

Determine book preview availability in Google’s index by passing ISBNs as the key(s) to Google. Google Preview’s Dynamic Links API is needed.

Given that a book preview exists, render the internationalized/localized Google preview image button based on users’ current locale (Google dictates that you use their image button for branding purposes). See image below.

The button can then link to Google for the preview or embed the preview within the current page.

Design and Solution

At this point, we’re at a good place to start designing. So, what should be modularized here? The button? Maybe. But that’s not as important as the call to determine book preview availability. That’s the part that can be truly modular and “self-contained.” That’s the part the can be portable from one application to the next. So, this module is going to be only responsible for the data; the request and response. And while Google suggests injecting a script tag dynamically into the DOM to avoid cross-origin requests, we can use JSONP as that’s exactly what it covers.

Let’s call our module: GooglePreviewAvailability

We will need the following properties on our module:

_locale: the locale to internationalize the image button provided by Google

_url: the JSONP url with the callback parameter

We will also need the following public function:

load([string] ISBNs, [function] callbackFn): passes a list of comma-separated isbn numbers to the call, and a callback function to be executed upon a successful google preview availability response. The callback function parameter allows the caller/client great flexibility as to what to do with the response. In other words, the caller can either attach the response to a UI element or maybe embed book preview (if it’s available) within the same page.

Identifying Testability

At this point, we haven’t written any code. We just have a boilerplate/skeleton of our module. We just need to identify what we’ll test. As a developer, you can test the heck out of your code all day long, but without knowing how to structure your test code, your tests aren’t really helping you. Martin Fowler addresses this in his article on async testing in JavaScript.

I usually structure my tests in similar fashion. I look for the following things to test:

Object creation & default values:
Verify the object is created successfully and the proper defaults are set.

Request, Response, Callbacks:If requests (JSONP in our case) are made or callbacks are provided, verify a successful request along with the parameters sent, the response and whether it was valid and, last but not least, successful callbacks.

Code and Tests

Here is a snippet of our module which only includes the constructor. Note that this relies on John Resig’s implementation of simple inheritance in JavaScript in addition to some other home-grown JS modules:

Now that we’ve validated our parameters, we need to test the request, response and callback function. Note that there is also a little bit of validation here for when to make the call. If you look back at the module, you’ll see that the JSONP call isn’t made if the isbn numbers parameter is the empty string.

google-preview-availability-tests.js – verify the request isn’t made for empty isbn

You will also notice that we only care about two cases in the response; (1) “full” preview and (2) “partial” preview. Google will send back “no view” in the “preview” response field when a book isn’t available for preview. At this point, we’re to do nothing. Here’s how we validate that in Jasmine.

NOTE: The test code contains a bit of duplication for the sake of clarity in this blog post.

Wrap up

The point that I (hopefully) illustrated is that we didn’t necessarily have to tie any specific UI component to a particular module. However, we’ve taken a very specific case of making requests and receiving responses very generic, reusable, portable and, most importantly, testable. Now clients of this feature can call this module and pass in their code for what to do with the button. In our case, we’re making the preview_url to the google image button as an href. Here is an example of a caller of this module:

This code could have utilized the same GooglePreviewAvailability module in order to embed a preview panel within the webpage as opposed to linking directly to Google. That’s the flexibility we get when we think about testability. Enjoy!