Recently, Dave Shea lamented that ” there are no automated tools to validate Javascript. ” This is true, but such a tool is well within reach. And with a little bit of work, you can have your own.
Every person poking around with JavaScript needs to be aware of the fine work of Douglass Crockford , JavaScript guru of gurus. On his site he has, in addition to very nice articles about Object-Oriented JavaScript, remedial JavaScript, and the very useful JavaScript Object Notation (JSON), a tool of alarming genius called jsLint . He describes it as follows:
When C was a young programming language, there were several common programming errors that were not caught by the primitive compilers, so an accessory program called
lintwas developed which would scan a source file, looking for problems. […] jslint takes a JavaScript source and scans it. If it finds a problem, it returns a message describing the problem and an approximate location within the source. The problem is not necessarily an error, although it often is. jslint looks at some style conventions as well as structural problems. It does not prove that your program is correct. It just provides another set of eyes to help spot problems.
This is great, super helpful. And it is written in JavaScript! Kick it around a bit; throw your favorite scripts at it and let it tell you just what an amateur you are. But at best it is a semi-automatic syntax checker; you have to paste in the script and pull the trigger. By bring in yet another excellent and largely underutilized JavaScript tool, we can take this “automated JavaScript validation tool” idea the rest of the way.
Somewhat less easy to use, but equally useful, is jsUnit , Edward Hieatt ’s JavaScript port of the popular Java unit testing framework jUnit.
What? You don’t unit test your JavaScript? It is true that in most projects you can get away without, but as I work on more complex things (especially when I’m validating a lot of user input, or localizing numbers and dates [more about this later]) I’m finding it increasingly useful. As my scripts become more interdependent it is ever more important to regression test (Did this change I just made break anything that depends on this bit of script?).
I won’t go into how to set up and use jsUnit, as it can seem a bit fiddly and installation-dependent at first (it isn’t so bad, but the documentation does nearly zero handholding). But jsUnit, in that it can invoke each of many test scripts in a test page and reports the results, can bring us much closer to the holy grail of automated syntax checking. In any case I’m going to blaze along with minimal handholding as if you are able to follow along at home. Other things we’ll need: a local copy of jsLint, a way of loading JavaScript files as strings, a test page that can do that for us, and a test function that asserts that the script we just loaded passes jsLint.
Douglass Crockford freely provides a copy of his jsLint parser at
http://www.crockford.com/javascript/fulljslint.js
. The
jslint
object that his script creates takes some booleans for three important options, accepts a string when called as a method, generates a report, and slaps the report into
jslint.report
. We’ll need to add a little helper function to our test page that sets these options and returns the report) that he makes available, like so:
1 2 3 4 5 6 7 | function go(str) { jslint.laxLineEnd=!lintOptions.requireStrictLineEndings; jslint.plusplus=lintOptions.dislikePreAndPostfixIncrements; jslint.jscript=lintOptions.tolerateJscript; jslint(str); return jslint.report(); } |
Note that I’m planning to use the properties of a
lintOptions
object to carry the options.
Just a moment ago I wrote, “a way of loading JavaScript files as strings.” This is a problem because (as far as I know) client-side JavaScript doesn’t open files, and jsUnit runs in a browser. We can, however, use a server-side include (or a JSP include, or a PHP include, or other server-side means) to write the JavaScript file of our choice into a textarea and get it as a string that way. Our test page will need to load the file into the textarea, get the contents, pass them to the helper function, and assert that the jslint report is OK.
A jsUnit test page is a rudimentary HTML document with a few important pieces:
- a script tag including jsUnitCore.js
- a script tag including the script being tested
- test functions, which interact with the script being tested
- optional HTML elements that are convenient to the testing of the script being tested
A test page can also contain
setUp()
and
tearDown()
functions that are run before and after (respectively) each test function. In our case, we’ll need to use
setUp()
to set the lint options and get the contents of the textarea, like so:
1 2 3 4 5 6 7 8 | function setUp() { lintOptions = { requireStrictLineEndings : true, dislikePreAndPostfixIncrements : false, tolerateJscript : false }; lintSrc = lintSrcElement.value; } |
We’ll also need to write a test function that makes use of all of this:
1 2 3 4 5 6 7 8 9 10 11 | function testRunJsLint() { var result = go(lintSrc); if (result.substr(0,2)!='ok') { result=result.entityify(); lintPass = false; } else { lintPass = true; } assert(result, lintPass); } |
Ideally you can infer from the code snippets above what HTML is required in the test page. I recognize that this post is short on handholding; I plan to continue to polish it.