Testing jQuery With QUnit
One thing that’s always on my mind when I develop applications is testing. How testable is your code? Does it rely on external processes or databases or can you easily mock these objects? Using frameworks such as ASP.NET MVC make your code more readily testable, but how do you test your JavaScript? Like most people I test this by hand, but the other day I stumbled upon jQuery’s QUnit framework. Here’s what the authors say about QUnit:
“QUnit is a powerful, easy-to-use, JavaScript test suite. It's used by the jQuery project to test its code and plugins but is capable of testing any generic JavaScript code (and even capable of testing JavaScript code on the server-side).”
I’ll be doing three examples in this article. The first is a page with manual testing. The second is automated testing but still relying on the UI elements. The third will be automated testing that mocks the UI elements which mean you can test your JavaScript independently of the page. Before we get started, this example uses the latest version of jQuery which is 1.3.2. That can be downloaded from here.
In its simplest form, QUnit contains one or more tests that contains one or more assertions. A test is defined by adding the test function. The assertions can either by one of the following:
-
ok - A boolean assertion, equivalent to JUnit's assertTrue
-
equals - A comparison assertion, equivalent to JUnit's assertEquals
-
same - A deep recursive comparison assertion, working on primitive types, arrays and objects
A simple test could look like this:
test("Sample", function() {
var addThemTogether = (1 + 1);
equals(2, addThemTogether, "Should equal two");
});
The examples in this article will involve creating a page with a text box and a span tag. If the user types in less than seven characters, all is good, but if they type in more than 7 characters, they fail validation. Fairly easy code as I’m focusing on the testing side of things. Okay let’s gets started.
Example 1 – Manual Testing
Open Visual Studio 2008 and create a new Web Application. Add a new web form to the project. Add the following HTML to the page:
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Testing jQuery With QUnit</title>
<script type="text/javascript" language="javascript" src="http://code.jquery.com/jquery-latest.js"></script>
<script type="text/javascript" language="javascript">
$(document).ready(function() {
var txt = $("input[id$=TextBox1]");
var span = $(txt).next();
$(txt).keyup(function() {
var length = $(txt).val().length;
$(span).text(length + " characters long");
$(span).css("background-color", length >= 8 ? "#FF0000" : "#FFFFFF");
});
});
</script>
</head>
<body>
<form id="form1" runat="server">
<asp:TextBox ID="TextBox1" runat="server" />
<span></span>
</form>
</body>
</html>
Run the application to start testing it. If you start typing in the text box, you’ll see the nunber of characters you have typed:
If you type more than 7 characters, you’ll be given visual feedback of the problem:
This testing is good, but we can make it better!
Example 2 – Automated Testing With UI
The same code as above but I’m adding three test functions.
<head runat="server">
<title>Testing jQuery With QUnit</title>
<script type="text/javascript" language="javascript" src="http://code.jquery.com/jquery-latest.js"></script>
<link rel="stylesheet" href="http://github.com/jquery/qunit/raw/master/qunit/qunit.css" type="text/css" media="screen" />
<script type="text/javascript" src="http://github.com/jquery/qunit/raw/master/qunit/qunit.js" language="javascript"></script>
<script type="text/javascript" language="javascript">
$(document).ready(function() {
var txt = $("input[id$=TextBox1]");
var span = $(txt).next();
$(txt).keyup(function() {
var length = $(txt).val().length;
$(span).text(length + " characters long");
$(span).css("background-color", length >= 8 ? "#FF0000" : "#FFFFFF");
});
test("Perform keyup - should fail", function() {
$(txt).val("Hello World!");
$(txt).trigger("keyup");
var color = $(span).css("background-color");
equals(color, "#ff0000", "The background color should be #ff0000");
});
test("Perform keyup - should pass", function() {
$(txt).val("Hello!");
$(txt).trigger("keyup");
var color = $(span).css("background-color");
equals(color, "#ffffff", "The background color should be #ffffff");
});
test("Perform keyup - should fail I think", function() {
$(txt).val("Ok");
$(txt).trigger("keyup");
var color = $(span).css("background-color");
equals(color, "#ff0000", "The background color should be #ff0000");
});
});
</script>
</head>
<body>
<form id="form1" runat="server">
<asp:TextBox ID="TextBox1" runat="server" />
<span></span>
<h1 id="qunit-header">QUnit example</h1>
<ol id="qunit-tests"></ol>
</form>
</body>
</html>
In the code above I have used the same code to connect to the keyup event on the text box. I have added three test functions. To simulate user interaction, each test copies text into the text box and triggers the text box’s keyup event by calling the trigger function. After each keyup event, I am calling the equals function to test the background colour of the text box. That way I’ll know if the result is what I expect.
test("Perform keyup - should fail", function() {
$(txt).val("Hello World!");
$(txt).trigger("keyup");
var color = $(span).css("background-color");
equals(color, "#ff0000", "The background color should be #ff0000");
});
This is a nice way to automate your test. The only thing to improve is making the test independent of the page. In the next example I’ll mock these elements so the JavaScript can be tested independently.
Example 3 – Automated Testing With Mocking Page Elements
This example dynamically mocks the UI elements so the JavaScript can be fully tested with the UI:
<html xmlns="http://www.w3.org/1999/xhtml" >
<head id="Head1" runat="server">
<title>Testing jQuery With QUnit</title>
<script type="text/javascript" language="javascript" src="http://code.jquery.com/jquery-latest.js"></script>
<link rel="stylesheet" href="http://github.com/jquery/qunit/raw/master/qunit/qunit.css" type="text/css" media="screen" />
<script type="text/javascript" src="http://github.com/jquery/qunit/raw/master/qunit/qunit.js" language="javascript"></script>
<script type="text/javascript" language="javascript">
$(document).ready(function() {
$("body").after("<input type=\"text\" id=\"TextBox1\" /><span></span>");
var txt = $("input[id$=TextBox1]");
var span = $(txt).next();
$(txt).live("keyup", function() {
var length = $(txt).val().length;
$(span).text(length + " characters long");
$(span).css("background-color", length >= 8 ? "#FF0000" : "#FFFFFF");
});
test("Perform keyup - should fail", function() {
$(txt).val("Hello World!");
$(txt).trigger("keyup");
var color = $(span).css("background-color");
equals(color, "#ff0000", "The background color should be #ff0000");
});
test("Perform keyup - should pass", function() {
$(txt).val("Hello!");
$(txt).trigger("keyup");
var color = $(span).css("background-color");
equals(color, "#ffffff", "The background color should be #ffffff");
});
test("Perform keyup - should fail I think", function() {
$(txt).val("Ok");
$(txt).trigger("keyup");
var color = $(span).css("background-color");
equals(color, "#ff0000", "The background color should be #ff0000");
});
});
</script>
</head>
<body>
<form id="form1" runat="server">
<h1 id="qunit-header">QUnit example</h1>
<ol id="qunit-tests"></ol>
</form>
</body>
</html>
To fully test this example I have removed the page elements. I’m creating the elements dynamically using jQuery’s after function:
body").after("<input type=\"text\" id=\"TextBox1\" /><span></span>");
Because these elements are added dynamically, the only other change required is to add the live event to the text box. This binds a handler to an event for all current and future matched elements:
$(txt).live("keyup", function() {
var length = $(txt).val().length;
$(span).text(length + " characters long");
$(span).css("background-color", length >= 8 ? "#FF0000" : "#FFFFFF");
});
The rest of the code is the same. I can now test the JavaScript independently:
Since writing this article I am performing this type of testing for most of my critical JavaScript code. This is a fantastic addition for anyone working with jQuery in my opinion. The entire source code of this article can be downloaded over here
This article has been editorially reviewed by Suprotim Agarwal.
C# and .NET have been around for a very long time, but their constant growth means there’s always more to learn.
We at DotNetCurry are very excited to announce The Absolutely Awesome Book on C# and .NET. This is a 500 pages concise technical eBook available in PDF, ePub (iPad), and Mobi (Kindle).
Organized around concepts, this Book aims to provide a concise, yet solid foundation in C# and .NET, covering C# 6.0, C# 7.0 and .NET Core, with chapters on the latest .NET Core 3.0, .NET Standard and C# 8.0 (final release) too. Use these concepts to deepen your existing knowledge of C# and .NET, to have a solid grasp of the latest in C# and .NET OR to crack your next .NET Interview.
Click here to Explore the Table of Contents or Download Sample Chapters!
Was this article worth reading? Share it with fellow developers too. Thanks!
Malcolm Sheridan is a Microsoft awarded MVP in ASP.NET, a Telerik Insider and a regular presenter at conferences and user groups throughout Australia and New Zealand. Being an ASP.NET guy, his focus is on web technologies and has been for the past 10 years. He loves working with ASP.NET MVC these days and also loves getting his hands dirty with jQuery and JavaScript. He also writes technical articles on ASP.NET for SitePoint and other various websites. Follow him on twitter @
malcolmsheridan