This Article Covers Jasmine Testing Framework & Its Constructs. Also, Learn About Jasmine-Jquery Package That Extends Jasmine to Test Jquery Applications:
We learned all about Karma in our previous tutorial in this series.
Here we will mainly focus on the basic Jasmine constructs for writing tests.
What You Will Learn:
What Are Testing Frameworks?
Testing Frameworks are suites of programs or packages that facilitate testing another program to ensure its quality. Every programming platform has its own testing framework as you must have learned from our previous tutorial.
There are different sets of tests that can be carried out on any software system. Examples of such tests include unit testing, end to end (e2e) testing, etc. Check here for more details.
Introduction To Jasmine Framework
There are different development approaches available in the present-day scenario. Out of these, two of the most popular development approaches include Test-Driven Development (TDD) and Behavior Driven Development (BDD).
Test-Driven Development is a development approach where we write the tests first, and then run them. Each test fails on its very first execution because the functions it uses have not been written yet.
We then write the functions and rerun the tests. Here, some of the tests fail and the others pass. We keep refactoring the code to have all the tests pass.
Behavioral Driven Development also follows the same approach. The only difference is that BDD is written to satisfy owners of the software (customer/business-oriented) i.e. to meet the software features with the business requirements or the expected behavior.
Whereas TDD is written to satisfy the developers of the software so that it can be assured that the software functions that are used in building the features are producing accurate results, stable and reliable.
See here to know more about TDD vs BDD.
There are two ways to use Jasmine to write your tests. One way is to use the standalone version that comes with specRunner.html (which displays test results in a browser). The other way is to simply install Jasmine, write your tests and run it with a test-runner like Karma to get the results displayed in the console window.
We would be looking at both the ways of using Jasmine in our upcoming tutorial.
Basic Jasmine Constructs For Writing Tests
Enlisted below are the various constructs of Jasmine for writing tests.
#1) describe: This construct is used to write a test suite. A test suite is a collection of multiple tests. ‘describe’ is a function in itself that takes two parameters: The name of the suite and a function.
The function parameter contains a collection of tests grouped under the test suite.
#2) it: This construct is used to write a test spec. A test spec is a set of constructs that are testing a particular or most minute expectation for a system.
Like describe construct, it also takes two parameters: The name of the test and the function that contains the assertions evaluating if the expectation is fulfilled or not.
#3) expect: This construct aids in testing if the expectations from the software system are fulfilled or not.
It takes a parameter called the actual (which is the result the software system is returning) and then it is chained with another construct called a matcher (expected outcome).
#4) Matches: This is a collection of constructs that the expect construct is chained to. It determines if the expectation is fulfilled or not.
These constructs take the expected value of the closest test being carried out and match it against the actual value obtained on executing the test. Click here for a complete list of Jasmine matcher constructs
#5) beforeEach: This is a global construct, provided by Jasmine to help you keep your tests DRY (do not repeat yourself). This construct is normally used in the function parameter of the describe construct.
Any code inside runs once before the specs under the suites are ran. Hence, any code that you wish to be run first before all the specs in the suite should be placed here.
#6) afterEach: This construct is the same as beforeEach, and the difference is that the code it contains is run after every code once the describe construct is ran.
#7) this: This construct is an empty object that can be used to share values across ‘beforeEach’, ‘afterEach’, and ‘it’ constructs in any test suites. Every test suite has its own object and the object is reset to empty before the test suites are executed.
#8) xdescribe: This construct is used to disable the software suites. It simply tells the test runner to skip the test suite and hence, its result is not shown and considered.
#9) xit: This construct is used to indicate a spec in a suite as a pending spec. A pending spec is a spec that will not run but will have their names shown in the test result as pending.
Also, if in any spec the pending function is called, then the spec is marked as a pending spec. Any spec declared without a function body is also tagged as pending.
#10) spyOn: This construct is used to create a Jasmine spy. Spies are mocks. Mocks are fake objects created to represent or mimic the real object. Mocks are required to prevent the overhead cost of creating the real object that they represent.
The essence of unit testing a code is to see how a function behaves under several conditions independent of the other units connected or will be connected to it.
Thus, we perform front-end unit testing to see how a unit of the front-end of our software product will behave independently of the other front-end units that will be connected or are connected to it.
During this test, we make calls to various arguments and functions that may be dependent on other functions and objects such as network connections, data sources, and files.
To meet these dependencies (so that we can carry out front-end unit testing), there is a need to make the required resources available. Hence, we adopt mocks to mimic the real-world objects and avoid the overhead cost of actually creating them.
Note that on a simple level, spyOn is used to test if a dependent function is actually called, and this dependent function may just be a simple function that is defined on the object that we are spying.
The spyOn function takes two parameters: the object being spied and the dependency function it contains which is checked to make sure that our function calls it.
Spies exist in the suite or spec in which it is defined. After the suite or spec gets executed, the spy stops to exist.
#11) createSpy: This construct serves the same purpose as spyOn, but the difference is that this function makes it possible to replace the dependent function with a fake one for testing.
Why do I have to do this? This is useful when the original dependency is also dependent on the other resources that are not available in the context of the test.
This function is accessed using the Jasmine object with a dot, i.e. Jasmine.createSpy(parameters). It takes only one parameter, which is a string representing the name of the dependency for which we are creating the mock.
Note that after creating a spy, the spy on the first call returns undefined, as the first call is assumed to be its training. Then, after subsequent calls, the function returns the actual value. See more details as we explore it below.
Jasmine Test Double Function Feature
The constructs spyOn and createSpy make the creation of mocks (for dependency) possible. This is no other thing than testing two functions in one test, thus the statement “test double function”.
The other word that can be used to refer to mocks is ‘stubs’.
Spy Matchers: There are several matchers that cater to the need of interacting with spies. They include: ‘toHaveBeenCalled’ and ‘toHaveBeenCalledWith’.
- toHaveBeenCalled: This is used in a spec to determine that the dependency being spied was called.
- toHaveBeenCalledWith: This is used in a spec to determine that the dependency being spied was called with a certain set of parameters.
Visit here for a detailed outline of all Jasmine constructs.
Two Ways To Use Jasmine
There are two ways to write Jasmine tests. One is to use Jasmine as a standalone distribution via specRunner and the other is using Jasmine with test runner.
Let’s first look at running Jasmine tests via the specRunner.
How To Use Jasmine Standalone Distribution?
Click here, and then download the standalone distribution by clicking on Jasmine-standalone.
Unzip the file to the project folder. You will discover that it adds these directories to the project directory: lib, src, and spec; and also adds these files: specRunner.html and MIT.LICENSE.
The lib directory contains the Jasmine library that executes the tests contained in the test files added to the specRunner.html file. The specRunner.html file enables you to run the test and view the result on the browser in a web page format rather than in the console window.
The src directory contains the front-end source codes, and the spec directory contains the test files written using Jasmine test suites. By default, you can see some test suites and files inside the directories but we are not going to use these, we would write our own tests in our subsequent tutorials.
Using Jasmine With A Test-Runner
This is the second way of using Jasmine, where you configure a test-runner like Karma and feed it with your source file and the test spec file to run the tests.
Then, you can either display the results and generate reports using Istanbul or publish the test results to coveralls.io.
Introduction To Jasmine-Jquery
Jasmine-Jquery is a node package that aids the testing of front-end codes built with jquery. In a way, it extends the Jasmine framework to be well suited for Jquery’s front-end testing.
The extensions it adds to the Jasmine framework include:
- A set of custom matchers for the Jquery framework, such as toBeChecked, toBeDisabled, toBeEmpty, etc.
- An API for handling HTML, CSS, and JSON fixtures in our specs.
Now the question is “what is an API?” An API (application programming interface) is an interface that grants you access to certain functions that may take time and resources for you to build from scratch.
Another question is what are fixtures? Fixtures are pre-defined states of an object that we usually create while writing tests so as to establish a baseline (a well-known and fixed environment) against which the tests are run in order to make the results repeatable.
See here for more details on the custom matchers and API(s).
- A Testing framework is a suite of programs or packages that facilitate testing of the software to ensure the quality of the developed software.
- Test-Driven Development is a development approach where we write the tests first, and then run them. Each test fails on its very first execution because the function it uses has not been yet written. We then write the functions and re-run the tests. Here, some of the tests fail and others pass. Then, we keep refactoring the code until all the tests pass.
- A Behavioral driven development approach is a development approach in which tests are written to ascertain that the software features behave as expected by all stakeholders.
- Jasmine-Jquery is a node package that aids the testing of front-end codes built with Jquery.
In our upcoming tutorial, we will explore the ways of using these two tools (Jasmine and Karma) to write test specs for a typical project. We would also see how to use the other tools such as gulp, browserify, etc. that are required to have our tests up and running.