Quick Tip: Quick and Easy JavaScript Testing with “Assert”
videos

Quick Tip: Quick and Easy JavaScript Testing with “Assert”

Tutorial Details
  • Subject: JavaScript Testing
  • Difficulty: Beginner - Intermediate
  • Tutorial Format: 9 Minute Screencast
Download Source Files

Years ago, I learned a deceptively simple “assert” function from John Resig, for testing your JavaScript. Amazingly, at barely five or six lines, this code provides a great level of power and control over your code, when testing. I’ll show you how to use it in today’s video quick tip.


Screencast


“Assert” Code

<!DOCTYPE HTML>
<html lang="en-US">
<head>
	<meta charset="UTF-8">
	<title>Easy JavaScript Testing </title>
	<style>
		.pass:before {
			content: 'PASS: ';
			color:  blue;
			font-weight: bold;
		}

		.fail:before {
			content: 'FAIL: ';
			color: red;
			font-weight: bold;

		}
	</style>
</head>
<body>

<ul id="output"></ul>

<script>
var output = document.getElementById('output');

function assert( outcome, description ) {
	var li = document.createElement('li');
	li.className = outcome ? 'pass' : 'fail';
	li.appendChild( document.createTextNode( description ) );

	output.appendChild(li);
};
</script>

That’s all you need for most basic testing! The assert function accepts two parameters:

  1. outcome: A boolean, which references whether your test passed or failed
  2. description: A short description of your test.

The assert function then simply creates a list item, applies a class of either “pass” or “fail,” dependent upon whether your test returned true or false, and then appends the description to the list item. Finally, that block of coded is added to the page. It’s crazy simple, but works perfectly.


Test 1: Your First Example

function add(num1, num2) {
	return num1 + num2;
}

var result = add(5, 20);
assert( result == 24, 'Checking the add function');

// OR
assert( add( 5, 20 ) == 24, 'Checking the add function');
JavaScript Testing Example

Test 2: Closures

var someArray = [1,2,3,4,5],
	len = someArray.length,
	i = 0;

var count = 0;

for ( ; i < len; i++ ) {
	setTimeout(function() {
		assert( count++ === i, 'Checking the value of: ' + i );
	}, i * 300);
}
JavaScript Testing Example

Uh oh! What happened?

This is a common issue, and the answer is to implement a closure, so that we can remember the value of "i." Otherwise, as we noticed above, the code will only render the final value in the sequence: 5.

var someArray = [1,2,3,4,5],
	len = someArray.length,
	i = 0;

var count = 0;

for ( ; i < len; i++ ) (function(i) {
	setTimeout(function() {
		assert( count++ === i, 'Checking the value of: ' + i );
	}, i * 300);
})(i);
JavaScript Testing Example

Conclusion

At first, it might appear as if only huge JavaScript libraries and such require some form of testing; however, that's far from the truth. As we've demonstrated, even a simple function, like Resig's "assert", can potentially save us from hours of debugging! So what do you personally use to test your code?

Add Comment

