zoukankan      html  css  js  c++  java
  • Sencha Test Futures API 探秘

    原文链接:http://blog.csdn.net/lovelyelfpop/article/details/52301249



    英文原文:《Inside the Sencha Test Futures API


    编写交互式測试的一个最大的挑战是处理它们的异步特性。Sencha Test 提供了一个新的强大的API,它被设计用来使这些异步測试像同步方式一样简单。

    Jasmine 框架的异步測试

    測试异步代码并非什么新奇事, Jasmine 提供了对其开箱即用的支持, 同意将你的測试标识为异步的:

    describe('Some tests', function () {
        it('takes time', function (done) { // << "done" marks test async
            doThings().then(done);
        });
    });
    

    传递给 it() 的第二个參数是一个函数,这个函数中有名字的那个參数(习惯写为“done”)。表明 Jasmine 測试是异步的。即測试(终于)告诉 Jasmine, 它是通过调用提供的“done”来结束的,而不是简单地返回。

    假设測试在一段时间内没有调用 done 函数(默认5秒), 測试则宣告失败。

    这个简单的方法在小測试下没问题, 可是假设有多个步骤, 非常难猜得到结束之前要消耗的总时间。

    server请求等在測试环境中甚至是不可预知的, 特别是当环境里可能同一时候装载到多个浏览器和场景下。

    当然, 我们非常easy忘记调用 done, 可是通常在写測试的时候就会发现。然而,假设一个測试涉及复杂的逻辑, 非常可能就会出现有些分支逻辑调用了 done。而某些分支却没有。

    it('should eventually call done', function (done) {
        if (condition) {  // true 98% of the time
            done();
        } else {
            // oops - fails "randomly"
        }
    });
    

    显然,假设可能的话,最好避免写这样的分支逻辑。

    在交互式測试之前,全部这些问题都是可控的。这样的測试无论是在端到端測试应用程序的UI, 还是单元測试应用程序视图和控制器的时候,都是普遍存在的。在这两种情况下, 大多数測试步骤须要异步操作和等待条件, 并混杂着 正确性检查和期望(expectations)。

    元素(Element) Futures

    为了使交互式測试更具表现力和易于维护, Sencha Test 測试提供了ST.future.* 命名空间下的一套类, 统称为“futures”。

    Futures 是在測试代码中创建出来的对象, 它提供了一个简洁的语法来描写叙述异步測试序列。

    来看一个 Futures 的简单的样例, 以下的代码使用 ST.element() 工厂方法返回的一个 ST.future.Element

    it('should change text on click', function () {
        ST.element('button#foo').
            click(10, 10).
            textLike(/^Save/).
            and(function (el) {
                expect(el.hasCls('somecls')).toBe(true);
            });
    });
    

    ST.element() 方法接收一个 定位器(locator) (一般是一个字符串,如XPath, 组合查询Component Query, 等等,用于定位一个详细元素). 返回的 ST.future.Element 实例提供了一些方法,我们上面也用到了: click()textLike() 和 and(). 每一个方法都返回相同的 ST.future.Element.

    要记住, 尽管 futures 看上去是同步调用, 可是它们实际上并没有马上运行对应操作。

    相反, 它们创建了一个动作序列,仅仅在“当它们能运行”的时候才会运行。

    定位器 Locators

    測试的第一步使用了 ST.element() 创建一个 future 元素实例。这仅仅是该方法的第一个职能, 第二个相同重要的职能是定位到目标 DOM 元素. 在幕后, ST.element() 保存下了定位器,然后会等待目标元素被加入到 DOM 树中而且可见。

    等到測试函数将控制权返回给浏览器,定位元素的任务才会開始.

    动作 Actions

    測试的第二步是在元素上运行 click() 。能够使用相对于该元素的坐标 (可选) . 当 click() 被调用, 它把点击事件加入到动作序列中. ST.future.Element 提供的非常多方法都是动作方法, 而且它们都以同样的方式工作: 后来的动作会排在之前的动作后面, 它们都会在 future 实例所定位到的元素上运行。

    动作方法以动词为名称 (比方“click”).

    状态 States

    測试第三步是 textLike() 函数. 此处安排了一次等待。直到元素的 textContent 匹配给定的正則表達式. 这组方法涉及到描写叙述状态。并注入一次延时操作,直到满足目标状态. 有些状态方法须要轮询检測状态变换,而另外一些能够仅仅监听事件来检測变化。无论如何,这样的细节已经被 Sencha Test 处理了。測试者无需关心.

    状态方法的名称是名词或者描写叙述 (比方“collapsed”或者“textLike”).

    检查 Inspections

    測试的最后一部分是调用 and() 方法. 这种方法安排了一个 函数(function),它会在前一个步骤完毕之后。才被调用。此处, 则是在 textContent 满足正則表達式之后。传递给 and() 的函数会接收到2个參数。

    此处我们仅仅声明了当中一个: 被定位到的 ST.Element

    可选的第二个參数是 done 函数, 这和 Jasmine 异步測试一样。

    假设声明了第二个參数, done 函数就会被传递进去, 并且必须被调用。

    这些方法通经常使用于检查元素, 它的当前状态 和/或 应用程序的其它方面。

    自己定义等待 Custom Waits

    有时须要在代码中写一个等待条件。

    我们能够改动 and() 方法,使其接收一个 done 函数.

    it('should change text on click', function () {
        ST.element('button#foo').
            click(10, 10).
            textLike(/^Save/).
            and(function (el, done) {
                // wait for condition and call done()
            });
    });
    

    在其它情况下, 測试必须轮询检測适当的状态。Futures 提供了一个 wait() 方法来处理:

    it('should change text on click', function () {
        ST.element('button#foo').
            click(10, 10).
            textLike(/^Save/).
            wait(function (el) {
                return el.hasCls('somecls'); // return true-like when done
            });
    });
    

    总的来说, 最好使用 and() 方式,由于它避免了轮询。只是很多其它情况下,还是要依赖详细情况做出正确的选择。

    组件 Futures

    使用 ST.element() 能够非常easy地和元素进行异步交互, 只是利用 Sencha Test Futures API 提供的 ST.component() 和 相关类型的 futures 能够做到很多其它。这些方法创建的类实例。都继承自 ST.future.Component

    这些类扩充了 ST.future.Component , 并为其对应类型的组件提供了额外的动作和状态方法。

    看个新的測试的样例:

    it('should change cell text on click', function () {
        ST.grid('grid#foo').
            row(42).
                cell('firstName').
                reveal().
                click(10, 10).
                textLike(/^Hello$/).
                and(function (cell) {
                    expect(cell.el.hasCls('somecls')).toBe(true);
                });
    });
    

    很多其它定位器 Locators

    在这个样例中, 位于 ST.grid() 后面的2个调用是定位方法: row() 和 cell()

    有非常多方式能够描写叙述目标行和列。这些相应的方法的名字以“row”和“cell”开头。在本例中, 我们使用的方法接收行记录的 id (42) 和 列id(“firstName”)。

    一旦我们调用了 row() 方法, 后面的方法链调用则都在此行(row)之上。我们能够通过调用行(row)的 grid() 方法使操作对象回到原来的 grid。例如以下。

    ST.grid('grid#foo').
        row(42).
            reveal().  // scroll the row into view
            click(10, 10).
        grid().row(999).  // pick a different row
            reveal().
            click(10, 10);
    

    对 列(cell) 来说也是类似的:

    ST.grid('grid#foo').
        row(42).
            cell('firstName').  // column id
                reveal().  // scroll cell into view
                click(10, 10).
            row().   // return to row 42
            cell('lastName').
                reveal().
                click(10, 10).
        grid().row(999).
            reveal().
            click(10, 10);
    

    很多其它动作 Actions

    组件 futures 层次结构中的类,为 Ext JS 框架中几个最实用的方法,提供了动作方法。比方。 ST.future.Panel 提供了 collapse() 和 expand() 动作方法。

    这些动作方法为合适的 panel 在正确的时机被调用.

    很多其它状态 States

    组件 futures 还提供了额外的 状态方法. 比方, ST.future.Panel 提供了collapsed() 和 expanded() 状态方法。它们会安排一个延时等待 panel 处于目标状态。

    继承得到的状态 States

    由于ST.future.Component 继承自 ST.future.Element, 所以它继承得到了大部分动作和状态方法. 这样的继承会随着 futures 类的层次结构继续下去. 比方, ST.future.ComboBox 继承自 ST.future.TextField , ST.future.TextField 又继承自  ST.future.Field 。  ST.future.Field  又继承自 ST.future.Component.

    使用 Jasmine 交互

    Sencha Test 与 Jasmine 的集成设计同意 futures 与 Jasmine 传统风格的异步測试协调工作。

    只是, 在使用 futures 时。通常没有必要使用 Jasmine 的 done 函数。就像上面的样例。

    当 future 的一系列操作完毕后, 測试就即将完毕了, Jasmine 会继续下一个測试。

    还有, future 序列中的每一步,都能够控制自己的超时时间, 没有必要为整个測试确定一个超时时间。

    由于每一个 future 动作也是5秒超时, 所以通常不必显式地设置一个它。

    futures API 的还有一个长处是,它利用 and(), 来提供了一种简洁的方式。把异步操作、等待条件和同步检查 混合起来使用。这样的做法避免了使用 done 函数, 使測试复杂性降到最低。

    避免反复代码 Keeping DRY

    Futures 使測试能够遵循 DRY (Don’t Repeat Yourself,避免反复代码) 原则。能够考虑使用以下的方式,而不是在用到的时候才去创建 future 实例.

    describe('Many tests', function () {
        var Page = {
            fooGrid: function () {
                return ST.grid('grid#foo');
            },
            nameField: function () {
                return ST.textField('textfield[name="username"]');
            }
        };
    
        it('might take some time', function () {
            Page.fooGrid().row(42).
                reveal().
                click(10, 10);
        });
    
        it('might take some more time', function () {
            Page.fooGrid().row(999).
                reveal().
                click(10, 10);
        });
    });
    

    正如上文所述, 我们仅仅是创建了一个包括一组方法的名为“Page”的对象。这样的方法使測试封装了測试对象(即应用程序)的定位器。

    假设 page 对象在多个測试中都会实用到, 我们能够把它放在 describe() 块外面, 并给它一个更合适的名称。由于 Sencha Test 在这样的场景下会载入全部 JavaScript 文件, page 对象将对全部的測试场景都可用。

    在不同场景中共享 page 对象, 能够把他们加入到測试项目的 附加库列表(Additional Libraries list) 中。

    结论

    我们希望本文能够让你对 怎样使用 Sencha Test Futures API 来解决异步測试的复杂问题,有个初步了解。请看 API 文档 , 查阅全部已经提供的动作和状态方法, 当然, 还能够寻找很多其它关于未来版本号 Ext JS 组件和特性。祝你測试快乐!




    欢迎增加Sencha Touch + Phonegap交流群

    1群:194182999 (满)

    2群:419834979

    共同学习交流(博主QQ:479858761


  • 相关阅读:
    《网络攻防与实践》第九周学习
    《网络攻防技术与实践》第八周作业
    《网络攻击技术与实践》第七周作业
    《网络攻防技术与实践》第六周学习
    《网络攻防技术与实践》第五周作业
    《网络攻防技术与实践》第四周学习
    《网络攻防技术与实践》第三周学习总结
    《网络攻防技术与实践》第二周学习总结
    20169214 2016-2017-2 《网络攻防实践》第十一周实验 SQL注入
    20169214 2016-2017-2 《移动平台开发实践》Android程序设计 实验报告
  • 原文地址:https://www.cnblogs.com/yjbjingcha/p/7400615.html
Copyright © 2011-2022 走看看