Press "Enter" to skip to content

Offline techniques for clean JavaScript code

If you are like like me, you find yourself occasionally offline without the ability to connect your laptop to the Internet. I’ve developed a technique to create quality Test Driven Development (TDD) style code while being disconnected.

Before we start, download the code from GitHub.

Let’s dig into the code by starting with the run.html HTML file:

I’ve adapted the above HTML file from the example supplied by the Official QUnit site.[1] The dynamic URLs (lines 6 and 11) have been modified to use a locally downloaded version of QUnit’s library. For those of you who have not used QUnit before, it is an xUnit style JavaScript library developed by the JQuery team, hence the Q in the name. For more detail, read about QUnit.

Line 12 of run.html references a local file named sut.js. SUT in unit testing stands for System Under Test. It is a term from the book “The Art of Unit Testing with examples in C# (second edition)”. While the book is intended for C# developers, many of the concepts are agnostic of programming language.

More simply, the term SUT means the “thing” (e.g., object, module, etc), that you’re currently testing. If you don’t like the name sut.js, an alternative would be production.js (meaning the code to be deployed to a production site).

Line 13 of run.html references a local file named tests.js. These are the JavaScript tests that QUnit runs when run.html is opened in the browser. Alternatively to calling this tests.js I should mention a naming convention often used by developers.[2]

So let’s get this puppy running so that you can see how it works in action. Assuming that you’ve already downloaded the code from GitHub, double click on the run.html file as shown below.


You will now see the following output in your browser:

The first question you may have is where the “1. Example tests: add_Input3Plus2_Returns5” is coming from. To answer this, open the tests.js file in your favorite text editor as shown below:

Toward the middle of the file, you’ll see some code that will look like the code below:

This is an example of the QUnit.test method. The first string ‘add_Input3Plus2_Returns5’ defines the name of the test.

There are a couple of standard conventions that I’ve used here that should be defined before going any further. For example, the methodUnderTest_Condition_ExpectedBehavior naming convention.

In this example, the methodUnderTest is the “add” method of the “Example” object in the sut.js file. The Condition is the Input3Plus2 wording meaning that the input values are 3 + 2. And lastly, the ExpectedBehavior is the Returns5 wording meaning that that the add method will return the value 5.

Another convention that you can see here is the Arrange, Act, Assert (AAA) pattern. This pattern is used to ARRANGE variables and preconditions, ACT (i.e., execute) the test itself, and then ASSERT (i.e., ensure) that the expected post-conditions are not violated.

Regarding the ASSERT section, I’m using the QUnit strictEqual method, which checks for strict equivalence. By strict equivalence, I mean that not only do the variables “expected” and “result” need to have the same values, but the types must also be the same type. To further explain this, in JavaScript “5”==5 is truthy because the integer type with value 5 is coerced to be a string with value “5”. Thus by using strict equivalence you can catch this kind of issue with your tests.

As a quick exercise to see this in action, replace the following code in the ‘add_Inputs3Plus2_Returns5’ test:

Notice that one of the advantages of this offline technique is that after changing and saving the “tests.js” file, you can simply refresh your browser to execute all these tests again. Alternatively, you can use the “Rerun” link to rerun just an individual unit test.[3]

After completing the above replacement, you should see the following error show up in the browser.
This means that the first ‘Assert equal’ ran using the QUnit assert equal method. But it ran fat, dumb, and happy. It coerced the types in order to get equality and reported a green status signifying that everything is good (i.e., no assertion).

The second assertion correctly failed with the strictEqual method and states that it expected 5 but got “5”. It then gives you a visual difference and the line number and file where the issue happened. A quick note, it’s considered bad form to assert more than one expected behavior per test. This is just an example to contrast the two methods.

To read more about the other assertion methods beyond just the strictEqual and equal methods click this link.

You may have also noticed the Object.<anonymous> in the output image above. If you’re curious, this refers to the fact that you’re using an anonymous method definition when defining the ‘add_Input3Plus2_Returns5’ test. If you’d like to get your hands dirty with the tests again, try changing the anonymous method definition to a named method definition instead:

You’ll see “fred” show up instead of :

My next blog post will discuss the second test (shown below) in the “tests.js” file. To whet your whistle, this is a technique discussed in detail in the JavaScript Patterns book. You can use it for defensively programming JavaScript Object constructors against missing new operators in the Object instantiation (see the missing “new” operator in line 5 below).

The only other piece of “tests.js” that has not yet been described is the QUnit.module method. The setup property enables you to setup preconditions that will be true for all tests in the module. The teardown property will reset, deallocate, etc objects for all the tests in module so that the next test is not affected by the previous test.

In the example shown below, you can see that I’m executing a console.log to print out ‘Starting test…’ before each test and ‘…Completed test!’ at the end of each test. This demonstrates that the sequence of events is: setup, test, teardown.

Now you should have an understanding of how to develop production JavaScript and TDD Unit tests while disconnected to the Internet. If you have any questions, please feel free to post them in the comments block below.


Tangent 1: Node.js:
Originally I was using Node.js to develop production quality JavaScript code. Node.js worked nicely but I am a big believer that a developer should develop and debug in the same type of environment that the production code will run in. This is especially true of my embedded software projects but is also true of JavaScript as well.
Node.js works well because the Native ECMAScript objects are the same across all JavaScript implementations. Node.js being a server-side technology, however, means that Host objects can differ from the browser-based client-side environments.
In an ideal world most of the Host objects (such as window) should be avoided or abstracted away to make your JavaScript truly portable. I think that the biggest reason that I like this offline technique over using Node.js is that this technique allows me to use the same tools that I would debug production issues with, such as the interactive debugger in Google Chrome’s Developer Tools.

Tangent 2: Naming conventions:
Using this convention, let’s say that you’re developing a production JavaScript object whose constructor is named MyObject. The filename of the production object would be named MyObject.js.The tests for this object would be contained in a separate directory that mimics the production folder structure. The filename for the tests would then be called, for example MyObjectTests.js to signify that the purpose of the file is to test the MyObject object as the SUT.For the offline technique, I’m using the sut.js and tests.js names rather than the convention I describe above so that I have a quick unchanging template. This keeps the SUT and tests separate so that I can later rename and move the individual files into version control when I’m back online.

Tangent 3: Google Chrome Developer Tools:
I will blog instructions in the future on how to use Google Chrome’s Developer Tools in conjunction with this offline technique. You will be able to edit, debug, and save JavaScript directly in Chrome without using an external text editor/IDE. It really saves a lot of time and feels more natural because you’re testing directly in the browser.

Be First to Comment

Leave a Reply

Your email address will not be published. Required fields are marked *