Discussion 51 Comments

  1. Andrew says:

    I still haven’t found a project that requires any testing bigger than the typical plug-n-chuck.

    • Scriptin says:

      Must be you had never seen a serious projects. It’s fun then you test some application in your favorite browser and when you launch it on the web, it doesn’t work.

      Quick example you write such code:
      > return
      > {
      > someProperty: value
      > }
      It returns nothing (implicit semicolon after ‘return’). When you compress it and launch your project:
      > return{someProperty:value}

      Now it returns an object. Gotcha! Not a very real-world example, but…

  2. edurup says:

    thanks for tips very good

  3. Luis says:

    Nice tut.

    What is that theme for espresso ? can you share it ? :)

  4. Brian Egan says:

    Hey Jeffrey,

    Nice, simple little function! I usually prefer JSpec (http://visionmedia.github.com/jspec/) for my testing suite, because it’s got a really nice command-line interface for quickly getting a new project setup, and because I really like the Behavior Driven Development philosophy in general.

    Brian

    • Jeffrey Way says:
      Author

      Hey Brian – cool. Checking it out now.

    • Rich says:

      I’d recommend checking out Google’s JsTestDriver. It’s similar to jspec in that it runs via the command line, but it has much much better support for testing multiple browsers and continuous integration.

      It’s native assertions are xUnit-like, but they encourage developers to produce their own libraries that work on top of the runner. Last time I checked there are plugins for Qunit and Jasmine (which uses a similar BDD philosophy to jspec).

      Yeti has just been announced by YUI, which seems to follow a similar approach but is at a very early stage – 0.10.

      • Brian Egan says:

        Wow, JSTestDriver is awesome! Although I like the “init” function and jQuery hooks that are provided by JSpec, the Eclipse integration is friggin awesome with JSTestDriver.

        Also, the fact that it’s built to work with a CI tool is really helpful as well. Thanks for the heads up!

      • Rich says:

        Have a look at the Jasmine api, it’s very similar to jspec in lots of ways, but is more javascript like as it doesn’t use a DSL. I personally quite liked that about jspec but I know a lot of people didn’t.

        http://pivotal.github.com/jasmine/

        It also has great support for creating custom assertions to make your tests more readable. Someone’s already created a set of jquery matchers.

        http://github.com/velesin/jasmine-jquery

      • Brian Egan says:

        Thanks again… I’ve checked out Jasmine, but it looked so similar to JSpec that I didn’t give it too much of a look over, as I’m like you — I find the DSL of JSpec very easy to read, and you can always program it the “normal way” as well.

        I’d love a combination of JStestDriver’s awesome command-line integration + Jasmine/JSpec syntax… the readability of the JSTestDriver specs is far worse than JSpec.

        Great links, thanks a ton man!

  5. Jenna Molby says:

    Thanks for the great tips!

  6. João Lopes says:

    Really nice. Thanks once more Jeffrey.
    Keep it up.

  7. Jaspal Singh says:

    Great, Thanks for sharing.

  8. Joao Lopes says:

    I’m sorry for the wrong section, but how do you change the avatar? —>
    I have a premium membership and can’t seem to find where to change it.

  9. Ahmed CZ says:

    Hi Jeff is there any JS noob to ninja tuts?? cuz JS is the next thing for me to learn after CSS HTML and little bit of PHP :)
    and thanks a lot for being a great web developer and tuter :)

  10. khantony says:

    hey jeffrey, check out the loading page of my website. A lot of people think that it is made by using flash or any javascript library. But the thing is it’s made by pure javascript and css. I know you can do it easily using jquery or any other javascript library but the first two page is just raw javascript. :)

  11. scott says:

    Hey Jeffrey,

    Great tutorial as always. Is there a tutorial just on closures? If not, can you please add a closure tutorial?

    Thanks,
    Scott

  12. Bogaert Dieter says:

    I almost always use simple alert box’es to test any variables or functions… I know that it’s probably not the professional way to do this but it seems to work fine for me. Probably for bigger projects this function would be more suited but then again why not just use the console.debug?

    I always wonder what big projects the people here on nettuts are making. personally I hardly ever have to write javascript that’s longer than 300lines of code within 1 project… Can anyone show me some of there bigger projects please? I don’t need to see the code I just wonder what type of things keeps you busy…

    • Rich says:

      Have a look through some of the featured javascript projects on github to get an idea of larger scale projects.

      http://github.com/languages/JavaScript

      In general, I’d say whatever the size of the project testing is a good idea, especially with a dynamic language like javascript because you can’t rely on a compiler to catch your mistakes.

  13. cem says:

    Hi all,thnx for this nice tut. Jeff Can u send your color theme to me ? PLS :) For Netbeans

  14. Tamil Songs says:

    I was searching for it .Found here. thanks.

  15. mimwow says:

    nice tut, thanks :)

  16. kkatusic says:

    Great tut, I always want to build some JS for testing my code, now you give me the way to do this.

    Thx.

  17. w1sh says:

    JS and RegEx confuse the hell out of me. I’ve watched all the screencasts and followed along, but I suppose I don’t learn unless I have some problem to work out.

    Maybe you could start providing ‘Homework’ for us like, “Create a list of animals in an array. Then use assert to test if each is a mammal or not.”

    I might be alone on this.

  18. I use the console in Firebug to do my testing… I add a bunch of console.log ()

  19. someone says:

    Hi Jeff great JS screencast
    i have a simple question to you and it is about CSS ,if i have to divs (the ids is”a b”) and i want to make the div witch id is “b” to turn it back round color to red after i hover the “a”id div
    is there anyway to do this with only CSS ???
    and thanks

    • Jeffrey Way says:
      Author

      So, when you hover over Div A, you want the color of Div B to change? Is that your question? There really isn’t an easy way (if any) to do that with CSS. You can instead do it with JavaScript.

      • someone says:

        Yes that’s exactly what i want, i know i can do it with JS but i really want to do it with CSS :(
        i hope CSS3 make this happen easily, and if i can not do it with CSS3 i Hope to do it with CSS4 :) :) :)
        thanks Jeffrey that was helpful even if you didn’t give me a way to do it with CSS
        thanks again XD :)

      • Jeffrey Way says:
        Author

        There are tricks you can use, where, for example, Div B is a child of Div A. In those cases, you can hack a CSS method. If you need JavaScript, use something like:

        <!DOCTYPE HTML>
        <html lang="en-US">
        <head>
        	<meta charset="UTF-8">
        	<title></title>
        	<style>
        		div {
        			cursor:  pointer;
        		}
        		.hover {
        			color:  red;
        		}
        	</style>
        </head>
        <body>
        	<div id="a">A</div>
        	<div id="b">B</div>
        
        	<script>
        		(function() {
        			var a = document.getElementById('a');
        
        			a.onmouseover = function() {
        				var elem = next( this );
        				elem.className = 'hover';
        
        				// OR document.getElementById('b').className = 'hover';
        			};
        
        			a.onmouseout = function() {
        				var elem = next ( this );
        				elem.className = '';
        
        				// OR document.getElementById('b').className = '';
        			};
        
        			// Find next sibling that isn't
        			// a text node.
        			var next = function( elem ) {
        				do {
        					elem = elem.nextSibling;
        				} while ( elem.nodeType !== 1 );
        				return elem;
        			};	
        
        		})();
        	</script>
        
        </body>
        </html>
        
      • Jeffrey Way says:
        Author

        Right – like I said, there are “hacks” you can use — but most of the time, they aren’t real-world applicable, and can force you into writing poor markup.

      • w1sh says:

        JW. That markup is horrible. :)

      • someone says:

        @w1sh thanks that was helpful but i only hope to do it without using a child div
        @Jeffery thanks another time for helping me, well i know the child trick, but i only hoped that i can do it without using this trick because if i used a position:relative on the parent div the child div wont display :(
        i hope W3 develop CSS to be some thing like this :
        #a:hover{
        background-color: blue
        #b{
        background-color: red
        }
        }

        and that code will make #a blue when hovering on it, and make #b red when hovering on #a,what do you think isn’t this such a great idea :)
        i really hope W3 make it that will make CSS more flexible and easy :)
        thanks again w1sh and JW that was really helpful

    • Nikolai says:

      Hello there :)
      You don’t really need css3 to do this, try this:

      #a, #b {
      width: 100px;
      height: 100px;
      background-color: black;
      cursor: pointer;
      color: white;
      font: bold 20px/100px Arial;
      text-align:center;
      }
      #a {
      position:relative;
      }
      #b {
      position:absolute;
      top: 0;
      left: 120px
      }
      #a:hover #b {
      background-color: red;
      }
      #a:hover #b:hover {
      background-color: black;
      }

      A
      B

      • Niolai says:

        my markup isn’t there :),
        but the idea is you put div#b into div#a, and it should do it

      • someone says:

        Hi Nikolai,
        that well work but the html need to be like this :

        and that’s mean that “b” is “a”child and i don’t want that
        double check the previous comments and you well get it ^_^
        Note:
        #a:hover #b:hover {
        background-color: black;
        }
        is useless because you can’t hover on both of “a” and “b” in the same time (you may do it if you have a parent div for both “a” and “b” and sitting it position for relative, but seems that you didn’t do that XD) thanks anyway :)

  20. w1sh says:

    Totally irrelevant to this post but I thought everyone should know what’s going on in my life right now so…

    I ffffinally splurged a whooping $9 on a Premium membership.

    There is a ton of content there. Like.. it’s reeeally nice. Instantly have access to hundreds upon hundreds of tutorials and screencasts… I don’t even… so… jeez.

    Few things I wish were different:
    - Videos and tut .zips had some sort of naming convention. screencast.flv and tut_fe2.pocketemail.zip make it hard to just download everything and shove it in a folder for later viewing.
    - Wish there was a way to just download everything in the above mentioned formatted way, in one huge .zip that was broken up into 3 or 4 .zips.

    Valid complaint:
    - When I view the videos in your inline FlowPlayer, it automatically expands the video to a fixed height that is taller than my viewport, and I’m on 1440×900! This denies me use of any controls and cuts off a portion of the video. Something needs to be fixed with that.

    Overall opinion:
    I can’t believe how much stuff is on there. A tut or two every week really adds up. There are literally hundreds of tutorials and screencasts.

    Thanks a lot guys for making Nettuts.

    Oh, and MOAR PYTHON TOOTS!!!

  21. nice tutorial, I’ve been looking for something like this forever

  22. Pipps says:

    This is great, I like firebug but sometimes console.log doesn’t seem to work for me. This seems much nicer than using alerts, which is what I would normally do.

    In your example, I understood why it was necessary to pass “i” to the function you created at the end, but why is “(i)” also needed at the end of the loop? I’m not familiar with using a function and a for loop this way, am I missing something?

Add a Comment

To add a code snippet to your comment, please wrap your code like so: <pre name="code" class="html">YOUR CODE</pre>. You can replace the class name with "js," "css," "sql," or "php." If there are any "<" or ">" within your code, please search and replace them with: &lt; and &gt; respectively.