MonkeyTalk 【翻译原创】(二)MonkeyTalk 语言参考说明

water · December 23, 2014 · Last by Haibo replied at September 13, 2015 · 976 hits
本帖已被设为精华帖!

注: MonkeyTalk脚本语言是简单而强大的,此说明书中详细说明了很多用法,由于内容比较多,未翻译完的地方会后续有时间补充。

概论:
MonkeyTalk是由用户层面的一系列简单命令组成的多功能测试语言。它足够简单地给测试人员使用,并且几乎不需要开发功底来进行分析,同时也可以给那些需要进一步编程的人员无缝地使用Java Script来编写。脚本可以由简单到由txt文档直接编写,或者由MonkeyTalk IDE等录制工具直接生成。
MonkeyTalk语言是与平台无关的,并且提供了标准的API,可以由任何一种编程语言来实现。MonkeyTalk 1.0中包含捆绑了Java Script语言。

命令语法:
它语法设计的出发点是让非开发人员也能轻易地看懂。它可读性高,可以使用简单的txt文本编辑器甚至表格来简单明了地阅读。另外,MonkeyTalk设计成可以用扁平表格编辑器例如MonkeyTalk IDE来进行阅读和编辑。
MonkeyTalk是一行作为一个一个命令的开始和结束,每一行遵从如下语法:
组件类型 MonkeyID 动作 各种参数... 修改器...
(ComponentType MonkeyId Action Args… Modifiers…)
总体说来,组件类型、MonkeyId、动作、参数、修改器合在一起构成命令的各个部分,组件类型所包含的动作就是这条命令的名字。
下面是各部分的说明:
1, 组件类型(必填):动作执行所在的组件的类型。例如按钮(Button)或文本框(TextArea)。组件类型是大小写不敏感的。组件类型可以扩展其他的组件类型,正如下面所说,还可以继承任何已定义的方法及其参数。组件类型是代表了UI组件的逻辑名字(例如叫Button而不叫UIButton),但也可以是特定平台的别名。所有的UI组件都继承自View类型的组件,所以当你指定View作为组件类型时就像使用通配符匹配所有类型的组件,例如:

# 点击带有"OK"标签的任何组件
View OK Tap

2,MonkeyId(必填):一个用来区分同一页面上同时显示的相同组件类型的不同组件标示。MonkeyId可以使用星号()表示识别到的第一个匹配类型的组件。
MonkeyId也可以规定用从1开始(不是从0开始)的引索以 #N 的格式来表示。这种情况下,MonkeyId标志了显示页面中的第N个匹配类型的组件。组件引索的顺序是按照坐标(x, y)从上到下、从左到右的进行排序的。
3,动作(必填):就是要执行的动作。例如包括 Tap, Select, 和EnterText等。动作(Action)是大小写不敏感的。
4,参数(按组件类型和动作需要填写):是一个或多个由空格隔开的列表。参数默认是从整条命令的第四列(第四部分)开始的。尽管它是以String类型表现,解读的时候是由命令的需要来进行解读的。如果某个参数是必须的但是没有填写(少写了最后一个参数),它就会使用默认值。参数可以使用星号(
)来强制使用它默认值。
5,修改器(选填):以空格隔开的、以%name=value格式表示的参数列表,%前缀用来标示它是一个修改器。有三个系统定义的修改器:
%timeout - 等待多少毫秒超时,超时之前重复尝试执行命令
%thinktime - 尝试执行第一次命令时的等待时间(毫秒)
%retrydelay - 再次多次尝试执行命令之间的间隔时间(毫秒)。(注:如果执行不成功就会继续尝试直到超时,例如页面还没刷新找不到组件)

命令举例:
所有的列都是以空格隔开的。带空格的值一定要用引号引起来。表示引号本身需要在双引号内用反斜杠转义,来表示引号本身。
点击OK按钮:

Button OK Tap

点击页面上的第二个按钮:

Button #2 Tap

点击页面上的第一个按钮:

Button * Tap

或者Button #1 Tap
点击页面上的第一个控件:

