Macaca 编写移动端 Macaca 测试用例 [单步调试]

鹤见 · April 05, 2016 · Last by 小马 replied at October 10, 2016 · 5125 hits
本帖已被设为精华帖!

前言

macaca

图片亮点自寻。

移动端UI自动化测试与普通的单元测试有一个让人很苦恼的区别,就是测试的前置条件要求太高,先要启动一个模拟器或者插上一台真机,然后安装需要测试的 App,随后启动才能开始跑测试用例,整个过程耗时可能要一两分钟,若由于某个用例没有通过,同一个流程后面的所有用例都可能不过,又得修改用例,然后重新跑一次,那么每次修改之后都得有那么一两分钟是用来准备前置的 App 的,实在是太浪费时间了,有没有办法能够解决这个问题,只要启动一次,就能让我们可以测试当前的 App 呢,答案是肯定的。

介绍

启动一个 Macaca 服务器

Macaca 客户端本身就已经集成了 Webdriver 协议服务端的实现,通常在运行用例时,我们采用 Mocha 框架自动读取并运行 test 文件夹下的所有用例,除了这种方式,我们还可以选择仅开启一个 Macaca Server,然后利用 Webdriver 客户端的库,一步步地执行测试用例。

启动 Macaca 服务器

macaca server --verbose

Macaca 服务器

从终端看到,当前的服务器已经成功启动并监听本地的3456端口。此时,我们便可以利用 Webdriver Client 端来发送请求给 3456 端口进行一系列操作。

在 REPL 中进行测试

Webdriver 协议采用了 CS 模型,利用HTTP 协议进行通信,整个过程是异步无状态的,所以我们可以在开启 Macaca Server 后,利用 Node 的 REPL 环境进行测试。

整个过程如下图所示:

  • 新开一个终端,进入项目的目录下,输入 node, 进入 REPL 环境。
cd macaca-ios-test-sample
node
>

利用 devtool 代替 REPL 进行测试。

devtool 是一个利用了 Chrome DevTools 的程序调试工具,相对于 REPL,调试和开发更加方便。

安装 devtool,由于网络原因,devtool 依赖的 electron-prebuilt 官方下载很慢。可以通过设置环境变量使用 taobao npm 镜像:
export ELECTRON_MIRROR=https://npm.taobao.org/mirrors/electron/

cnpm i -g devtool

进入项目目录下,执行 devtool

cd macaca-ios-test-sample
devtool

此时会弹出一个 Chrome 的 DevTools,随后就可以进入 Console 进行操作。

devtool 截图

  • 启动模拟器,安装 App
> const wd = require('wd');
> const driver = wd.promiseChainRemote({
host: 'localhost',
port: 3456
});

> driver.init({
platformName: 'ios',
platformVersion: '9.3',
deviceName: 'iPhone 6s',
app: '/Users/ziczhu/Code/macaca/macaca-ios-test-sample/app/ios-app-bootstrap.zip'
});

启动模拟器,安装App

模拟器截图0

  • 登录应用
> driver
.waitForElementByXPath('//UIATextField[1]')
.sendKeys('loginName')
.waitForElementByXPath('//UIASecureTextField[1]')
.sendKeys('123456')
.sleep(1000)
.sendKeys('\n')
.waitForElementByName('Login')
.click();

登陆应用

模拟器截图1

  • 测试相关
> driver
.contexts()
.then(arr => {
return driver
.context(arr[0]);
})
.elementByName('Baidu')
.click()
.contexts()
.then(arr => {
return driver
.context(arr[arr.length - 1]);
})
.elementById('index-kw')
.sendKeys('TesterHome')
.elementById('index-bn')
.tap()

百度搜索

模拟器截图2

  • 退出应用
> driver
.contexts()
.then(arr => {
return driver
.context(arr[0]);
})
.elementByName('PERSONAL')
.click()

结束登出

上述代码和 App 均来自 macaca-ios-test-sample

在 REPL 中进行测试相对于直接执行文件有了更多的灵活性,我们可以反复通过不同的方式去进行测试,例如利用 XPath 或者 CSS 获取元素等,不用担心因为元素查找错误而直接结束用例。我们推荐可以先在 REPL 中进行编写,等得到正确的结果之后,再将其编写成标准的用例格式,进行回归测试,而不是一开始就完全写成测试用例去执行,这样会浪费大量时间在启动模拟器和安装 APP 之上。

