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

鹤见 · 2016年04月05日 · 最后由 老马 回复于 2016年10月10日 · 3213 次阅读
本帖已被设为精华帖!

前言

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 条回复 时间 点赞
达峰的夏天 [该话题已被删除] 中提及了此贴 06月27日 11:17

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

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

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

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

@ziczhu 你文章里没提及啊

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

@lylh osx 和 xcode 升级到最新

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

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

鹤见 #11 · 2016年04月13日 Author

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

匿名 #34 · 2016年04月13日

跨应用的调用可以测吗?

匿名 #14 · 2016年04月13日

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

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

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

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

Macaca 也是行为驱动吗?

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

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

浏览下!

#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,但是特么又找不到。

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

@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 项目也能支持 语法提示插件啊。

老马 [该话题已被删除] 中提及了此贴 08月08日 16:32
老马 [该话题已被删除] 中提及了此贴 08月09日 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)
老马 [该话题已被删除] 中提及了此贴 10月10日 10:21
bruno yang Koa 在 Macaca 中的实践 中提及了此贴 11月27日 10:22
达峰的夏天 [该话题已被删除] 中提及了此贴 06月27日 11:17
需要 登录 后方可回复, 如果你还没有账号请点击这里 注册