代码改变世界

开源手机自动化测试框架iQuery入门教程(二)

2012-09-12 17:47  知平软件  阅读(1865)  评论(0编辑  收藏  举报

上次介绍iQuery之后,已经有些朋友在开始在手机自动化测试程序里试用iQuery了,由于之前的介绍文档比较含糊,先搁置扩展iQuery使其支持多种编程语言的系列文章,补充一下iQuery的入门教程,之前写的介绍性文章可以参考:
1.    开源类库iQuery Android版使用说明
2.    类jQuery selector的控件查询iQuery开源类库介绍
3.    开源手机自动化测试框架iQuery入门教程(一)

iQuery是一个开源的自动化测试框架项目,有兴趣的朋友可以在这里下载:https://github.com/vowei/iQuery/downloads

源码位置:https://github.com/vowei/iQuery

在iQuery里增加新的伪类

在前文开源类库iQuery Android版使用说明提到,iQuery语法包含有伪类、伪属性等概念,我们编写iQuery的一个主要目标就是对测试人员隐藏多平台上查找控件的差异性,而伪类和伪属性就是隐藏不同平台上控件差异性的核心方式,然而我们在开发iQuery的时候,只提供了少数几个伪类:
    :button – 代表按钮控件,在不同的移动操作系统上,iQuery会将button这个伪类转换相应的按钮控件。
    :checkbox – 代表复选框控件。
    :radio – 代表单选框控件。
    :text – 代表文本编辑框控件。
    :label – 代表文本标签控件。
    :image – 代表图片控件。

这样做的目的是想保持iQuery的简洁性,同时iQuery也提供了方法让用户测试开发工程师注册自定义的伪类。

比如说要注册一个新的伪类“:switch”,这个伪类在iOS平台上,代表“UIASwitch”类型的控件,在Android平台上,代表“CheckBox”控件,注册的方式如下:

Android:

iQueryParser parser = iQuery.createParser(“:switch”);
parser. registerPseudoClass(“switch”, new IPseudoClass() {
    public boolean resolve(ITreeNode node) {
        return filterByNameEndsWith(node, "CheckBox");
    }
});

在上例中,第一行首先创建一个iQueryParser对象,使用iQuery.createParser(String iquery)这个函数创建,如果看源码可知,由这个函数创建的iQueryParser对象会注册默认的伪类。第2行之后,通过iQueryParser.registerPseudoClass对象注册伪类,该函数接受一个字符串参数 – 要注册的伪类名,第二个参数是一个实现了IPseudoClass的对象,是一个回调函数,当iQueryParser碰到非默认的伪类时,会调用这个函数判断一个UI控件对象是否归属于这个伪类。

iOS:

var iq = new iQuery(“:switch”, true);
iq.parser. registerPseudoClass(“switch”, function(uiaobj) {
    return isMatch(uiaobj, new Array(“UIASwitch”));
});

跟Android版类似,第一行先创建一个iQuery对象,然后在第二行通过iQuery.parser实例变量的registerPseudoClass函数注册一个伪类,和判断控件是否属于该伪类的回调函数。

在iQuery里增加新的伪属性


跟伪类相似,iQuery默认仅仅支持很少的伪属性:
    [:top] – 表示一个控件的左上角的y坐标值。
    [:left] – 表示一个控件的左上角的x坐标值。
    [:bottom] – 表示一个控件的右下角的y坐标值。
    [:right] – 表示一个控件的右下角的x坐标值。
    [:width] – 表示一个控件的宽度。
    [:height] – 表示一个控件的高度。

如果要注册一个新的伪属性,例如要注册一个表示控件上文本的伪属性:“:text”,在Android平台上,对于一些控件,例如按钮(Button)控件,表示其“mText”属性,而在iOS上,则是按钮控件的“name”属性。下面是注册伪属性的方法:

Android:

iQueryParser parser = iQuery.createParser(“:switch”);
parser. registerPseudoAttribute (“text”, new IPseudoAttribute () {
public String resolve(ITreeNode node) {
        return node.getProperty("mText").getValue();
    }
});

在上例中,第1行跟伪类相似,第2行后使用iQueryParser. registerPseudoAttribute函数注册一个新的伪属性“text”,iQueryParser通过调用一个IPseudoAttribute接口类型的回调函数来获取伪属性的值。

iOS:

var iq = new iQuery(“:switch”, true);
iq.parser.registerPseudoAttrs("text", function(uiaobj) {
    if ( uiaobj != undefined && uiaobj.rect != undefined ) {
        return uiaobj.name();
    }
});

在上例中,第1行创建一个iQuery解析器,第二行注册“text”伪属性,和返回伪属性值的回调函数。

为了简单起见,伪属性要求返回的属性值是字符串格式,而iQuery解析器在执行属性值对比时,会根据给出的查询上下文做相应的转换。比如说:
1.    针对查询语句:
“[:text = ‘abc’]”

由于:text返回的属性值是字符串格式,而对比的期望值也是字符串格式:“’abc’”,因此通过普通的字符串对比来完成过滤操作。

详情请参看源代码:
https://github.com/vowei/iQuery/blob/master/iOS/lib/iQuery.g 中对“'[' ':' attr=ELEMENT op v=QUOTED_STRING ']'”的处理,本文写作时,为源代码的“184 - 219”行。

https://github.com/vowei/iQuery/blob/master/java/iquery/iquery-core/src/main/java/cc/iqa/iquery/iQuery.g 中对“'[' ':' attr=ELEMENT op v=QUOTED_STRING ']'”的处理,本文写作时,为源代码的“388 - 424”行。

2.    而针对查询语句:
“[:top = 123]”
虽然:top返回的属性值是字符串格式,由于对比的期望值是数字格式:“123”,因此在对比时,iQuery会将:top返回的字符串格式的属性值转化成数字,然后再做对比。

详情请参看源代码:
https://github.com/vowei/iQuery/blob/master/iOS/lib/iQuery.g 中对“'[' attr=ELEMENT num_comp_op v=(INTEGER | FLOAT | PERCENTAGE) ']'”的处理,本文写作时,为源代码的“257 - 293”行。

https://github.com/vowei/iQuery/blob/master/java/iquery/iquery-core/src/main/java/cc/iqa/iquery/iQuery.g 中对“'[' attr=ELEMENT num_comp_op v=(INTEGER | FLOAT | PERCENTAGE) ']'”的处理,本文写作时,为源代码的“425 - 479”行。

3.    但是对于查询语句:
“[:text = 123]”
由于:text返回的是字符串格式,而期望值“123”是一个数字格式,iQueryParser无法将:text的值转换成数字,因此可能会报错。

对于iQuery对伪类和伪属性的扩展就暂时讲到这里,后文讲解避免重复注册伪类和伪属性的方法。