另外,需要注意的是,大部分的 Webdriver Client 实现都是基于 Promise 的,所有操作的结果都是异步的,并不是常规的将结果作为返回值的函数,如果想要得到某个步骤的返回值输出,需要在结尾跟上 then 去解析结果。

 > driver
.currentContext()
.then(console.log.bind(console))
// NATIVE_APP

> driver
.elementByName('Baidu')
.then(console.log.bind(console))
// PromiseElement {value: 7, browser: PromiseWebdriver}

当然,为了安全起见,最好在 then 的第二个参数也加上一个函数来捕捉可能出现的错误信息,比如当我查询一个不存在的元素时:

> driver
.elementByName('Google')
.then(console.log.bind(console), console.log.bind(console))
// Error: [elementByName("Google")] Error response status: 7, , NoSuchElement - An element could not be located on the page using the given search parameters.

参考资料

共收到 34 条回复 时间 点赞

亲测使用devtool的方式调试非常好用

@ziczhu 执行 cnpm i -g devtool 会很慢,怎么解决

@tsj1107 这个是否支持页面滑动操作,以及是否可以识别自定义控件

#3楼 期待 @tsj1107 分享个滑动滚动的示例,有这方面问题的人很多, @kasi

在真机调试的时候总是报错,求解决~

@lylh osx和xcode升级到最新

#6楼 @xdf 都升级到最新版也是这样。。。。

技术小白,求助报 Error: Cannot find module 'webdriver-client',

@ziczhu 你文章里没提及啊

鹤见 #11 · April 13, 2016 作者

#9楼 @jessiezhou0412 请在一个安装了 webdriver-client 的目录下启动 devtool, cnpm i webdriver-client

跨应用的调用可以测吗?

#12楼 @mengfeiyang 跨应用怎么理解

#13楼 @xdf 就是比如在A.app中打开B.app,操作了之后返回A.app继续操作

@mengfeiyang 可以实现,不过麻烦一些。Macaca支持多session,可以quit一个driver后唤起另一个driver,如此切换。

其实,我还是不懂。开发提供的app包,里面的控件命名要怎样的规范化,控件元素名称我不清楚。

还有很多脚本写法,我不知道要怎样下手,之前是用appium,采用java.

我从来都是直接打LOG看结果

#19楼 @unbug 是说打哪里的log

浏览下!

Macaca也是行为驱动吗?

#22楼 @cuckoo_du Macaca是测试框架啊,行为驱动是一种测试风格,随你选择风格

wanghaifengdeiMac:macaca-test $ macaca install ios
macaca-ios is installing for the first time with args: ["install","macaca-ios","-—unsafe-perm=true","--registry=https://registry.npmjs.org/"]


\ loading...macaca-cli@1.0.35 /usr/local/lib/node_modules/macaca-cli
└── macaca-ios@1.0.30 extraneous
npm ERR! Darwin 15.3.0
npm ERR! argv "/usr/local/bin/node" "/usr/local/bin/npm" "install" "macaca-ios" "-—unsafe-perm=true" "--registry=https://registry.npmjs.org/"
npm ERR! node v6.2.0
npm ERR! npm v3.8.9
npm ERR! path /usr/local/lib/node_modules/macaca-cli/node_modules/.staging/macaca-cli-4d061662
npm ERR! code ENOENT
npm ERR! errno -2
npm ERR! syscall rename

npm ERR! enoent ENOENT: no such file or directory, rename '/usr/local/lib/node_modules/macaca-cli/node_modules/.staging/macaca-cli-4d061662' -> '/usr/local/lib/node_modules/macaca-cli'
npm ERR! enoent ENOENT: no such file or directory, rename '/usr/local/lib/node_modules/macaca-cli/node_modules/.staging/macaca-cli-4d061662' -> '/usr/local/lib/node_modules/macaca-cli'
npm ERR! enoent This is most likely not a problem with npm itself
npm ERR! enoent and is related to npm not being able to find a file.
npm ERR! enoent
npm ERR! Darwin 15.3.0
npm ERR! argv "/usr/local/bin/node" "/usr/local/bin/npm" "install" "macaca-ios" "-—unsafe-perm=true" "--registry=https://registry.npmjs.org/"
npm ERR! node v6.2.0
npm ERR! npm v3.8.9
npm ERR! path npm-debug.log.147207587
npm ERR! code ENOENT
npm ERR! errno -2
npm ERR! syscall open

