Macaca 如何重头开始编辑一个自己的基于 web 浏览器的 macaca 用例脚本项目

老马 · 2016年08月08日 · 最后由 测试抗巴子 回复于 2017年06月26日 · 4022 次阅读

该文为 macaca 的 nodejs 版本 样例https://github.com/macacajs/macaca-test-sample
macaca java 版本 https://github.com/macacajs/wd.java
macaca python 版本 https://github.com/macacajs/wd.py

一 建立一个新用例脚本项目

D:\macaca\me-app

拷贝 D:\macaca\macaca-test-sample-master 官方示例脚本下的依赖文件 app 、package.json、 README.md

到新项目 me-app 下。为图方便。macaca-test 文件夹也整个 copy 过来。

2016年8月10日补充:
我们来看下 package.json

{
  "name": "macaca-test-sample",
  "version": "1.0.8",
  "description": "aicai-sample",
  "keywords": [
    "macaca",
    "sample"
  ],

  /*"repository": {
    "type": "git",
    "url": "git://github.com/macacajs/macaca-test-sample.git"
  },*/

  "dependencies": {
    "macaca-utils": "^0.1.8"
  },
  "devDependencies": {
    "jshint": "*",
    "macaca-cli": "^1.1.0",
    "pre-commit": "1.1.1",
    "webdriver-client": "~1.0.0"
  },

  "scripts": {
    "test": "make test-pc",
    "jshint": "make jshint"
  },

  "pre-commit": [
    "jshint"
  ],
  "license": "MIT"
}

package.json 主要是用来配置依赖的 nodejs 模块的,dependencies 是配置所依赖的模块 ,devDependencies 是用来配置开发环境下依赖的模块。
你可以根据需要在这里来编辑项目组件依赖和其他一些配置。大家要自己从头写的话,还是要熟悉这里。

二 创建用例脚本文件 *.test.js

D:\macaca\me-app\macaca-test

将示例脚本 macaca-desktop-sample.test.js 重命名为 H5-aicai-sample.test.js

开始编辑修改 H5-aicai-sample.test.js 脚本的内容。

三 编辑业务流脚本内容

涉及到用一些工具来定位元素

3.1 chrome 浏览器的 DevTools

新开一 chrome 窗口,直接按 F12 快捷键调出该工具。

然后你可以调整下用哪类 devices 分辨率来展示页面。

然后 URL 栏输入需要查看的地址。

最后你便可以用查看元素工具来定位元素 ID 等资源信息了。

3.2 firefox 浏览器的 firebug

如果是 xpath 定位的话,有一个有用的插件 FirePath.

https://addons.mozilla.org/zh-CN/firefox/addon/firepath/

最后 H5-aicai-sample.test.js 脚本内容如下

只是简单的测试下,看是否可以如此构建自己的用例项目。所以业务流程只是简单的 输入用户名 输入密码 点击登录,由于还不会破验证码没输入所以会提示 ‘请输入验证码’。同时 注释掉删除掉了一些验证步骤和自己不了解的原脚本内容。
2016年8月10日修改后

'use strict';

var wd = require('webdriver-client')({
  platformName: 'desktop',
  browserName: 'chrome'
});

describe('aicai-sample', function() {
  this.timeout(5 * 60 * 1000);

  const driver = wd.initPromiseChain();
  const initialURL = 'http://m.aicai.com/m/login.do?agentId=1&vt=5';

  before(() => {
    return driver
      .initDriver()
      .setWindowSize(1280, 800)
      .sleep(3000);
  });

  it('#0 should go into H5login', function() {
    return driver
      .get(initialURL)
      .sleep(5000);
  });

  it('#1 should edit webform H55login and prompt 请输入验证码 ', function() {
    return driver
      .elementById('jq_account')
      .sendKeys('h5test0808a')
      .sleep(3000)

      .elementById('jq_password')
      .sendKeys('0808a123')
      .sleep(3000)

      .elementById('submit')
      .click()
      .sleep(3000)

      .source()
      .then(function(html) {
       html.should.containEql('请输入验证码');
     })
  });


  after((done) => {
    return driver
      .quit(done);
  });
});

