Introduction
This article is a Step by Step guide on how to do Unit testing of ExtJS application using Jasmine Framework. The MVC approach of ExtJS along with the ‘Behavior Driven Testing’ approach of Jasmine Framework enables independent testing of ExtJS model, store and controller.
Background
ExtJS is a Model-View-Controller (MVC) based Javascript framework used to develop Rich Internet Applications. The architecture of ExtJS enforces keeping the model/view/controller in different files to develop desktop like applications. ExtJS architecture necessitates creation of model, view and controller, preferably as separate files.
As per the MVC paradigm:
- Model represents the state of the Entity
- View deals with the presentation logic of the entity and
- Controller mediates between Model and view by handling events occurring on the model/view and updates the model/view in response to events.
The MVC architecture, as detailed above, facilitates writing unit tests for the controller and store. This approach doesn't require to fire events from the View, since all the events occurring on the View are bound to event-handlers which are
JavaScript functions in the Controller, so they can be called independently. Similarly the ExtJS store is also independent of the View and can be tested independently.
Jasmine Framework
Jasmine is a JavaScript framework which enables Behavior driven testing of
JavaScript code. Jasmine is an independent framework which doesn't depend on any other JavaScript library. It enables the testing of the
JavaScript code without any interactions with DOM. Jasmine library can be used to test the functionality of any
JavaScript code.
Jasmine can be integrated easily to test ExtJS applications behavior because the controller/store/model of ExtJS are functional pieces of code with minimal reference to the UI. The controller in the ExtJS binds to the different UI events like click, selection etc. and delegates it to the respective event Handlers defined as function in the controller. We can leverage the Jasmine framework to test these event delegates without actually generating the events from the UI.
In this article we will be testing a simple QuestionBank application that enables us to Add/Delete/List multiple-choice questions and answer in the database.
The document contains two zip files, one containing the QuestionBank application (questionbank.zip) without test cases. This zip file can be used as skeleton to write the test cases. The other zip file (questionbank-tests.zip) contains the full codebase along with test cases for quick reference.
For simplicity, the sample application codebase has a sample servlet which uses the array list to return/save the questions.
Let us start exploring the way to create unit-test cases for ExtJS Application.
Components of application
Extract the contents of
the WebContent directory in the attached questionbank.zip to your web project called PRJ_DIR. Different components of the application are as follows:
In Nut shell, there are six steps for integration of Jasmine framework with ExtJS for creating the browser based HTML test cases:
- Create Test folder structure
- Download and set up Jasmine framework
- Create test-app.js
- Create test cases in Jasmine spec
- Create Test HTML files
- Execute the test cases
So let us explore these steps one by one.
Step 1: Create Test Folder structure
In order to configure the test cases we need to create folders for Jasmine framework, test cases and configuration file. Create a folder called
js in the PRJ_DIR\WebContent directory and create the following folders:
- js
- js/jasmine
- js/test
- js/spec
The image below shows the final directory structure required. The folder names written in red rectangle are the new folders which are to be created to integrate Jasmine Framework
Step 2: Download and Setup Jasmine Framework
In this step we will learn how to setup the Jasmine Framework to enable Unit Testing.
- Download the Jasmine Framework bundle "jasmine-standalone-1.3.1.zip" from https://github.com/pivotal/jasmine/downloads
- Unzip the jasmine-standalone-1.3.1.zip to any directory of your choice.
- Copy the following files to your PRJ_DIR\WebContent\js\jasmine directory
- lib/jasmine-1.3.1/jasmine.css to PRJ_DIR/WebContent/js/jasmine/jasmine.css
- lib/jasmine-1.3.1/jasmine.js to PRJ_DIR/WebContent/js/jasmine/jasmine.js
- lib/jasmine-1.3.1/jasmine-html.js to PRJ_DIR/WebContent/js/jasmine/jasmine-html.js
Step 3: Create test-app.js
We have to create a separate app.js file to enable testing. This file will be created in the
PROJECT_DIR\WebContent\js\test directory.
Let us see how to do this:
- Create a copy of existing app.js so it looks like:
Ext.Loader.setConfig ({enabled: true});
Ext.application ({
controllers:[ 'QuestionController' ],
models: [ 'Question' ],
stores: [ 'QuestionStore' ],
views: [ 'MainPanel' ],
autoCreateViewport: true,
name: 'QAApp'
});
- Set
autoCreateViewPort
to false
so that ExtJS
doesn't render any HTML. This is required as we will be testing the controllers/store without initializing View.
Ext.Loader.setConfig ({enabled: true});
Ext.application ({
.............
.............
autoCreateViewport: false,
name: 'QAApp'
});
- Add the launch function to initialize and execute the Jasmine Test Cases:
Ext.Loader.setConfig ({enabled: true});
Ext.application ({
.............
.............
autoCreateViewport: false,
name: 'QAApp',
launch: function () {
var jasmineEnv = jasmine.getEnv ();
jasmineEnv.updateInterval = 1000;
var htmlReporter = new jasmine.HtmlReporter ();
jasmineEnv.addReporter (htmlReporter);
jasmineEnv.execute ();
}
});
Step 4: Create Test Cases in Jasmine Spec
Create an empty JavaScript file
PROJECT_DIR\WebContent\js\spec\QuizControllerSpec.js. This will act as a placeholder for all the unit test cases.
Start writing the Jasmine Test Cases for example:
describe ("ExtJS Question App Test Suite", function () {
var mainPanel = null;
var questionStore = null;
var questionStore = null;
var storeLength = -1;
var controller = null;
beforeEach (function () {
mainPanel = Ext.create ('QAApp.view.MainPanel');
questionStore = Ext.StoreManager.lookup ('QuestionStore');
controller = Ext.create ('QAApp.controller.QuestionController');
storeLength = questionStore.data.items.length;
});
it ('Main View is loaded', function () {
expect (mainPanel != null).toBeTruthy ();
});
it ('Store shouldn’t be null', function () {
expect (questionStore != null).toBeTruthy();
});
it ('Controller shouldn’t be null', function () {
expect (controller != null).toBeTruthy();
});
it ('Grid should be loaded', function () {
expect (Ext.getCmp ("questionGrid") != null).toBeTruthy ();
});
it ('Store has items', function () {
expect (questionStore.data.items.length).toBe (storeLength);
});
it ('New item should be added to store', function () {
var record = Ext.create ("QAApp.model.Question");
record.id = 1;
record.question = 'Questions 3';
questionStore.add (record);
expect (questionStore.data.items.length).toBe (storeLength + 1);
questionStore.removeAt (storeLength);
});
it ('Item should be removed from store', function () {
var record = Ext.create ("QAApp.model.Question");
record.id = 1;
record.question = 'Questions 3';
questionStore.add (record);
controller.deleteQuestionFromStore(record);
questionStore.removeAt (storeLength);
expect (questionStore.data.items.length).toBe (storeLength);
});
});
Step 5: Create Test HTML File
This is major file which will integrate Jasmine Unit test cases and code of ExtJS Application. It will include the Jasmine framework, Jasmine test cases, ExtJS
test-app.js file. This file will actually execute the test cases.
Please refer the below steps for more details:
- Create an empty html file SpecRunner.html with following contents:
<html>
<head>
<title>Test Quiz Application</title>
</head>
<body>
</body>
</html>
- Add Jasmine frameworks CSS and JS files in the test HTML. This is to make SpecRunner.html use Jasmine framework to enable Unit Testing
- Add the ExtJS Libraries/CSS in
SpecRunner.html. This is required to load the ExtJS codebase in the test file.
- Including the Jasmine Test Case File. This will enable the Test cases to be loaded so that Jasmine framework can execute them.
- Now Add the app-test.js file to load the ExtJS Application in Test mode.
- After executing all the above steps the final SpecRunner.html file will look like:
<html>
<head>
<title>Test Quiz Application</title>
// including the Jasmine Files
<link rel="stylesheet" type="text/css" href="js/jasmine/jasmine.css">
<script type="text/javascript" src="js/jasmine/jasmine.js"></script>
<script type="text/javascript" src="js/jasmine/jasmine-html.js"></script>
//including the ExtJS Files
<script type="text/javascript" src="extjs-4.1.1/ext-all.js"></script>
<link rel="stylesheet" type="text/css" href="extjs-4.1.1/resources/css/ext-all.css">
// including the Jasmine Test Case file
<script type="text/javascript" src="js/spec/QuizControllerSpec.js"></script>
// including the test-app.js file to load test cases
<script type="text/javascript" src="js/test/test-app.js"></script>
</head>
<body>
</body>
</html>
Step 6: Execute the Test Cases
Executing the Test cases is very easy. Just deploy the application on any Application Server like Tomcat.
Once the application is deployed, then opening the URL http://<servername>:<port>/ExtJSQuizApp/SpecRunner.html will fire the test cases.
The results can be seen as follows:
Summary
As we have seen that it’s quite easy to leverage the Jasmine framework to test the ExtJS application. Similarly, we can use Jasmine to test any
JavaScript codebase.
Source Code
Attached is the source code of the application with skeleton and test cases.
References
- http://www.sencha.com/products/extjs
- http://pivotal.github.io/jasmine/