使用 Jasmine 进行 ExtJS 应用程序单元测试的分步指南
本文是一个关于如何使用 Jasmine 实现 ExtJS 应用程序单元测试的分步指南。
引言
本文是关于如何使用 Jasmine 框架对 ExtJS 应用程序进行单元测试的分步指南。ExtJS 的 MVC 方法结合 Jasmine 框架的“行为驱动测试”方法,能够独立测试 ExtJS 的模型、存储和控制器。
背景
ExtJS 是一个基于模型-视图-控制器(MVC)的 JavaScript 框架,用于开发富互联网应用程序。ExtJS 的架构强制将模型/视图/控制器保存在不同的文件中,以开发类似桌面应用程序。ExtJS 架构需要创建模型、视图和控制器,最好是作为独立的文件。根据 MVC 范例:
- 模型代表实体的状态。
- 视图处理实体的表示逻辑,并且
- 控制器通过处理模型/视图上发生的事件来充当模型和视图之间的中介,并响应事件更新模型/视图。
Jasmine 框架
Jasmine 是一个 JavaScript 框架,可以实现 JavaScript 代码的行为驱动测试。Jasmine 是一个独立的框架,不依赖任何其他 JavaScript 库。它允许在不与 DOM 交互的情况下测试 JavaScript 代码。Jasmine 库可用于测试任何 JavaScript 代码的功能。
Jasmine 可以轻松集成以测试 ExtJS 应用程序的行为,因为 ExtJS 的控制器/存储/模型是功能代码片段,对 UI 的引用最少。ExtJS 中的控制器会绑定到不同的 UI 事件,如单击、选择等,并将它们委托给控制器中定义的相应事件处理函数。我们可以利用 Jasmine 框架来测试这些事件委托,而无需实际从 UI 生成事件。
在本文中,我们将测试一个简单的 QuestionBank 应用程序,该应用程序允许我们在数据库中添加/删除/列出多项选择题和答案。
文档包含两个 zip 文件,一个包含不带测试用例的 QuestionBank 应用程序(questionbank.zip)。此 zip 文件可用作编写测试用例的骨架。另一个 zip 文件(questionbank-tests.zip)包含完整的代码库以及测试用例,方便快速参考。
为简单起见,示例应用程序代码库包含一个示例 servlet,该 servlet使用数组列表来返回/保存问题。
让我们开始探索为 ExtJS 应用程序创建单元测试用例的方法。
应用程序组件
将附加的 questionbank.zip 中的 WebContent 目录的内容提取到名为 PRJ_DIR 的 Web 项目中。应用程序的不同组件如下:
总之,在集成 Jasmine 框架与 ExtJS 以创建基于浏览器的 HTML 测试用例时,有六个步骤:
- 创建测试文件夹结构
- 下载并设置 Jasmine 框架
- 创建 test-app.js
- 在 Jasmine 规范中创建测试用例
- 创建测试 HTML 文件
- 执行测试用例
因此,让我们一步一步地探讨这些步骤。
步骤 1:创建测试文件夹结构
为了配置测试用例,我们需要为 Jasmine 框架、测试用例和配置文件创建文件夹。在 PRJ_DIR\WebContent 目录下创建一个名为 js 的文件夹,并创建以下文件夹:
- js
- js/jasmine
- js/test
- js/spec
下图显示了最终所需的目录结构。用红色矩形标出的文件夹是需要创建的新文件夹,用于集成 Jasmine 框架。
步骤 2:下载并设置 Jasmine 框架
在此步骤中,我们将学习如何设置 Jasmine 框架以实现单元测试。
- 从 https://github.com/pivotal/jasmine/downloads 下载 Jasmine 框架包 "jasmine-standalone-1.3.1.zip"
- 将 jasmine-standalone-1.3.1.zip 解压缩到您选择的任何目录。
- 将以下文件复制到您的 PRJ_DIR\WebContent\js\jasmine 目录:
- lib/jasmine-1.3.1/jasmine.css 到 PRJ_DIR/WebContent/js/jasmine/jasmine.css
- lib/jasmine-1.3.1/jasmine.js 到 PRJ_DIR/WebContent/js/jasmine/jasmine.js
- lib/jasmine-1.3.1/jasmine-html.js 到 PRJ_DIR/WebContent/js/jasmine/jasmine-html.js
步骤 3:创建 test-app.js
我们需要创建一个单独的 app.js 文件来实现测试。此文件将创建在 PROJECT_DIR\WebContent\js\test 目录中。
让我们看看如何做到这一点:
- 创建现有 app.js 的副本,使其看起来像这样:
- 将
autoCreateViewPort
设置为false
,以便 ExtJS 不会渲染任何 HTML。这是必需的,因为我们将测试控制器/存储而不初始化视图。 - 添加 launch 函数以初始化和执行 Jasmine 测试用例。
Ext.Loader.setConfig ({enabled: true});
// Loading different components like controller, model, view..
Ext.application ({
controllers:[ 'QuestionController' ],
models: [ 'Question' ],
stores: [ 'QuestionStore' ],
views: [ 'MainPanel' ],
autoCreateViewport: true,
name: 'QAApp'
});
Ext.Loader.setConfig ({enabled: true});
Ext.application ({
.............
.............
// Setting the autoCreateViewPort to initialize the Application without
// View being rendered
autoCreateViewport: false,
name: 'QAApp'
});
Ext.Loader.setConfig ({enabled: true});
Ext.application ({
.............
.............
autoCreateViewport: false,
name: 'QAApp',
// using the Launch method of Application object to execute the Jasmine
//Test Cases
launch: function () {
var jasmineEnv = jasmine.getEnv ();
jasmineEnv.updateInterval = 1000;
var htmlReporter = new jasmine.HtmlReporter ();
jasmineEnv.addReporter (htmlReporter);
jasmineEnv.execute ();
}
});
步骤 4:在 Jasmine 规范中创建测试用例
创建一个空的 JavaScript 文件 PROJECT_DIR\WebContent\js\spec\QuizControllerSpec.js。这将作为所有单元测试用例的占位符。
开始编写 Jasmine 测试用例,例如:
describe ("ExtJS Question App Test Suite", function () { var mainPanel = null; var questionStore = null; var questionStore = null; var storeLength = -1; var controller = null; /* Setup method to be called before each Test case.*/ beforeEach (function () { // Initializing the mainPanel. mainPanel = Ext.create ('QAApp.view.MainPanel'); questionStore = Ext.StoreManager.lookup ('QuestionStore'); controller = Ext.create ('QAApp.controller.QuestionController'); storeLength = questionStore.data.items.length; }); // before each /* Test if View is created Successfully.*/ it ('Main View is loaded', function () { expect (mainPanel != null).toBeTruthy (); }); /* Test if store is loaded successfully.*/ it ('Store shouldn’t be null', function () { expect (questionStore != null).toBeTruthy(); }); /* Test controller is initialized successfully.*/ it ('Controller shouldn’t be null', function () { expect (controller != null).toBeTruthy(); }); /* Test if Grid in MainPanel is loaded successfully.*/ it ('Grid should be loaded', function () { expect (Ext.getCmp ("questionGrid") != null).toBeTruthy (); }); /* Test if Grid in MainPanel is loaded successfully.*/ it ('Store has items', function () { expect (questionStore.data.items.length).toBe (storeLength); }); /* Test if new item is added to store.*/ 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); }); /* Item should be removed from store via controller.*/ 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); /* Removing item from controller API.*/ controller.deleteQuestionFromStore(record); questionStore.removeAt (storeLength); expect (questionStore.data.items.length).toBe (storeLength); }); });
步骤 5:创建测试 HTML 文件
这是主要文件,它将集成 Jasmine 单元测试用例和 ExtJS 应用程序的代码。它将包含 Jasmine 框架、Jasmine 测试用例、ExtJS test-app.js 文件。此文件将实际执行测试用例。
请参考以下步骤了解更多详情:
- 创建一个空的 html 文件 SpecRunner.html,其中包含以下内容:
- 在测试 HTML 中添加 Jasmine 框架的 CSS 和 JS 文件。这是为了让 SpecRunner.html 使用 Jasmine 框架来实现单元测试。
- 在 SpecRunner.html 中添加 ExtJS 库/CSS。这是加载 ExtJS 代码库到测试文件所必需的。
- 包含 Jasmine 测试用例文件。这将允许加载测试用例,以便 Jasmine 框架可以执行它们。
- 现在添加 app-test.js 文件以在测试模式下加载 ExtJS 应用程序。
- 执行完以上所有步骤后,最终的 SpecRunner.html 文件将如下所示:
<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>
<html>
<head>
<title>Test Quiz Application</title>
</head>
<body>
</body>
</html>
步骤 6:执行测试用例
执行测试用例非常容易。只需将应用程序部署到任何应用程序服务器,如 Tomcat。
应用程序部署后,打开 URL http://
结果如下所示:
摘要
正如我们所见,利用 Jasmine 框架来测试 ExtJS 应用程序非常简单。同样,我们可以使用 Jasmine 来测试任何 JavaScript 代码库。
源代码
附带了带骨架和测试用例的应用程序源代码。