jQuery MiniUI,Ajax Web开发

Sencha Test 测试新建应用程序

Sencha Studio 允许开发人员快速和自动测试一个应用程序或 web 页面的细微粒度方面。随着代码库的增长,单元 测试可以确保应用程序的所有部分按照你的预期运行。

本指南, 我们学习生成一个新的应用程序,并设置测试环境, 创建一个可测试的类, 并对它进行单元测试. 所有这些工作都可以在 Sencha Studio 中完成.

如果你有一个已存在的应用程序, 请看 测试已有应用程序.

本文假定你已经对 Jasmine 测试框架比较熟悉. 如果你不熟悉 Jasmine 或 测试的概念, 请查阅他们优秀的 文档,来获取更多关于编写 Jasmine 测试的信息. 本指南也使用了 Sencha Cmd 来生成 一个 Ext JS 应用程序,并假定你已经下载安装它了.

让我们开始吧!

创建一个 Workspace

先打开 Sencha Studio.

你可以在 Sencha Studio 工具栏上点击下面的菜单来生成你需要的 workspace:

Sencha Studio -> New -> Workspace...

选择合适的文件路径,然后点击 "OK". 你会发现新生成的 workspace 中有一个测试项目了.

接下来, 我们添加一个应用程序到这个新的 workspace 中.

生成一个 Classic 应用程序

简单起见, 我们生成一个 Classic 应用程序到我们的 workspace 中. 我们也可以用 Sencha Test 来生成应用程序!

点击下面的菜单即可:

Sencha Studio -> New -> Application...

接着, 输入应用程序名称, 选择 classic, 然后把 workspace 的位置作为保存论斤. 你的应用程序就会出现在 workspace 下面了.

增加一个可测试的类

这个简单的应用程序只有很少的功能, 所以我们来加点东西用于测试. 此处, 我们创建一个 WindowEditor 类,在 MyApp/app/view/main/WindowEditor.js 文件里,你可以使用任何 IDE 编写. 你可以使用下面这段代码:

Ext.define('MyApp.view.main.WindowEditor', {
   extend: 'Ext.Window',

   alias: 'widget.windoweditor',

   width:400,
   height:200,
   padding:20,

   autoShow: true,

   title: 'Update Email',

   items: [{
       xtype: 'form',
       items: [{
           xtype: 'textfield',
           allowBlank: false,
           vtype: 'email'
       },{
           xtype: 'button',
           text: 'Submit Change',
           formBind: true
       }]
   }]
});

该类继承 window,里面有一个 form, form 里面包含一个文本框和一个按钮. 我们指明了文本框不允许为空而且必须输入一个邮箱地址.

此外, 我们还把按钮的 formBind 配置为了 true. 这表明,如果表单验证不通过,按钮则一直处于不可用状态. 一旦验证通过, 按钮就可以被点击了.

你还可以把 MyApp/app/view/main/MainController.js 的 onItemSelected 函数替换为下面的代码:

onItemSelected: function (sender, record) {
    Ext.create('MyApp.view.main.WindowEditor');
}

这将为表格打开一个 email editor. 在 Sencha Studio 创建接下来的测试之前,最好不要修改控制器的代码. 也就是说,你会发现,你的应用程序的创建逻辑,和你接下来要写的测试 spec 是平行执行的.

我们最终会使用这个类来测试,当输入的文本满足我们的规定的时候,按钮是否能够成功启用/禁用。

注意: 这个 "editor" 此时其实还没啥功能, 不过已经满足我们测试的需要了.

初始化一个测试项目


我们选择 "Applications" 下的 "Tests" 节点,来设置测试项目. 再点击右手边明细页的 "Initialize Test Project". 点击之后, 你会看到一些项目设置. 此时我们还不需要变动它们. 不过, 如果你改了设置, 记得点击 "Save" 才能生效.

下面, 我们来添加一个应用程序场景(scenario).

增加一个场景(Scenario)


一个测试项目必须要有 “场景”, 而后才能添加一套测试 specs.

场景 - 场景下包含了接下来要创建的测试套件.

要创建一个场景, 点击 Scenarios 标题下面的 "+ Add" 按钮. 然后你可以改变场景的名称和文件路径. 通常, 你会基于你将要测试的内容来命名. 此处, 我们取名 "WindowEditor". 添加完之后, 一定要点击 "Save". 现在我们可以添加一套测试 specs 到场景中了.

增加一个套件(Suite)


现在你可以看到 “WindowEditor” 是 "Tests" 的一个子节点. 点击它, 你会看到一个浏览器列表,还有一个带有 "无测试用例(No tests found)" 字样的面板. 我们来改变它!

我们来添加一个 Jasmine 测试套件.

套件 - 套件是一个文件,包含了一组 代表应用程序某些方面 的测试. 这些方面可以是一个类,一个组件,或者是一组方法. 具体地,还要取决于你是如何组织你的测试套件的.

"右击" “Window Editor” 节点,然后点击 "New->Jasmine Test Suite". 弹出了一个模态对话框,需要你输入套件名称. 我们取名叫 "WindowValidation" 吧.

添加好之后, 可以看到 "WindowEditor" 底下多了个 "WindowValidation.js" 文件. 点击这个文件,会看到一段默认代码,方便我们开始.