* * Tap

传入参数带空格:

TextArea editText1 enterText this is a test

设置动作超时时间为5秒

TextArea editText1 enterText this is a test %timeout=5000

注释是以#开头

# this is a comment
# another comment
Button OK Tap

换行用\n表示

Input shipping EnterText John Smith\n123 Main St.\nAnytown, USA 12345

脚本:
把一条或者多条MonkeyTalk命令放到一个文件中并保存为.mt文件你就得到了一个MonkeyTalk脚本。
举个例子,一个登陆的.mt脚本可能看起来是这样的:

# simple script to login as joe
Input username EnterText joe-at-doe.com
Input password EnterText i like cheese
Button LOGIN Tap

想在脚本中调用另一个脚本,可以使用Script命令加上.mt文件名作为MonkeyId,就像这样:Script login.mt Run

变量:
脚本中可以包含写法为 ${name} 的变量,并且可以在一条命令的任何地方使用。也可以包含写法类似于 ${var}的内置变量。
内置变量有 %{componentType}, %{monkeyId}, %{action}以及内置参数 %{1}, %{2}等等。变量只能作为命令的某一部分,包括组件类型、MonkeyId等等。
例如,一个已命名的变量可以作为参数:

Input username EnterText ${usr}

或者参数和MonkeyId:

Input ${foo} EnterText ${bar}

又或者整条命令都用参数:

${foo} ${bar} ${baz}

变量可以内嵌到某些字符串里面,但是不能内嵌到另一个变量名中,例如:

Input username EnterText ${usr}@example.com

但是下面这样的命令是不合法的:

Input username EnterText ${foo${bar}}

参数化脚本:
使用Vars.Define命令可以在脚本中命名变量并设置它们的默认值。让我们参数化我们的Login.mt脚本如下:

Vars * Define usr="default-at-example.com" pwd
Input username EnterText ${usr}
Input password EnterText ${pwd}
Button LOGIN Tap

我们设置了两个变量 ${usr} 和${pwd},并设置${usr}的默认值为default-at-example.com。${pwd}变量的默认值没有指定,所以默认值会是(以尖括号括起来的变量名)。
我们可以用如下方式调用我们的参数化脚本:

Script login.mt Run joe-at-doe.com "i like cheese"

或者让脚本参数使用默认值:

Script login.mt Run

或者使用一个星号来使用${usr}的默认值:

Script login.mt Run * password1

请注意变量只能在定义它们的脚本中使用,所以${usr} 和 ${pwd}只在login.mt中有定义。当然除非你使用变量来调用一个子脚本。

数据驱动脚本:
参数化脚本只是一个开始,MonkeyTalk支持全数据驱动的脚本,仅仅只要使用RunWith代替Run命令,并且设定一个数据文件作为第一个参数。
用我们的参数化脚本login.mt举例,我们首先编写一个数据文件credentials.csv,用csv格式保存如下:

joe-at-doe.com, "i like cheese"
alpha-at-beta.net, password1
charlie-at-dog.org, abc123

第一行可以指定变量名(与login.mt脚本最前面的Vars.Define中他们命名完全相同),后面各行指定变量值。MonkeyTalk需要CSV文件每一列以逗号隔开,如果带空格需要用双引号引起来。
现在,我们可以数据驱动我们的脚本:

Script login.mt RunWith credentials.csv

这会根据数据文件中的每一行数据跑一边login.mt脚本。所以这个例子中login.mt会运行3此,第一次运行时参数usr = joe-at-doe.com和pwd = "i like cheese",第二次 usr = alpha-at-beta.net 和pwd = password1,第三次usr = charlie-at-dog.org 和pwd = abc123。

RunIf命令:
使用RunIf命令,我们可以指定一个命令通过以后才跑某一个脚本。使用这条命令的方法是在一个带有Verify的命令执行通过以后跑指定一个脚本,使用命令如下:

Script YourScript.mt RunIf [Verify Command]

这意思是你在参数部分把脚本中的其他命令整个放在了里面。一个脚本例子如下:

