原文链接: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

Sencha Test Futures API 探秘的更多相关文章

  1. sencha touch api 使用指南

    本文主要讲解如何使用sencha touch的api以及如何查看api中官方示例源码 前期准备 1.sdk 下载地址:http://www.sencha.com/products/touch/down ...

  2. Scala 并行和并发编程-Futures 和 Promises【翻译】

    官网地址 本文内容 简介 Futures 阻塞 异常 Promises 工具 最近看了<七周七语言:理解多种编程泛型>,介绍了七种语言(四种编程范型)的主要特性:基本语法,集合,并行/并发 ...

  3. 【翻译】探究Ext JS 5和Sencha Touch的布局系统

    原文:Exploring the Layout System in Ext JS 5 and Sencha Touch 布局系统是Sencha框架中最强大和最有特色的一个部分. 布局要处理应用程序中每 ...

  4. 网页股票期货历史数据(API)

    //[和讯数据] //大商所DCE.郑商所CZCE.上期所SHFE3.中金所CFFEX //期货1分钟线http://webftcn.hermes.hexun.com/ ... I1709&d ...

  5. 用 Sencha Touch 构建移动 web 应用程序

    Sencha Touch 是一个使用 HTML5.CSS3 和 JavaScript 语言构建的移动 web 应用程序框架,在本文中,学习如何应用您当前的 web 开发技能进行移动 web 开发.下载 ...

  6. scala Futures and Promises

    http://docs.scala-lang.org/overviews/core/futures.html  Futures and Promises   By: Philipp Haller, A ...

  7. Future与Promise

    https://code.csdn.NET/DOC_Scala/chinese_scala_offical_document/file/Futures-and-Promises-cn.md#ancho ...

  8. Sencha touch API

    Sencha touch  API http://docs.sencha.com/touch/2.3.1/#!/guide/getting_started

  9. sencha touch 扩展篇之使用sass自定义主题样式 (上)使用官方的api修改主题样式

    大家知道,sencha touch是通过我们写的js代码来动态渲染单页面生成一个个div+css的html页面来模拟app应用,那么既然是div+css结构的,我们就可以通过修改css样式来自定义我们 ...

随机推荐

  1. roadhogrc.mock.js配置

    1.roadhogrc.mock.js const fs=require('fs'); const path=require('path'); const mockPath=path.join(__d ...

  2. lightgbm 学习笔记

    首先是配置文件参数.参考自https://lightgbm.apachecn.org/#/docs/6 配置参数实在是太多了,大家还是去原文档查表吧orz 参数名 可选参数 作用 config= 自填 ...

  3. jQuery选择器总结(重要)

    jQuery 的选择器可谓之强大无比,这里简单地总结一下常用的元素查找方法 $("#myELement") 选择id值等于myElement的元素,id值不能重复在文档中只能有一个 ...

  4. android hook 框架 xposed 如何实现挂钩

    Android so注入-libinject2 简介.编译.运行 Android so注入-libinject2  如何实现so注入 Android so注入-Libinject 如何实现so注入 A ...

  5. c专家编程读书笔记

    无论在什么时候,如果遇到malloc(strlen(str));,几乎可以直接断定他是错误的,而malloc(strlen(str)+1):才是正确的: 一个L的NUL哟关于结束一个ACSII字符串: ...

  6. ZOJ2112 Dynamic Rankings(整体二分)

    今天学习了一个奇技淫巧--整体二分.关于整体二分的一些理论性的东西,可以参见XRH的<浅谈数据结构题的几个非经典解法>.然后下面是一些个人的心得体会吧,写下来希望加深一下自己的理解,或者如 ...

  7. Codeforces Round #446 (Div. 2) C. Pride【】

    C. Pride time limit per test 2 seconds memory limit per test 256 megabytes input standard input outp ...

  8. 整数划分问题(记忆化搜索和DP方法)

    一. 问题 现在有一正整数N,要把它分为若干正整数之和,问有多少种本质不同的分法? (1)其中最大数不超过m, 有多少种分法? (2)分割后的正整数的数目不超过m个, 有多少种分法? (3)分成最大数 ...

  9. Codevs1026 SEARCH(逃跑的拉尔夫 )(BFS)

    SEARCH 时间限制: 1 Sec  内存限制: 128 MB提交: 11  解决: 4[提交][状态][讨论版] 题目描述 年轻的拉尔夫开玩笑地从一个小镇上偷走了一辆车,但他没想到的是那辆车属于警 ...

  10. iOS duplicate symbol for architecture arm64 解决办法

    导致这个问题的原因有多种: 1.重复定义了const常量. 2.多个第三方库同时用到了某个函数库. 暂时列举这几种,以后遇到了其他原因再加.