npm ERR! enoent ENOENT: no such file or directory, open 'npm-debug.log.147207587'
npm ERR! enoent ENOENT: no such file or directory, open 'npm-debug.log.147207587'
npm ERR! enoent This is most likely not a problem with npm itself
npm ERR! enoent and is related to npm not being able to find a file.
npm ERR! enoent

npm ERR! Please include the following file with any support request:
npm ERR! /usr/local/lib/node_modules/macaca-cli/npm-debug.log

npm install exited with code 254 and signal null
install macaca-ios failed with Error: npm ERR! Darwin 15.3.0
npm ERR! argv "/usr/local/bin/node" "/usr/local/bin/npm" "install" "macaca-ios" "-—unsafe-perm=true" "--registry=https://registry.npmjs.org/"
npm ERR! node v6.2.0
npm ERR! npm v3.8.9
npm ERR! path /usr/local/lib/node_modules/macaca-cli/node_modules/.staging/macaca-cli-4d061662
npm ERR! code ENOENT
npm ERR! errno -2
npm ERR! syscall rename

npm ERR! enoent ENOENT: no such file or directory, rename '/usr/local/lib/node_modules/macaca-cli/node_modules/.staging/macaca-cli-4d061662' -> '/usr/local/lib/node_modules/macaca-cli'
npm ERR! enoent ENOENT: no such file or directory, rename '/usr/local/lib/node_modules/macaca-cli/node_modules/.staging/macaca-cli-4d061662' -> '/usr/local/lib/node_modules/macaca-cli'
npm ERR! enoent This is most likely not a problem with npm itself
npm ERR! enoent and is related to npm not being able to find a file.
npm ERR! enoent
npm ERR! Darwin 15.3.0
npm ERR! argv "/usr/local/bin/node" "/usr/local/bin/npm" "install" "macaca-ios" "-—unsafe-perm=true" "--registry=https://registry.npmjs.org/"
npm ERR! node v6.2.0
npm ERR! npm v3.8.9
npm ERR! path npm-debug.log.147207587
npm ERR! code ENOENT
npm ERR! errno -2
npm ERR! syscall open

npm ERR! enoent ENOENT: no such file or directory, open 'npm-debug.log.147207587'
npm ERR! enoent ENOENT: no such file or directory, open 'npm-debug.log.147207587'
npm ERR! enoent This is most likely not a problem with npm itself
npm ERR! enoent and is related to npm not being able to find a file.
npm ERR! enoent

npm ERR! Please include the following file with any support request:
npm ERR! /usr/local/lib/node_modules/macaca-cli/npm-debug.log

你好,请问这是什么原因?

@lihuazhang 楼上跟你一样啊,看来问题很多啊

#25楼 @xdf 嗯 这个问题得解决。npm creates a .staging directory during install,但是特么又找不到。

#24楼 @wangcityboy 用 npm@2.15.5

@wangcityboy 可以使用 npm i macaca-ios -g

xdf [Topic was deleted] 中提及了此贴 27 Jun 11:17
xdf [Topic was deleted] 中提及了此贴 27 Jun 11:17

@ziczhu devtool 不支持win10平台环境吗? 还是我安装没成功

D:\macaca\macaca-desktop-browser>npm i devtool -g
D:\nodejs\node-global\devtool -> D:\nodejs\node-global\node_modules\devtool\bin\index.js
D:\nodejs\node-global
`-- devtool@2.0.3

npm WARN optional Skipping failed optional dependency /devtool/chokidar/fsevents:
npm WARN notsup Not compatible with your operating system or architecture: fsevents@1.0.14

D:\macaca\macaca-desktop-browser>devtool
fs.js:549
return binding.open(pathModule._makeLong(path), stringToFlags(flags), mode);
^

Error: ENOENT: no such file or directory, open 'D:\nodejs\node-global\node_modules\devtool\node_modules\electron-prebuilt\path.txt'
at Error (native)
at Object.fs.openSync (fs.js:549:18)
at Object.fs.readFileSync (fs.js:397:15)
at Object. (D:\nodejs\node-global\node_modules\devtool\node_modules\electron-prebuilt\index.js:4:42)
at Module._compile (module.js:409:26)
at Object.Module._extensions..js (module.js:416:10)
at Module.load (module.js:343:32)
at Function.Module._load (module.js:300:12)
at Module.require (module.js:353:17)
at require (internal/module.js:12:17)

sorry 自己又鼓捣好了。是假性安装成功,实际并没有安装成功。
假性安装成功的日志如下:
npm i devtool -g
D:\nodejs\node-global\devtool -> D:\nodejs\node-global\node_modules\devtool\bin\index.js
D:\nodejs\node-global
`-- devtool@2.0.3