这次加入了断言代码也就是

 .source()
 .then(function(html) {
  html.should.containEql('请输入验证码');
})

该段。这段是这样的, 先调用.source() 获取当前的一个 html 页面数据,然后结合 should.js 断言库,判断这个 html 是否包含对应的字符串.
关于 should.js 请查看http://shouldjs.github.io/

那么实际也可以用https://macacajs.github.io/macaca-wd/api/#hasElement has 系列的是 macaca 封装好的断言 API

再补充下,像脚本里的这些框架代码
describe
before
it
after 来自于 mocha.js 关于 mocha.js 请查看http://mochajs.org/

四 运行环境准备工作

老样子,你需要到 D:\macaca\me-app> 目录下执行下 npm i 来为 me-app 准备 macaca 的组件包依赖。

成功看到安装成功日志后,接下来便可以执行用例脚本了。

五 执行用例脚本

D:\macaca\me-app\macaca-test>dir



 驱动器 D 中的卷没有标签。

 卷的序列号是 0A87-8753

 D:\macaca\me-app\macaca-test 的目录

2016/08/08  14:40    <DIR>          .

2016/08/08  14:40    <DIR>          ..

2016/08/08  14:12             2,876 androidapp-acp-sample.test.js

2016/08/04  16:27               638 debug.log

2016/08/08  14:58             1,746 H5-aicai-sample.test.js

2016/07/23  02:59             1,437 macaca-mobile-browser-sample.test.js

2016/07/23  02:59                33 mocha.opts

2016/08/04  17:53                22 test.js

               6 个文件          6,752 字节

               2 个目录 101,416,828,928 可用字节


D:\macaca\me-app\macaca-test>macaca run -d H5-aicai-sample.test.js --verbose
>> index.js:17:12 [master] pid:11912 webdriver server start with config:
 { port: 3456,
  window: true,
  ip: '*.*.*.*',
  host: 'cmd-PC',
  loaded_time: '2016-08-10 11:15:32' }
>> middlewares.js:17:10 [master] pid:11912 base middlewares attached
>> router.js:108:10 [master] pid:11912 router set
>> webdriver sdk launched
>>

>>
  aicai-sample

>> responseHandler.js:11:12 [master] pid:11912 Recieve HTTP Request from Client: method: POST url: /wd/hub/session, jsonBody: {"desiredCapabilities":{"autoAcceptAlerts":true,"browserName":"chrome","platformName":"desktop","version":"","javascriptEnabled":true,"platform":"ANY"}}
>> session.js:47:10 [master] pid:11912 Creating session, sessionId: d7c46de0-03e3-48bc-bfdb-9c8a39e71ad7.
>> chromedriver bin path: D:\nodejs\node-global\node_modules\macaca-chrome\node_modules\macaca-chromedriver\exec\chromedriver.exe
>> macaca-chromedriver.js:89:16 [master] pid:11912 Noting to kill.
>> kill all chromedriver process success!
>> Starting ChromeDriver 2.20.353145 (343b531d31eeb933ec778dbcf7081628a1396067) on port 9515
Only local connections are allowed.

