Introduction
Testing the software we develop has become a very important part of our
daily work. It doesn't matter if you work on Java, C#, PHP or any other
language. I bet you have great tools for testing your code, Java guys
may have Junit, .NET kids may probably use Nunit and some
other PHP developers may work with PHPUnit or something else.
Some weeks ago, I started working on a web app and yes... I had to write
tests for my JavaScript code too, so I started to evaluate some of the
options out there like Jasmine and of course Qunit which is the one that I am going to write about.
Background
Learn by doing is my favorite way to gain knowledge about new
technologies, so I am going to show an end to end example about testing a
simple calculator app.
Calculator
For this simple calculator, we are going to create two files:
- index.html: contains plain HTML code with inputs and a button to calculate results
- calculator.js: contains the logic to perform basic arithmetic calculations
Index.html
<!DOCTYPE html>
<html>
<head>
<title>Calculator</title>
<script type="text/javascript"
src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.1/jquery.min.js"></script>
<script type="text/javascript" src="./calculator.js"></script>
</head>
<body>
<label for="number_a">Number 1:</label>
<input type="text" id="number_a"><br>
<label for="number_b">Number 2:</label>
<input type="text" id="number_b"><br>
<label for="operation">Operation:</label>
<select name="operation" id="operation">
<option value="+">+</option>
<option value="-">-</option>
<option value="*">*</option>
<option value="/">/</option>
</select>
<button onclick="getResult();">Calculate</button><br>
<label for="result">Results:</label>
<input id="result">
<hr>
<div id="validation"></div>
<script type="text/javascript">
function getResult () {
var a = $('#number_a').val();
var b = $('#number_b').val();
var op = $('#operation').val();
var result = calculate(a, b, op);
$('#result').val(result);
}
</script>
</body>
</html>
calculator.js
function add (a, b) {
return a + b;
}
function substract (a, b) {
return a - b;
}
function divide (a, b) {
if(b === 0){
$('#validation').text('Attempt to divide by zero');
return "error";
}
return a / b;
}
function multiply (a, b) {
return a * b;
}
function notSupported () {
$('#validation').text("un-supported operation");
return "error";
}
function validate_input (number) {
var is_valid = true;
number = number.toString().trim();
if(number.length == 0){
$('#validation').text("Blank input found");
is_valid = false;
}
else if(!/^\d+$/.test(number)){
$('#validation').text("Invalid input ("+ number+")");
is_valid = false;
}
return is_valid;
}
function calculate (a, b, op) {
if(!validate_input(a))
return;
if(!validate_input(b))
return;
a = parseInt(a);
b = parseInt(b);
switch(op){
case "+":
return add(a,b);
break;
case "-":
return substract(a,b);
break;
case "*":
return multiply(a,b);
break;
case "/":
return divide(a,b);
break;
default:
return notSupported();
break;
}
}
Calculator should look like this:
I know, I know the UI is ugly but come on guys!!! This is a tip about qunit.
Adding Tests to Our Calculator
At this point our application should work, but now it's time to add
some tests to make sure our app will behave as expected and also to make
sure future changes won't break the application.
We are going to add two more files that will take care of testing our existing app:
- index_test.html: The file you need to open with a browser to execute the tests
- calculator_test.js: contains all the asserts that will be executed against our real application code
index_test.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>
Calculator Tests
</title>
<!--
<script type="text/javascript"
src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.1/jquery.min.js"></script>
<script type="text/javascript"
src="http://code.jquery.com/qunit/qunit-1.12.0.js"></script>
<link rel="stylesheet"
type="text/css" href="http://code.jquery.com/qunit/qunit-1.12.0.css">
<!--
<script type="text/javascript" src="./calculator.js"></script>
<script type="text/javascript" src="./calculator_test.js"></script>
</head>
<body>
<!--
<div id="qunit"></div>
<!--
<div id="qunit-fixture">
<input type="text" id="number_a">
<input type="text" id="number_b">
<select name="operation" id="operation">
<option value="+">+</option>
<option value="-">-</option>
<option value="*">*</option>
<option value="/">/</option>
</select>
<input id="result">
<div id="validation"></div>
</div>
</body>
</html>
qunit div
Qunit will run your tests and print a fancy report inside the div
with the id="qunit"
.
qunit-fixture
Inside
this div
, you can write any HTML code that you want so it's there when
you run the tests. It is useful to execute DOM tests and validate UI
behavior after calling a specific function.
An important thing to
know about this section is that HTML content inside this div
will be
reset before each individual test to ensure that every single test
works fine and avoid dangerous dependencies.
calculator_test.js
test("verifies that calculator can add", function() {
equal(calculate(1,1,"+"), 2);
});
test("verifies that calculator can substract", function() {
equal(calculate(1,1,"-"), 0);
});
test("verifies that calculator can multiply", function() {
equal(calculate(1,1,"*"), 1);
});
test("verifies that calculator can divide", function() {
equal(calculate(1,1,"/"), 1);
});
test("verifies that calculator can handle divide by zero error", function() {
var result = calculate(1,0,"/");
equal(result, "error");
equal($('#validation').text(), 'Attempt to divide by zero');
});
test("verifies that calculator can handle invalid number in first argument", function() {
calculate("invalid input",1,"+");
equal($('#validation').text(), "Invalid input (invalid input)");
});
test("verifies that calculator can handle invalid number in second argument", function() {
calculate(1,"invalid input","+");
equal($('#validation').text(), "Invalid input (invalid input)");
});
test("verifies that calculator can handle empty inputs in first argument", function() {
calculate("",1, "+");
equal($('#validation').text(), "Blank input found");
});
test("verifies that calculator can handle empty inputs in second argument", function() {
calculate(1, "", "+");
equal($('#validation').text(), "Blank input found");
});
test("verifies that calculator can handle invalid operator", function() {
calculate(1, 1, ":)");
equal($('#validation').text(), "un-supported operation");
});
test("verifies that calculator can handle blank operator", function() {
var result = calculate(1, 1, "");
equal(result, "error");
equal($('#validation').text(), "un-supported operation");
});
test("verifies that calculator can handle invalid operators", function() {
var result = calculate(1, 1, ":)");
equal(result, "error");
equal($('#validation').text(), "un-supported operation");
});
Running the Example
In order to run our tests, you just need to open the file index_test.html and you will see something like:
Points of Interest
Qunit is a great JavaScript testing framework, there is a lot more to
learn about it and also about other great frameworks out there.
I just wanted to share some of the basic qunit stuff I have learned so far, I hope you like it.
History