describe("my test suite", function() {
    it("should pass", function() {
        expect(1).toBe(1);
    });
});

为了便于使用, "右击" WindowValidation.js 标签页,点击 "Move Right". 这个操作会将WindowEditor和你的 场景的测试运行器分隔开来. 这样,改动之后,可以很快地测试它们.

目前套件中的代码没什么用处, 我们来给它添加一个 spec.

添加一个 Spec


Spec - 指的是一个单独的测试,用一个 JavaScript 函数的形式来解释你的程序应该完成什么. 我们应当用简单的语言来解释测试所期望的结果是什么. 然后提供 JavaScript 代码执行测试,以达到期望.

需要注意的是,对于创建类和获得对组件的引用来说,多次测试可能会并行应用程序代码的多个方面.

暂时我们先复制下面的代码到你的 WindowEditor.js 文件,然后点击 "Save":

describe("formBind true", function() {
    it("should disable button if email is not valid", function(done) {

        // Create and reference the WindowEditor and then 
        // get reference to the button and textfield
        var win = Ext.create('MyApp.view.main.WindowEditor'),
            button = win.down('button'),      
            field  = win.down('textfield');

        // Set the field's value to a valid email address
        // in order to have the button fire an enable event
        field.setValue('valid@email.com');

        button.on('enable', function() {

            // Set the field's value to an invalid email address (nothing)
            // in order to have the button fire a disable event
            field.setValue('');

            button.on('disable', function() {

                //  Once the disable event has been called after setting a 
                //  bad value, we can safely say that the button is properly 
                //  hooked into the form's validity.  Thusly, we can 
                //  alert the spec to return by calling the done function.
                done();    
            });
        });
    });
});

可以看到, 我们测试了表单是否验证通过会改变按钮的可用状态. 如果文本框的值有效, 表单验证通过, 按钮就可用. 相反的, 如果输入框值无效,表单验证不通过,按钮就不可用. 这种行为是由于按钮的 formBind 配置被设置为 true.

我们可以用过监听按钮的 enable/disable 事件来测试这些条件是否达到. 如果按钮触发了 "enable", 我们就知道表单通过了验证. 如果按钮触发了 "disable" 事件, 那么表单就没有通过验证. 此时, 我们就认为测试成功,然后调用 Jasmine 的done() 函数.

很多情况下, 你应该使用一个断言(expectation)来确保结果满足你的要求. 断言使用 expect 函数, 此函数接收一个值, 称作实际值. 然后通过一个接收期望值的 Matcher 函数将2者链接起来. 断言的结果是 true/false, 或者也称作 pass/fail.

也就是说, 这个例子中我们不需要使用断言. done() 函数会作为参数传递给 it() 方法. 当我们决定执行完毕时,我们可以简单调用 done() 函数. 在处理异步测试时, done() 通常作为一个 "成功" 回调. 不过此处, 我们可以用 done(),而不需要设置一个断言. 因为在最后的事件中, 我们知道测试已经满足了, 所以不需要断言. 如果最后的事件永远触发不了, done() 就不会被调用, 测试就会在5秒后超时, 表示测试失败了.

现在我们有了一个测试用例, 我们来执行它,以确保我们的应用程序编辑器正确实现了表单验证.

执行测试


现在已经连接上了测试, 我们用本地浏览器(local browser)运行一下.

首先, 在 Workspace 导航视图上选择 "WindowEditor" 场景节点,以便显示场景的测试执行标签页. 然后, 在测试执行标签页左侧,根据你的需要选择浏览器. 此处, 我们选择 Chrome.
选择完成后, 你会发现你选择的浏览器正在打开你的应用程序.

注意: 如果 "sencha app watch" 正在初始化, 你会在应用程序节点右侧看到一个黄色的眼睛图标. 当图标变成黑色的时候,浏览器才会打开, 表示 "app watch" 初始化完成.

在 WindowEditor 的测试运行器中选择 "WindowValidation.js", 然后点击顶栏的 "Run Selection" . 如果一切正常, 你会得到一个绿色的勾,表示测试执行通过.

再来看看测试失败时发生什么, 我们来改一下测试用例的代码,强制使得测试执行失败.
我们把下面的代码:

    // Set the field's value to a valid email address
    // in order to have the button fire an enable event
    field.setValue('valid@email.com');

改为:

    field.setValue('');

可以想象, 这个改动会使得输入框值无效,按钮的 enable 事件永远不会触发,也就永远不会调用 done(). 5 秒之后, 测试超时并执行失败.

保存 spec,然后重新执行一下. 你会看到一个红色的 "1". 表示一个 spec 失败了. 如果你展开 WindowValidation.js, 然后展开 formBind true, 你会看到我们的 spec 后边跟着一个红色的 "x". 如果你点击红色的 "x", 你就可以在摘要面板上看到错误的摘要.

结论


可以想象, 本指南只接触了通过 Sencha Studio 使用 Sencha Test 的表面. 希望本文为你提供了基础知识,来探索和发现 Sencha Studio 中更多功能强大的工具.

译者: 神秘_博士
原文: http://blog.csdn.net/lovelyelfpop/article/details/52511283