该文为 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 是用来配置开发环境下依赖的模块。
你可以根据需要在这里来编辑项目组件依赖和其他一些配置。大家要自己从头写的话,还是要熟悉这里。
D:\macaca\me-app\macaca-test
将示例脚本 macaca-desktop-sample.test.js 重命名为 H5-aicai-sample.test.js
开始编辑修改 H5-aicai-sample.test.js 脚本的内容。
涉及到用一些工具来定位元素
新开一 chrome 窗口,直接按 F12 快捷键调出该工具。
然后你可以调整下用哪类 devices 分辨率来展示页面。
然后 URL 栏输入需要查看的地址。
最后你便可以用查看元素工具来定位元素 ID 等资源信息了。
如果是 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] - 自动化测试实践总结