npm WARN optional Skipping failed optional dependency /devtool/chokidar/fsevents:
npm WARN notsup Not compatible with your operating system or architecture: fsevents@1.0.14

记得每次 卡进度 ctrl+c 结束掉后upm uninstall devtool -g 一下。 否则下次再执行 npm i devtool -g 会假性安装成功 实际运行devtool又会报错。

总是卡进度,没办法换下安装源头
C:\Users\cmd>npm config get registry
http://registry.cnpmjs.org/

C:\Users\cmd>npm config set registry http://registry.npm.taobao.org

C:\Users\cmd>npm config get registry
http://registry.npm.taobao.org/

C:\Users\cmd>npm i devtool -g
D:\nodejs\node-global\devtool -> D:\nodejs\node-global\node_modules\devtool\bin\index.js

electron-prebuilt@1.1.1 postinstall D:\nodejs\node-global\node_modules\devtool\node_modules\electron-prebuilt
node install.js

Downloading electron-v1.1.1-win32-x64.zip
[============================================>] 100.0% of 51.47 MB (2.39 MB/s)
D:\nodejs\node-global
-- devtool@2.0.3
+-- browser-resolve@1.11.2
|
-- resolve@1.1.7
+-- chokidar@1.6.0
| +-- anymatch@1.3.0
| | +-- arrify@1.0.1
| | `-- micromatch@2.3.11
| | +-- arr-diff@2.0.0
略掉以下

这样看到依赖组件目录树了 才算真正安装成功。

@ziczhu

按照你的步骤执行到这里,报错了 没找到webdriver-client。。。请问该如何解决

遇到的这个问题,咨询作者说是devtool工具的问题。已经提了issue
https://github.com/alibaba/macaca/issues/97

也希望macaca团队能重视下。对于国内大多数公司的非测试开发人员来说,稍微有些运维和开发的弄这个确实遇到好多问题。
1 希望能把教程分平台环境写, 比如win10 linux mac。这样才算真正的跨平台支持。
2 希望针对用例脚本的书写 再多些分享。比如 这篇就很不错。但引用到的技术也是相当多概念的。对于希望深入的使用者还是有难度的。
3 希望能添加下 对IDE 工具,macaca语法提示插件的支持,比如webstorm。


经过不懈的研究琢磨,尝试。终于摸清webstorm 是在此处添加语法提示插件。
但是在此处搜索macaca发现该地址并未提供语法插件支持,https://github.com/DefinitelyTyped/DefinitelyTyped
直接去也搜不到macaca 到是搜到了mocha 和webdriverio 。

并且我们看到,mocha支持的after 框架语法,找到了语法提示文件 ***.mocha.d.ts.

希望macaca项目也能支持 语法提示插件啊。

小马 [Topic was deleted] 中提及了此贴 08 Aug 16:32
小马 [Topic was deleted] 中提及了此贴 09 Aug 10:55

MAC安装完毕devtool后,启动devtool,

cd macaca-ios-test-sample
devtool

然后界面中输入第一行指令就出错,devtool中指令:

const wd = require('wd');

报错内容为:

module.js:442 Uncaught Error: Cannot find module 'wd'()

还请问下是什么原因?我看截图是top frame,装好后只能选top,不知道是否和这个有关

补充:直接在REPL中执行也是报错,确定是回复中说的devtool问题?

> const wd = require('wd');
TypeError: Identifier 'wd' has already been declared
at repl:1:1
at REPLServer.defaultEval (repl.js:262:27)
at bound (domain.js:287:14)
at REPLServer.runBound [as eval] (domain.js:300:12)
at REPLServer.<anonymous> (repl.js:431:12)
at emitOne (events.js:82:20)
at REPLServer.emit (events.js:169:7)
at REPLServer.Interface._onLine (readline.js:211:10)
at REPLServer.Interface._line (readline.js:550:8)
at REPLServer.Interface._ttyWrite (readline.js:827:14)
小马 [Topic was deleted] 中提及了此贴 10 Oct 10:21
bruno yang Koa 在 Macaca 中的实践 中提及了此贴 27 Nov 10:22
需要 Sign In 后方可回复, 如果你还没有账号请点击这里 Sign Up