>> chromedriver starting success.
>> proxy.js:52:14 [master] pid:11912 Proxy: /status:GET to http://localhost:9515/wd/hub/status:GET with body:
>> proxy.js:58:16 [master] pid:11912 Got response with status 200: "{\"sessionId\":\"\",\"status\":0,\"value\":{\"build\":{\"version\":\"alpha\"},\"os\":{\"arch\":\"x86_64\",\"name\":\"Windows NT\",\"version\":\"10.0\"}}}"
>> proxy.js:52:14 [master] pid:11912 Proxy: /session:POST to http://localhost:9515/wd/hub/session:POST with body: {"desiredCapabilities":{"autoAcceptAlerts":true,"browserName":"chrome","platformName":"desktop","version":"","javascriptEnabled":true,"platform":"ANY","window":true}}
>> proxy.js:58:16 [master] pid:11912 Got response with status 200: {"sessionId":"ef744a2babc69552261dffd7dacfccfd","status":0,"value":{"acceptSslCerts":true,"applicationCacheEnabled":false,"browserConnectionEnabled":false,"browserName":"chrome","chrome":{"userData...
>> chromedriver ready with: {"sessionId":null,"status":0,"value":{"acceptSslCerts":true,"applicationCacheEnabled":false,"browserConnectionEnabled":false,"browserName":"chrome","chrome":{"userDataDir":"C:\\Users\\cmd\\AppData\\Local\\Temp\\scoped_dir1300_27322"},"cssSelectorsEnabled":true,"databaseEnabled":false,"handlesAlerts":true,"hasTouchScreen":false,"javascriptEnabled":true,"locationContextEnabled":true,"mobileEmulationEnabled":false,"nativeEvents":true,"platform":"Windows NT","rotatable":false,"takesHeapSnapshot":true,"takesScreenshot":true,"version":"52.0.2743.82","webStorageEnabled":true}}
>> responseHandler.js:43:14 [master] pid:11912 Send HTTP Respone to Client: {"sessionId":"d7c46de0-03e3-48bc-bfdb-9c8a39e71ad7","status":0,"value":"{\"autoAcceptAlerts\":true,\"browserName\":\"chrome\",\"platformName\":\"desktop\",\"version\":\"\",\"javascriptEnabled\":true,\"platform\":\"ANY\",\"window\":true}"}
>> responseHandler.js:11:12 [master] pid:11912 Recieve HTTP Request from Client: method: POST url: /wd/hub/session/d7c46de0-03e3-48bc-bfdb-9c8a39e71ad7/window/current/size, jsonBody: {"width":1280,"height":800}
>> proxy.js:52:14 [master] pid:11912 Proxy: /wd/hub/session/d7c46de0-03e3-48bc-bfdb-9c8a39e71ad7/window/current/size:POST to http://localhost:9515/wd/hub/session/ef744a2babc69552261dffd7dacfccfd/window/current/size:POST with body: {"width":1280,"height":800}
>> proxy.js:58:16 [master] pid:11912 Got response with status 200: {"sessionId":"ef744a2babc69552261dffd7dacfccfd","status":0,"value":null}
>> session.js:107:14 [master] pid:11912 Send HTTP Respone to Client: {"sessionId":"d7c46de0-03e3-48bc-bfdb-9c8a39e71ad7","status":0,"value":null}
>> responseHandler.js:11:12 [master] pid:11912 Recieve HTTP Request from Client: method: POST url: /wd/hub/session/d7c46de0-03e3-48bc-bfdb-9c8a39e71ad7/url, jsonBody: {"url":"http://m.aicai.com/m/login.do?agentId=1&vt=5"}
>> proxy.js:52:14 [master] pid:11912 Proxy: /wd/hub/session/d7c46de0-03e3-48bc-bfdb-9c8a39e71ad7/url:POST to http://localhost:9515/wd/hub/session/ef744a2babc69552261dffd7dacfccfd/url:POST with body: {"url":"http://m.aicai.com/m/login.do?agentId=1&vt=5"}
>> proxy.js:58:16 [master] pid:11912 Got response with status 200: {"sessionId":"ef744a2babc69552261dffd7dacfccfd","status":0,"value":null}
>> session.js:107:14 [master] pid:11912 Send HTTP Respone to Client: {"sessionId":"d7c46de0-03e3-48bc-bfdb-9c8a39e71ad7","status":0,"value":null}
>>
>>     √ #0 should go into H5login (6071ms)

>> responseHandler.js:11:12 [master] pid:11912 Recieve HTTP Request from Client: method: POST url: /wd/hub/session/d7c46de0-03e3-48bc-bfdb-9c8a39e71ad7/element, jsonBody: {"using":"id","value":"jq_account"}
>> proxy.js:52:14 [master] pid:11912 Proxy: /wd/hub/session/d7c46de0-03e3-48bc-bfdb-9c8a39e71ad7/element:POST to http://localhost:9515/wd/hub/session/ef744a2babc69552261dffd7dacfccfd/element:POST with body: {"using":"id","value":"jq_account"}
>> proxy.js:58:16 [master] pid:11912 Got response with status 200: {"sessionId":"ef744a2babc69552261dffd7dacfccfd","status":0,"value":{"ELEMENT":"0.8424815980731128-1"}}
>> session.js:107:14 [master] pid:11912 Send HTTP Respone to Client: {"sessionId":"d7c46de0-03e3-48bc-bfdb-9c8a39e71ad7","status":0,"value":"{\"ELEMENT\":\"0.8424815980731128-1\"}"}
>> responseHandler.js:11:12 [master] pid:11912 Recieve HTTP Request from Client: method: POST url: /wd/hub/session/d7c46de0-03e3-48bc-bfdb-9c8a39e71ad7/element/0.8424815980731128-1/value, jsonBody: {"value":["h5test0808a"]}
>> proxy.js:52:14 [master] pid:11912 Proxy: /wd/hub/session/d7c46de0-03e3-48bc-bfdb-9c8a39e71ad7/element/0.8424815980731128-1/value:POST to http://localhost:9515/wd/hub/session/ef744a2babc69552261dffd7dacfccfd/element/0.8424815980731128-1/value:POST with body: {"value":["h5test0808a"]}
>> proxy.js:58:16 [master] pid:11912 Got response with status 200: {"sessionId":"ef744a2babc69552261dffd7dacfccfd","status":0,"value":null}
>> session.js:107:14 [master] pid:11912 Send HTTP Respone to Client: {"sessionId":"d7c46de0-03e3-48bc-bfdb-9c8a39e71ad7","status":0,"value":null}
>> responseHandler.js:11:12 [master] pid:11912 Recieve HTTP Request from Client: method: POST url: /wd/hub/session/d7c46de0-03e3-48bc-bfdb-9c8a39e71ad7/element, jsonBody: {"using":"id","value":"jq_password"}
>> proxy.js:52:14 [master] pid:11912 Proxy: /wd/hub/session/d7c46de0-03e3-48bc-bfdb-9c8a39e71ad7/element:POST to http://localhost:9515/wd/hub/session/ef744a2babc69552261dffd7dacfccfd/element:POST with body: {"using":"id","value":"jq_password"}
>> proxy.js:58:16 [master] pid:11912 Got response with status 200: {"sessionId":"ef744a2babc69552261dffd7dacfccfd","status":0,"value":{"ELEMENT":"0.8424815980731128-2"}}
>> session.js:107:14 [master] pid:11912 Send HTTP Respone to Client: {"sessionId":"d7c46de0-03e3-48bc-bfdb-9c8a39e71ad7","status":0,"value":"{\"ELEMENT\":\"0.8424815980731128-2\"}"}
>> responseHandler.js:11:12 [master] pid:11912 Recieve HTTP Request from Client: method: POST url: /wd/hub/session/d7c46de0-03e3-48bc-bfdb-9c8a39e71ad7/element/0.8424815980731128-2/value, jsonBody: {"value":["0808a123"]}
>> proxy.js:52:14 [master] pid:11912 Proxy: /wd/hub/session/d7c46de0-03e3-48bc-bfdb-9c8a39e71ad7/element/0.8424815980731128-2/value:POST to http://localhost:9515/wd/hub/session/ef744a2babc69552261dffd7dacfccfd/element/0.8424815980731128-2/value:POST with body: {"value":["0808a123"]}
>> proxy.js:58:16 [master] pid:11912 Got response with status 200: {"sessionId":"ef744a2babc69552261dffd7dacfccfd","status":0,"value":null}
>> session.js:107:14 [master] pid:11912 Send HTTP Respone to Client: {"sessionId":"d7c46de0-03e3-48bc-bfdb-9c8a39e71ad7","status":0,"value":null}
>> responseHandler.js:11:12 [master] pid:11912 Recieve HTTP Request from Client: method: POST url: /wd/hub/session/d7c46de0-03e3-48bc-bfdb-9c8a39e71ad7/element, jsonBody: {"using":"id","value":"submit"}
>> proxy.js:52:14 [master] pid:11912 Proxy: /wd/hub/session/d7c46de0-03e3-48bc-bfdb-9c8a39e71ad7/element:POST to http://localhost:9515/wd/hub/session/ef744a2babc69552261dffd7dacfccfd/element:POST with body: {"using":"id","value":"submit"}
>> proxy.js:58:16 [master] pid:11912 Got response with status 200: {"sessionId":"ef744a2babc69552261dffd7dacfccfd","status":0,"value":{"ELEMENT":"0.8424815980731128-3"}}
>> session.js:107:14 [master] pid:11912 Send HTTP Respone to Client: {"sessionId":"d7c46de0-03e3-48bc-bfdb-9c8a39e71ad7","status":0,"value":"{\"ELEMENT\":\"0.8424815980731128-3\"}"}
>> responseHandler.js:11:12 [master] pid:11912 Recieve HTTP Request from Client: method: POST url: /wd/hub/session/d7c46de0-03e3-48bc-bfdb-9c8a39e71ad7/element/0.8424815980731128-3/click, jsonBody: {}
>> proxy.js:52:14 [master] pid:11912 Proxy: /wd/hub/session/d7c46de0-03e3-48bc-bfdb-9c8a39e71ad7/element/0.8424815980731128-3/click:POST to http://localhost:9515/wd/hub/session/ef744a2babc69552261dffd7dacfccfd/element/0.8424815980731128-3/click:POST with body: {}
>> proxy.js:58:16 [master] pid:11912 Got response with status 200: {"sessionId":"ef744a2babc69552261dffd7dacfccfd","status":0,"value":null}
>> session.js:107:14 [master] pid:11912 Send HTTP Respone to Client: {"sessionId":"d7c46de0-03e3-48bc-bfdb-9c8a39e71ad7","status":0,"value":null}
>> responseHandler.js:11:12 [master] pid:11912 Recieve HTTP Request from Client: method: GET url: /wd/hub/session/d7c46de0-03e3-48bc-bfdb-9c8a39e71ad7/source, jsonBody: {}
>> proxy.js:52:14 [master] pid:11912 Proxy: /wd/hub/session/d7c46de0-03e3-48bc-bfdb-9c8a39e71ad7/source:GET to http://localhost:9515/wd/hub/session/ef744a2babc69552261dffd7dacfccfd/source:GET with body: {}
>> proxy.js:58:16 [master] pid:11912 Got response with status 200: {"sessionId":"ef744a2babc69552261dffd7dacfccfd","status":0,"value":"<!DOCTYPE html><html xmlns=\"http://www.w3.org/1999/xhtml\" lang=\"en\"><head><link href=\"http://m.aicaicdn.com/wap5/js/??plugin...
>> session.js:107:14 [master] pid:11912 Send HTTP Respone to Client: {"sessionId":"d7c46de0-03e3-48bc-bfdb-9c8a39e71ad7","status":0,"value":"\"<!DOCTYPE html><html xmlns=\\\"http://www.w3.org/1999/xhtml\\\" lang=\\\"en\\\"><head><link href=\\\"http://m.aicaicdn.com/wap5/js/??plugins/lhgdialog/skins/chrome.css\\\" rel=\\\"stylesheet\\\" id=\\\"lhgdialoglink\\\" />\\n\\t<meta charset=\\\"utf-8\\\" />\\n\\t<meta name=\\\"viewport\\\" content=\\\"width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, minimal-ui\\\" /> \\n\\t<meta name=\\\"format-detection\\..."}
>>
>>#1 should edit webform H55login and login (9543ms)

>> responseHandler.js:11:12 [master] pid:11912 Recieve HTTP Request from Client: method: DELETE url: /wd/hub/session/d7c46de0-03e3-48bc-bfdb-9c8a39e71ad7, jsonBody: {}
>> macaca-chromedriver.js:141:18 [master] pid:11912 chromedriver exit with code: 1, signal: null
>> session.js:80:12 [master] pid:11912 Delete session, sessionId: d7c46de0-03e3-48bc-bfdb-9c8a39e71ad7
>> responseHandler.js:43:14 [master] pid:11912 Send HTTP Respone to Client: {"sessionId":"d7c46de0-03e3-48bc-bfdb-9c8a39e71ad7","status":0}
>>

>>
  2 passing (21s)


>> Test completed!


相关知识栈:

macaca https://github.com/macacajs
macaca API http://macacajs.github.io/macaca-wd/api/

nodejs http://nqdeng.github.io/7-days-nodejs/

mocha.js 脚本组织框架 http://mochajs.org/ https://github.com/mochajs/mocha

should.js macaca 引用的一个断言库 http://shouldjs.github.io/

wd.js http://admc.io/wd/ https://github.com/admc/wd

webdriverio https://github.com/webdriverio

建议从上往下看,围绕自家业务流程脚本为目标,以当前业务脚本实现遇到的实际问题为出发点;
前期不要搞的太复杂,想的太完美;
能用 macaca API 最原生支持的解决业务脚本问题,就不要过度扩展使用自己不熟悉的组件包。

以下为参考的文章,向作者表示感谢,提供了思路。
如何从头编写你的 Macaca 测试用例
编写移动端 Macaca 测试用例 [单步调试]
Macaca-iOS 入门那些事 2
[基于 Node.js 的自动化测试-Macaca] - 自动化测试实践总结

更多信息请参考 wiki 汇总

小马的 macaca 入门指引合集

如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
共收到 7 条回复 时间 点赞
老马 [该话题已被删除] 中提及了此贴 08月09日 10:55
老马 [该话题已被删除] 中提及了此贴 10月10日 10:21

我能问一下,macaca 发现了 bug,可以用什么办法可以读取浏览器或者移动设备的 log 并记录吗,小白的我只晓得截图。

@Cononico 你说的 bug 是需测项目的 bug 吗? 如果是,要看你是安卓还是 ios app 或者是 web 网页。不同的平台使用的技术都有差异。另,要看你发现的是什么类型的 bug,如果是基于 macaca 的功能回归的,基本都是界面元素断言来判断某一业务功能是否在 UI 层成功,如果是这类失败就 try cache 截图,如果是 java 构建的 macaca 自动化 可以用其他日志工具 比如 maven surefire-report 和 testng 结合来获取运行日志。 其他手段 安卓的话可以 adb log 命令 adb 相关的去获取或查看手机端执行日志。

index.js:17:12 [master] pid:14172 webdriver server start with config:
{ port: 3456,
verbose: false,
always: true,
window: true,
ip: '192.168.2.168',
host: 'sunyakuan-PC',
loaded_time: '2016-12-09 17:15:17' }
middlewares.js:17:10 [master] pid:14172 base middlewares attached
router.js:129:10 [master] pid:14172 router set
webdriver sdk launched
E:\node\node_modules\macaca-cli\lib\run\index.js:44
throw err;
^

Error: Cannot find test framework "mocha" in E:\macaca\demo\macaca-test-sample-n
odejs-master\macaca-test\node_modules
at Runner.initFramework (E:\node\node_modules\macaca-cli\lib\run\index.js:71
:13)
at co.then (E:\node\node_modules\macaca-cli\lib\run\index.js:41:10)
at process._tickCallback (internal/process/next_tick.js:103:7)

npm 下载的依赖里面是有 mocha 的,请问下遇到过这样的问题了的吗?

#7 楼 @sunkuan2007 我也遇到这个问题 请问你解决里面?如果解决了 麻烦告诉下你是怎么解决呢

#8 楼 @xiaocong168 😂 周末把所有安装都删除了重新安装了一次还是报错,你解决了给我说下。。。

#9 楼 @sunkuan2007 我也还没解决 搞了两天了

erinet 回复

搞定了吗? 我擦 烦人啊

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册