Input username enterText Fred
Input password enterText SecurePassword
Button LOGIN tap
script logout.mt RunIf Label * Verify "Welcome, Fred!"

自定义命令:
MonkeyTalk语言可以通过自定义部件类型(component type)和动作(Action)来进行拓展。任何以两个部分组成,格式为..mt 命名的脚本自动可以作为自定义命令。例如,如果我们创建了一个名为 user.login.mt 的脚本,我们就可以增加一个user的部件类型,它拥有login的动作。
我们用以下的样式来调用新的自定义命令:

User * Login

并且我们可以传递MonkeyId以及参数:

User joe Login joespassword

在你自定义的命令中,可以使用%{monkeyId}的格式来使用传进来的monkeyId。下面是一个可以实现上面命令的user.login.mt脚本的例子:

Vars * Define pwd="password"
Input username enterText %{monkeyId}
Input password enterText ${pwd}
Button LOGIN tap

测试和验证:
一个测试(Test)就是使用Test部件来代替Script部件进行调用一个脚本。测试结果会写到一个标准的文件中,以JUnit-compatible xml文件格式保存。
每条命令的执行成功与否在于验证用户指定的界面部件(元素)是否存在。另外,你也可以在脚本中使用Verify动作来验证部件中的值是否与预期一致。首先,我们再次重写login.mt,加入一些Verify动作,像这样:

Vars * Define usr="default-at-example.com" pwd=name
Input username EnterText ${usr}
Input password EnterText ${pwd}
Button LOGIN Tap
Label welcome Verify "Welcome, ${name}!"
Button LOGOUT Verify

现在,我们可以以如下方式测试(Test)的方式来运行login.mt,值得注意的是,我们增加了${name}这个变量,因此我们需要加入第三个参数进行调用:

Test login.mt Run joe-at-doe.com "i like cheese" "Joe Doe"

并且我们也可以使用数据驱动的方式来测试我们的脚本(注意增加第三列的数据到credentials.csv)

Test login.mt RunWith credentials.csv

验证(Verify):
Verify动作存在于所有的部件中(除了Script 和 Device),用以验证实际的值是否是我们想要的值。在它的基本格式中,Verify接受三个可选参数:expectedValue, propPath, 以及failMessage。
如果没有传递任何参数,Verify只验证部件是否存在:

Button LOGIN Verify

当只有一个expectedValue参数时,Verify会检查部件中的值,这些值只会是部件逻辑上的值(Button的值是它的label,Input的值是它的text,CheckBox 的值是"On"或者"Off",等等):

Button LOGIN Verify LOGIN

用expectedValue以及 propPath作为参数时,Verify会检查制定的部件属性。一些propPaths 例如value或item是逻辑上MonkeyTalk指定的属性路径,它们是跨平台的(它们不以点作为开头)。部件指定的属性值是平台相关的(它们以点作为开头)。
验证一个iOS按钮的Font名字:

Button LOGIN Verify Helvetica .font.fontName

验证Android上RatingBar总的星星数量:

RatingBar reviewRating Verify 5 .numStars

最后一个参数时验证失败时给出的信息failMessage :

Input username Verify joe-at-doe.com value "bad username!!!"

可以在用户手册上查看更详细内容:
http://www.cloudmonkeymobile.com/monkeytalk-documentation/monkeytalk-user-guide/verifying-expected-values/using-verification-commands

