No site found for codelikethis.herokuapp.com; using CodeLikeThis content.

 Slides

No-Frills In-Browser Unit Testing

or, Testing Framework? What Testing Framework?

by Alex Chaffee
Burlington Code Academy

The Best Tests

"The best tests are the ones you actually write." - me

  • Friction is the enemy of flow
  • If you're in the zone, don't get distracted by setup...
  • ...code first, fiddle with your framework later

The Best Test Framework

function assert(value) {
  if (!value) {
    console.log("Failure");
  }
}

All you need is loveassert.

Even better

function assert(value, why) {
  if (value) {
    console.log("Success: " + why);
  } else {
    console.error(new Error("Failure: " + why).stack);
  }
}

console keeps calm and carries on

console.assert(pageNumber >= 0 && pageNumber < numPages,
               'page number should be in range');
  • This built-in console.assert function works fine, but failures do not stop execution
  • a custom assert function lets you "fail fast" which is usually a better idea for unit tests since a failure is more obvious and immediate

Test As You Go - Step 1

Start with the null case.

assert(fancyText('') === '');

function fancyText(s) {
    return '';
}

"Run Test Suite" command: F5 (Refresh)

Test As You Go - Step 2

Write one more test case...

assert(fancyText('') === '');
assert(fancyText('apple') === 'Apple');

...and enough code to make it pass

function fancyText(s) {
    return s[0].toUpperCase() + 
      s.slice(1).toLowerCase();
}

Test As You Go - Step 3

There is no step 3!

Just keep writing tests, and code that satisfies them.

assert(fancyText('pad thai') === 'Pad Thai');
assert(fancyText('state of the union') === 'State of the Union');

Self-Testing Web Sites

screenshot

TAP

tap dancing shoes

  • TAP is a test output format
    • Test Anywhere Protocol
  • tape is a JS implementation of TAP that works in browsers
    • with a little help from browserify :-)
  • tap is a node module that runs on the command line

image from http://hopefuls-rph.tumblr.com/post/88053060131/important-things-to-keep-in-mind-when-portraying-a

Tapped Out

fancy screenshot with tap

Tapped Source: fancy.js

t.equal is tap's assert :

var test = require('tape');
if (window.tapExtension) {
  test = window.tapExtension(test);
}

function fancyText(s) {
  return s[0].toUpperCase() + 
    s.slice(1,s.length).toLowerCase();
}

test('fancy formatter', function(t) {
  t.equal(fancyText(""), "", 
    "should not do anything to an empty string");
  t.equal(fancyText("bob"), "Bob", 
    "should capitalize a single word");
  t.end()
});

Tapped Source: fancy-bundle.js

shell:

npm install --save-dev browserify tape
browserify -o fancy-bundle.js --standalone fancyText fancy.js
  • browserify rewrites & smooshes server-side JS files and libraries into a single file
  • -o fancy-bundle.js means "output all the JS into this one file"
  • --standalone fancyText means "make the fancyText function available to other scripts on the page"

Tapped Source: index.html

<button id="format" onclick="doFormat()">
>> Format >>
</button>
...
<script src="fancy-bundle.js"></script>
<script>
function doFormat() {
  var inputWidget = document.getElementById("input");
  var outputWidget = document.getElementById("output");
  var output = fancyText(inputWidget.value);
  outputWidget.value = output;
}
</script>

Conclusion

  • Testing is delicious, do it all the time
  • Don't get trapped by your tools
  • Do what works and fix it later (or don't)
  • Optional: use a standard format like TAP
    • gives you an upgrade path from in-browser to command-line / continuous-integration / full suite
    • integrates with other tools (like Browser-Tap and tap-spec)
    • might be more familiar to teammates

Links