OVERVIEW
In software engineering, collaboration is key. Therefore, it is important to integrate collaboration into all aspects of the engineering processes during development.
In light of it, Behavior-Driven Development (BDD) is a process that encourages collaboration among developers, quality assurance experts, and customer representatives in a software project.
To achieve effective collaboration amongst development teams, BDD combines general techniques and principles of Test-Driven Development (TDD) to provide collaborative tools for software teams.
Therefore, since BDD is an extension of TDD, it requires tools that integrate the principles of BDD and the extensions of Test-Driven Development. That's exactly where Jasmine – the open-source JavaScript-based BDD testing framework comes in.
In this Jasmine unit testing tutorial, we will explain the basics of testing with Jasmine and discuss different Jasmine and testing concepts such as test suites, spies, specifications, expectations, matchers, etc. Additionally, you'll learn from a practical example of writing unit tests with Jasmine to check bugs in your code.
So, let’s get started!
Jasmine is a popular open-source JavaScript-based testing framework for unit testing JavaScript applications. It follows a BDD procedure to ensure that each line of JavaScript code is appropriately tested.
In addition, Jasmine has over 15.5k stars and is used by over 2.6m projects on GitHub. It has a strong community of developers, and great documentation is available if you get stuck.
In the next section of this Jasmine unit testing tutorial, we will explore what Jasmine is used for and what type of project you can integrate with Jasmine. You can learn more about the Jasmine framework through this blog on Jest vs Mocha vs Jasmine.
With over 2.6m projects using Jasmine as their collaborative testing framework. It is clear that software testing remains vital, and Jasmine has gained industry recognition.
In 2000, JsUnit was the available automation testing framework for JavaScript applications, and later, this framework got upgraded to Jasmine.
Angular developers favor Jasmine because it is included natively in Angular projects. In addition, the key value proposition of Jasmine is that it's easy to set up and write tests.
In the next section of this Jasmine unit testing tutorial, we will elucidate how to use Jasmine. We will discuss the different ways to install, configure, and start using Jasmine to perform your automated testing and BDD.
Accelerate Jasmine automation testing over 3000+ environments. Try LambdaTest Now!
Now that the fundamentals are out let's get our hands dirty. Let's see how to go from zero to hero with Jasmine unit testing.
There are different ways to install, configure and start using Jasmine in your projects. Let's explore these different ways.
Jasmine is available in different programming languages and can be used to test different microservices written in different languages.
However, this Jasmine unit testing tutorial will focus on JavaScript and explore how to perform Selenium automation testing with Jasmine framework.
The standalone distribution allows you to run your specs in a web browser. You can start by downloading the latest version from the release page and extracting the file to your preferred location inside the project you want to test.
The extracted file will contain many default files, folders, and sample test cases to get you started:
The code snippet below is the default content of the SpecRunner.html file:.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Jasmine Spec Runner v3.2.1</title>
<link rel="shortcut icon" type="image/png" href="lib/jasmine-3.2.1/jasmine_favicon.png">
<link rel="stylesheet" href="lib/jasmine-3.2.1/jasmine.css">
<script src="lib/jasmine-3.2.1/jasmine.js"></script>
<script src="lib/jasmine-3.2.1/jasmine-html.js"></script>
<script src="lib/jasmine-3.2.1/boot.js"></script>
<!-- include source files here... -->
<script src="src/Player.js"></script>
<script src="src/Song.js"></script>
<!-- include spec files here... -->
<script src="spec/SpecHelper.js"></script>
<script src="spec/PlayerSpec.js"></script>
</head>
<body>
</body>
</html>
Most importantly, you can change the source location of the /src and /spec folders to locate your actual source and test files.
You can use Jasmine as a library in your project. The `jasmine` module is a command line interface and code for running Jasmine specs with Node.js.
var Jasmine = require('jasmine');
var jasmine = new Jasmine();
jasmine.loadConfigFile('spec/support/jasmine.json');
jasmine.execute();
The configuration can be loaded from any location. Also, you can create a custom configuration to fix your project requirements.
{
"spec_dir": "spec",
"spec_files": [
"**/*[sS]pec.?(m)js"
],
"helpers": [
"helpers/**/*.?(m)js"
],
"env": {
"stopSpecOnExpectationFailure": false,
"random": true
}
}
Below is the list of some of the important configurations inside the `jasmine.json` configuration file.
You can find more CLI options from the official documentation when running the Jasmine commands. Below are some of the useful CLI options:
Set Jasmine as your test script in your package.json file:
"scripts": { "test": "jasmine" }You can also use Jasmine in the browser, if you're working on the frontend, you can install Jasmine into your project and test out your frontend projects.
In this section of this Jasmine unit testing tutorial, we explore different methods to set up Jasmine for your testing needs. In the next section of this Jasmine unit testing tutorial, we will understand the Jasmine testing framework deeper and explore the general keywords used in Jasmine and software testing.
This section will explore the basic elements of Jasmine testing, such as suites, specs, expectations, matchers, spies, etc.
We will start by creating a demo project that will enable us to practically learn and understand the different elements used in Jasmine testing.
function fibonacci(num, memo) {
memo = memo || {};
if (memo[num]) return memo[num];
if (num <= 1) return 1;
return (memo[num] = fibonacci(num - 1, memo) + fibonacci(num - 2, memo));
}
module.exports = {
fibonacci: fibonacci,
}
The snippet above is a simple Fibonacci series computation. We will use it to understand the different elements of Jasmine testing.
A suite is a group of specs or test cases. It's used to test a group of features or behavior of the JavaScript code. It's usually encapsulated by an object/class or a function. You can define a suite of test cases using the `describe` block.
The `describe` block takes two required parameters – a string for the suite name and a function that implements the actual code of the test suite.
Let's explore an example of our first Jasmine test suite:
describe('Test Helpers', function () {
/**
* Add all your related test cases here
*
*/
});
With the `describe` block, you can group related blocks for better organizing and accurately describing test cases.
describe('Test Helpers', function () {
/**
* Add all your related test cases here
*
*/
});
describe('Test Authentication', function () {
/**
* Add all your related test cases here
*
*/
});
Excluding a suite can be done by adding `x` to the `describe` function for instance `xdiscribe()`. This will temporarily disable a suite making all the specs within the disabled `describe` block marked as pending and not executed in the report.
A spec declares a specific test that belongs to a test suite. This is achieved by calling the Jasmine global function `it()`, which takes two parameters. The spec title and a function that implements the actual test case.
A spec may contain one or more expectations used to determine the correctness of the test. Each expectation is simply an assertion that can return true or false. When an expectation returns true, the spec is passed but fails when the expectation returns false.
Here is how to declare a spec:
describe('Test Helpers', function () {
it('should calculate Fibonacci series', function () {
/*...*/
});
});
We can also exclude individual specs from execution by adding x to the xit() function. Jasmine will ignore this particular test and also ignore reporting it.
Expectations are created using the expect function. They take a value called the actual. The actual value is compared with a matcher function and returns the falsity or truthy of the comparison.
You can chain many expect() functions with multiple matchers to obtain different results from your test cases.
Here is a simple example of using the except function for comparison:
describe('Test Helpers', function () {
it('should calculate Fibonacci series', function () {
const fib = Fibonnaci(4);
expect(fib).toEqual(3);
});
});
Expectations can come in different formats depending on your use cases and the type of matchers you decide to use to obtain your result.
Jasmine provides a rich set of built-in matchers. Let's explore some important ones:
You can find the full list of matchers from the docs.
The code snippet below shows a simple implementation of our specs with some of the matchers.
describe('Test Helpers', function () {
it('should calculate Fibonacci series', function () {
const fib = Fibonnaci(4);
expect(fib).toEqual(5);
expect(fib).toBeDefined();
expect(fib).toBeNaN().toBeFalsy();
});
});
Jasmine provides the ability to define your custom matcher to satisfy your use case. You can create a custom assertion function not covered by the built-in matcher.
Jasmine provides two global functions for initializing and cleaning your specs. They are the beforeEach and afterEach functions.
For instance, if you need to initial variables to use in each of your test suites, you can simply add the initialization process inside the `beforeEach` function, and it will be initialized on every test case. Also, you can reset any variable of your choice using the `afterEach` function.
In the next section of this Jasmine unit testing tutorial, we will explore how to set up the Jasmine testing environment and configure Jasmine to work with our demo project setup.
In the previous section of this Jasmine unit testing tutorial, we discussed the different ways to use Jasmine in your project. In this section, we will learn how to initialize your testing environment and configure Jasmine to work with our project setup.
We are going to use Jasmine as a library in this demo project. The `jasmine` module is a command line interface and code for running Jasmine specs with Node.js.
Here are the default configuration file:
{
"spec_dir": "spec",
"spec_files": [
"**/*[sS]pec.?(m)js"
],
"helpers": [
"helpers/**/*.?(m)js"
],
"env": {
"stopSpecOnExpectationFailure": false,
"random": true
}
}
"scripts": {
"test": "jasmine"
}
In the next section of this Jasmine unit testing tutorial, we will follow these steps to test the registration form demo Node.js application we have created for this Jasmine unit testing tutorial.
In this Jasmine unit testing tutorial section, we will build and test a registration form in Node.js using Express and Jasmine.
<h1>Registration form</h1>
<div class="form-container">
<form name="registerForm" method="POST">
<label for="firstName">First Name *</label>
<input
type="text"
id="firstName"
name="firstName"
placeholder="John"
required
/>
<p class="error-message"></p>
<label for="lastName">Last Name *</label>
<input type="text" id="lastName" placeholder="Doe" required />
<p class="error-message"></p>
<label for="e-mail">E-mail address *</label>
<input
type="text"
id="e-mail"
placeholder="john-doe@net.com"
required
/>
<p class="error-message"></p>
<label for="phoneNumber">Phone Number</label>
<input
type="text"
id="phoneNumber"
maxlength="9"
pattern=".{9,}"
required
title="9 characters length"
placeholder="223587972"
/>
<p class="error-message"></p>
<label for="country">Country</label>
<input type="text" id="country" placeholder="United Kingdom" />
<p class="error-message"></p>
<label for="password">Password *</label>
<input
type="password"
id="password"
pattern=".{8,}"
required
title="8 characters minimum"
/>
<p class="error-message"></p>
<p class="password-rules">
Your password should contain at least 8 characters and 1 number.
</p>
</form>
/*first name input validation*/
function FirstName(fname) {
var letters = /^[A-Za-z]+$/;
if (fname.match(letters)) {
return true;
} else {
return false;
}
}
/*last name input validation*/
function LastName(lname) {
var letters = /^[A-Za-z]+$/;
if (lname.match(letters)) {
text = '';
return true;
} else {
return false;
}
}
/*email address input validation*/
function Email(email) {
var mailformat = /^w+([.-]?w+)*@w+([.-]?w+)*(.w{2,3})+$/;
var atpos = email.indexOf('@');
var dotpos = email.lastIndexOf('.');
if (email.match(mailformat) || (atpos > 1 && dotpos - atpos > 2)) {
return true;
} else {
return false;
}
}
/*phone number validation*/
function PhoneNumber(pnumber) {
var numbers = /^[0-9]+$/;
if (pnumber.match(numbers)) {
return true;
} else {
return false;
}
}
/*country input validation*/
function Country(country) {
var letters = /^[A-Za-z]+$/;
if (country.match(letters)) {
return true;
} else {
return false;
}
}
/*validate password*/
function Password(password) {
var illegalChars = /[W_]/; // allow only letters and numbers
if (illegalChars.test(password)) {
return false;
} else if (password.search(/[0-9]+/) == -1) {
return false;
} else {
return true;
}
}
The code snippet is already self-explanatory with the use of comments. We are validating different inputs for each param passed to the individual functions.
First, we will create the `validations.spec.js` file inside the newly created `spec` folder and add the following codes to cover the Validation test suites.
const {
validateCountry,
validatePassword,
validatePhoneNumber,
validateEmail,
validateLastName
} = require('../helpers');
describe('Validation Helpers', function () {
it('should validate country', function () {
const country = validateCountry('nigeria');
expect(country).toEqual(true);
});
it('should validate acceptable password', function () {
const password = validatePassword('Password1');
expect(password).toEqual(true);
});
it('should validate wrong password', function () {
const password = validatePassword('Password');
expect(password).toEqual(false);
});
it('should validate good PhoneNumber', function () {
const password = validatePhoneNumber('081456552232');
expect(password).toEqual(true);
});
it('should validate empty PhoneNumber', function () {
const password = validatePhoneNumber('');
expect(password).toEqual(false);
});
it('should validate good email', function () {
const email = validateEmail('test@test.com');
expect(email).toEqual(true);
});
it('should validate empty email', function () {
const email = validateEmail('');
expect(email).toEqual(false);
});
it('should validate good last name', function () {
const lastName = validateLastName('Solomon');
expect(lastName).toEqual(true);
});
});
The code snippet above uses the different concepts we have explained above to create a test suite for making sure our validation methods work as expected.
Lastly, we will run the test to see if it passes or not. Type the following command into your root terminal.
npm run testIf your test is successful, you should see three 12 cases passed, as shown in this figure.
In this section of this Jasmine unit testing tutorial, we have demonstrated how to configure and structure software testing with Node.js using the latest Jasmine testing library. We have also learned how to write a basic unit test.
However, you can use cloud testing platforms like LambdaTest to perform Jasmine unit testing at scale over a cloud Selenium Grid. LambdaTest offers a secure and reliable cloud-based Selenium Grid infrastructure that enables you to conduct cross browser testing on a large scale. With a vast selection of over 3000 browser and operating system combinations available on its online browser farm, LambdaTest allows you to test your code on various environments.
You can follow the LambdaTest YouTube Channel for more such videos around Selenium testing, CI/CD, Cypress UI testing, and more.
To perform Jasmine unit testing on a cloud grid-like LambdaTest, you can follow these steps:
If you're a JavaScript developer looking to improve your unit testing skills, consider taking the Selenium JavaScript 101 certification course from LambdaTest to gain the expertise needed to excel in the field.
"Furthermore, delve into an extensive compilation of commonly asked Jasmine Interview Questions in 2023. This resource is designed to aid interview preparation and enhance your Jasmine framework proficiency."
BDD encourages collaboration even in software testing, and Jasmine testing framework builds on these principles to deliver a collaborative testing environment for the software engineering team.
Software testing is a very important aspect of software development. It ensures that the software under test meets the intended requirement, is defect-free, and is free of errors and bugs.
In this Jasmine unit testing tutorial, we discussed the overview of Jasmine and how it implements BDD principles. We explored the different ways to use Jasmine in your JavaScript projects and elucidate the different elements of the Jasmine testing framework.
In this Selenium JavaScript tutorial, we implemented a simple registration form demo Node.js application using Expressjs. Lastly, we use Jasmine to implement the JavaScript unit testing method to validate users' input to ensure it's in the correct format.
Yes, Jasmine is a unit testing tool for JavaScript. It is a behavior-driven development (BDD) framework that provides a suite of matchers for making assertions about the code being tested. It does not require a DOM (Document Object Model) and has a clean, obvious syntax, so it's easy to write tests. It is open-source and widely used in JavaScript development.
Jasmine and Jest are popular JavaScript testing frameworks with different design philosophies and features. Both frameworks are powerful and widely used, so choosing between them will depend on your specific needs and project requirements.Jest is a complete testing solution. It includes everything you need to start testing, including a test runner, assertion library, and mocking library; it's also faster than Jasmine. Jasmine, on the other hand, is a bit more minimal, and it's more of a pure BDD framework, which makes it more suitable in certain contexts.
Reviewer's Profile
Himanshu Sheth
Himanshu Sheth is a seasoned technologist and blogger with more than 15+ years of diverse working experience. He currently works as the 'Lead Developer Evangelist' and 'Director, Technical Content Marketing' at LambdaTest. He is very active with the startup community in Bengaluru (and down South) and loves interacting with passionate founders on his personal blog (which he has been maintaining since last 15+ years).
Get 100 minutes of automation test minutes FREE!!