I would like to hear other people’s opinion on what to unit test in JavaScript. I’ve been thinking about it and experimenting and let me present what seems to me the right thing. First of all, in order to be able to unit test your production code you need to divide the productin code into three layers: (1) DOM/jQuery, (2) Logic, and (3) AJAX. Refer to the attached image.
The Logic layer sits between the DOM/jQuery layer and the AJAX layer, that is, the DOM/jQuery layer is not tied to the AJAX layer. So, in my opinion the only layer that should be unit tested is the Logic. Writing unit tests should be easy, otherwise programmers will not write them. What is the use of writing unit tests for the DOM/jQuery layer – ok, you’ve added an li element to an ul element, why do I need to assert that, there should be no if statements there. About the AJAX layer, what’s there to assert…the URL that was used was “blah”, I know it was “blah”. Whatever the data that was obtained in the AJAX layer should be given to the Logic layer. Now, the Logic layer is a different story, for example, in a unit test it can be given data that suppossedly came from an AJAX call, and use a mock DOM/jQuery layer to verify that the data was displayed correctly. Let me know what you think.
1
Why not Ajax?
That strikes me as a great place to unit test. As a point of entry/egress in and out of a given domain, that’s one choke point where it’s nice to know your code is going to handle bad data in the best possible way. Ideally, a network hiccup or data problem won’t throw the kinds of exceptions that break all the code on your page and give user feedback as appropriate. But I would emphasize live-logging validation here as a strategy first.
Semi-Agreed on the DOM Interface
All you can test for is whether something works when all the HTML is correct. You really can’t make assumptions about what your code should do when the HTML is broken because validating for every little DOM operation is way too expensive. Also, breakage is typically so obvious it’s a wasted effort anyway. It’s better to simply have test pages full of in-production variations on fully functional widgets with automated activation of their various features. If that counts as unit testing then I guess I disagree.
Agreed on Unit Testing Data-Juggling/Data-Formatting/Logic
This is definitely the interior layer where it might make the most sense to focus on some sort of a testing strategy.
But Still Not 100% Sold on Extensive Client-Side Web Unit Testing
I’m on the fence about it primarily because it’s obscenely easy to test your code before committing it and issues are typically highly visible on the client-side. If you don’t get immediate visual cues you’ll see problems in the console.
IMO, the critical thing is to focus on testing for how your code reacts to bad stuff from vectors you don’t control like what’s coming in from Ajax or JSON dropped in by the server on page load. Regression issues of the whack-a-mole bug variety where one “fix” breaks something elsewhere are something any client-side web developer should be loathe to ever allow into their code in the first place by maintaining clean separations of concerns and hand-testing the crap out of all their work in every browser supported before committing. That takes time and I’d argue time is better spent avoiding the problem in the first place than testing to see if you failed to avoid it. JS’s flexibility makes it so easy to reduce complexity that I would tend to argue for automated testing only at key bottlenecks and necessarily highly complex data-handling.
In recent work with a very messy codebase that has mostly not been touched by client-side dev hands the most critical debug time-saver IMO, is first establishing a way to very rapidly rule out whether it actually is a client-side problem. If you’re validating all data to and from the server and logging issues (silently in production of course) as they happen, this can be a matter of seconds rather than hours. But that’s not unit testing of course, it’s validation, which I would argue is more important than unit testing when you can run and diagnose your code in a live environment as easily as we can with client-side web code.
Consider a Mixed Strategy
So I’m not saying it’s always a bad idea. I just think that with JavaScript being good at what it’s very good at and with development on the client-side web being the unique animal that it is, it’s better to put time into avoiding the kinds of needless complexity that makes one worry about regression issues in the first place and focus more on aiding rapid diagnosis of problems in your running environment. Widget test-pages are great. Validation of data ingress/egress and perhaps unit testing of failure handling is great. And when dealing with high complexity for data handling/formatting, unit testing could potentially also be great. But 100% unit testing coverage of any given layer, I would argue, is time/effort that might be better focused elsewhere for a typical client-side web app.
2
At a minimum test at the interfaces. On your diagram you should have two arrows, one at jQuery|Logic and one at Logic|Ajax.
Work your way inward as the design solidifies. You don’t want to spend alot of time unit testing some piece of internal logic that will only get ripped out and replaced by something else later.
Of course, as you granulate your design, the Logic box will look like lots of little boxes or stripes. Again test at the interfaces between the components.