测试套件(Suite)
一个测试套件(Suite)就是若干脚本的Test放在一起执行的集合。当一个Test失败时,它不会立刻停止,而是跑下一个Test。当所有的Test执行完毕时,会生成一个xUnit-compatible的报告(http://reflex.gforge.inria.fr/xunit.html#xunitReport), 报告会统计所有所跑Test的Pass数、Fail数、Error数。
Suite必须以.mts文件后缀结尾,与脚本区别开来。
Suite使用Test命令调用脚本,以"Test"作为部件类型,脚本名称作为monkeyId,Run或者Runwith作为动作(action)。一个Test命令(在Suite中使用)与Script命令(在Scripte中使用)类似;它只是增加了一些额外的管理功能。例如一个简单的Suite如下:

# login and log out
Test login.mt Run joe@doe.com JoEsPaSsWoRd
Test logout.mt

只有在Suite中可以使用Test命令,相反只有脚本中可以使用Scipt命令。一般来说,如果你想要跑一个脚本,就在Suite中调用Tests,在脚本中调用Script。
有时候一组Test会共享一些依赖及清理工作,在每个Test前后进行维护时非常无聊并且容易出错的。Suite允许你使用"Setup"以及"Teardown"部件类型来进行设置初始化及清理工作(分别在每一条Test前后执行),用法与Test命令非常类似。在Suite中,任何这样定义的Setup脚本都会在没一个Test前进行调用,如果初始化成功,Test就会运行,然后Teardown就会运行(无论Test成功与否)。
Suite里面可以调用其他的Suite,使用Suite部件类型。
Suite中只能包含Test, Setup, Teardown, 和Suite,以及注释。
举个例子,一个myapp.mts测试套件可能长这样:

# setup runs before every test
Setup login.mt Run joe@doe.com JoEsPaSsWoRd

# teardown runs after every test
TearDown logout.mt Run

# the tests...
Test add_contact.mt RunWith contacts.csv
Test remove_contact.mt RunWith contacts.csv

例子中我们就使用Setup 和TearDown来指定每条Test执行前后需要调用的脚本。

命令执行选项:
除非特殊指定,否则MonkeyTalk在超时时间之前会不停地尝试去执行命令。超时时间的值有一个为2秒的全局默认值,也可以在每一条语句后面使用超时的编辑器(Modifier)来自定义。
例如:

Button OK Tap %timeout=5000 %thinktime=2000 %retrydelay=123

上述命令会在尝试点击OK按钮之前等待2秒钟,然后每隔123毫秒会尝试一次执行命令,直到5秒的超时时间到。(命令最多会执行7秒钟)。

注:后面的一些内容为介绍Java Script语法、Java API、命令大全的内容,太多就不翻译了。有兴趣的童鞋可以访问连接查看:
http://www.cloudmonkeymobile.com/monkeytalk-documentation/monkeytalk-language-reference/scripting-javascript

到这里语法说明终于告一段落。由于最近比较懒,更新也是断断续续的,语法说明篇幅大概在4000字左右,请期待下一篇- 3-

如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
共收到 11 条回复 时间 点赞

Monkeytalk语法简明,初学者用起来比较方便,IDE做的比较烂,经常崩溃。

#1楼 @squallff 我用的时候目前没有崩溃过,你试试别用Pro版本? 可以脱离IDE写脚本,用Excel写都可以 - -!

第二篇了,加油!~

#3楼 @pajack 你的单元测试学的咋样?

@weamylady 没进展,先学习下Android 代码~

#2楼 @weamylady 我用的不是pro的,就是普通版。复杂的逻辑用mt语言写不了,只能用js写。扩展性不强。后来我们用MT提供的jar包做了个框架,写起来就顺手多了。

#6楼 @squallff 那是技术测试人员的思维惯性,一条一条单独的案例为何需要这么复杂的逻辑语言呢?一个案例整个流程下来应该是单线的,Pass就是Pass,Fail就是Fail。当然我同意Java API来编写顺手一点,自由性和逻辑性强很多,MonkeyTalk语言的简单的好处就是容易给编程功底弱的测试人员使用,容易推广,毕竟要你写所有案例的脚本太累了。

#6楼 @squallff 普通版本容易崩溃就用Pro Beta版本试试。

#1楼 @squallff 我用的也没崩溃过

#8楼 @weamylady 可能大家都是在windows系统上用的吧,我是OSX系统

@weamylady 大神最近还有在研究MonkeyTalk吗,可以跟你交流学习一下吗?

12Floor has been deleted
需要 Sign In 后方可回复, 如果你还没有账号请点击这里 Sign Up