1.Macaca简介
Macaca是阿里巴巴集团开发的一套完整的自动化测试解决方案。
2.Macaca特性:
- 支持移动端和PC端
- 支持Native, Hybrid, H5 等多种应用类型
- 提供客户端工具和持续集成服务
3.macaca-cli客户端的安装:
3.1安装 Node.js
请安装 Node.js v4.0 或者更高版本,装好 Node.js 后命令行里就已经集成了 npm 工具,为了提高安装模块的速度,请使用国内的 cnpm。
3.2 iOS 环境安装
请安装 Xcode8 或者更高版本
需要安装 usbmuxd 以便于通过 USB 通道测试 iOS 真机,不需要测试真机则不用安装
$ brew install usbmuxd
应用中如含有 WebView,请安装 ios-webkit-debug-proxy
$ brew install ios-webkit-debug-proxy
备注:使用brew命令需要安装Homebrew(一款常用的 MacOS 的包管理器),请按照官网提示安装。
准备 App 包:如需要测试 iOS 应用,请使用 Scheme 设置为 debug 的 .app 包。
3.3 Android环境安装
3.3.1 安装 JDK
配置 JAVA_HOME,根据你所使用的 shell 工具修改不同的文件,比如 ~/.bashrc, ~/.bash_profile, ~/.zshrc
shell export JAVA_HOME=path/to/your/Java/Home
3.3.2安装安卓 SDK
运行 brew install android-sdk,然后安装18-24版本中的任一 SDK
shell 环境设置 ANDROID_HOME 根据你所使用的Terminal修改不同的
文件,比如~/.bashrc, ~/.bash_profile, ~/.zshrc
# 如果是通过homebrew安装的android-sdk,则路径如下
export ANDROID_HOME = /usr/local/opt/android-sdk
# 如果通过其他方式安装的sdk,路径设置为对应的android sdk的路径
export ANDROID_HOME = path/to/your/Android/sdk
注意:准备 App 包:如需要测试 Android 应用,请使用 .apk 格式的包。
3.4 全局安装macaca
$ npm i -g macaca-cli
如果看到如下可爱的小猴子,那恭喜你安装成功啦!重新安装则会覆盖更新。
3.5安装驱动
3.6 环境检查
通过 macaca doctor 可以检查环境是否配置成功
$ macaca doctor
如上图所示则表示环境均配置正常,如果有错误,会出现红色的提示。
4 运行官方示例
将官方示例(mobile-app-sample-nodejs)克隆到本地,更多的示例请访问macaca-sample。
$ git clone https://github.com/macaca-sample/mobile-app-sample-nodejs.git --depth=1
$ cd mobile-app-sample-nodejs
$ npm i
# 更多运行方式见Makefile
$ macaca run --verbose
4.1 Android 的自动化测试
先在mobile-app-sample-nodejs/macaca-test/mobile-app-sample.test.js脚本文件中如果是ios该为Android。
var platform = process.env.platform || 'Android';
platform = platform.toLowerCase();
在mobile-app-sample-nodejs目录下执行
macaca run
测试的过程
lidongdeMacBook-Pro:mobile-app-sample-nodejs lidong$ macaca run ./macaca-test/macaca-mobile-sample.test.js
>> webdriver sdk launched
>>
>>
>> macaca mobile sample
>> get /Users/lidong/.macaca-temp/android_app_bootstrap-debug.apk from cache
>> sha:e2ca601f9ee1ec101326d12377a2e8d4
INSTRUMENTATION_STATUS: numtests=1
INSTRUMENTATION_STATUS: stream=
com.android.uiautomator.client.Initialize:
INSTRUMENTATION_STATUS: id=UiAutomatorTestRunner
INSTRUMENTATION_STATUS: test=testStartServer
INSTRUMENTATION_STATUS: class=com.android.uiautomator.client.Initialize
INSTRUMENTATION_STATUS: current=1
INSTRUMENTATION_STATUS_CODE: 1
uiautomator start socket server.
>> socket server ready
>> socket client ready
recive: {"cmd":"wake","args":{}}
return: {"success":true,"data":{"status":0,"value":true}}
recive: {"cmd":"getWindowSize","args":{}}
return: {"success":true,"data":{"status":0,"value":"{\"width\":1080,\"height\":1794}"}}
>> current window size {"width":1080,"height":1794}
recive: {"cmd":"find","args":{"strategy":"class name","selector":"android.widget.EditText","multiple":true}}
return: {"success":true,"data":{"status":0,"value":[{"ELEMENT":"1"},{"ELEMENT":"2"}]}}
recive: {"cmd":"clearText","args":{"elementId":"1"}}
return: {"success":true,"data":{"status":0,"value":true}}
recive: {"cmd":"setText","args":{"elementId":"1","text":"中文+Test+12345678"}}
return: {"success":true,"data":{"status":0,"value":true}}
recive: {"cmd":"find","args":{"strategy":"class name","selector":"android.widget.EditText","multiple":true}}
return: {"success":true,"data":{"status":0,"value":[{"ELEMENT":"3"},{"ELEMENT":"4"}]}}
recive: {"cmd":"clearText","args":{"elementId":"4"}}
return: {"success":true,"data":{"status":0,"value":true}}
recive: {"cmd":"setText","args":{"elementId":"4","text":"111111"}}
return: {"success":true,"data":{"status":0,"value":true}}
recive: {"cmd":"find","args":{"strategy":"name","selector":"Login","multiple":true}}
return: {"success":true,"data":{"status":0,"value":[{"ELEMENT":"5"}]}}
recive: {"cmd":"click","args":{"elementId":"5"}}
return: {"success":true,"data":{"status":0,"value":true}}
>>
>> ✓ #1 should login success (19613ms)
recive: {"cmd":"getSource","args":{}}
return: {"success":true,"data":{"status":0,"value":true}}
>> { hierarchy:
{ rotation: '0',
node:
{ index: '0',
class: 'android.widget.FrameLayout',
package: 'com.github.android_app_bootstrap',
checkable: 'false',
checked: 'false',
clickable: 'false',
enabled: 'true',
focusable: 'false',
focused: 'false',
scrollable: 'false',
'long-clickable': 'false',
password: 'false',
selected: 'false',
bounds: '[0,0][1080,1794]',
node: [Object] } } }
>>
>> ✓ #2 should display home (911ms)
recive: {"cmd":"find","args":{"strategy":"name","selector":"list","multiple":false}}
等等
4.2 IOS 的自动化测试
先在mobile-app-sample-nodejs/macaca-test/mobile-app-sample.test.js脚本文件中如果是Android改为ios。
var platform = process.env.platform || 'ios';
platform = platform.toLowerCase();
在mobile-app-sample-nodejs目录下执行
macaca run
测试过程
lidongdeMacBook-Pro:mobile-app-sample-nodejs lidong$ macaca run ./macaca-test/macaca-mobile-sample.test.js
>> webdriver sdk launched
>>
>>
>> macaca mobile sample
>> get /Users/lidong/.macaca-temp/android_app_bootstrap-debug.apk from cache
>> sha:e2ca601f9ee1ec101326d12377a2e8d4
INSTRUMENTATION_STATUS: numtests=1
INSTRUMENTATION_STATUS: stream=
com.android.uiautomator.client.Initialize:
INSTRUMENTATION_STATUS: id=UiAutomatorTestRunner
INSTRUMENTATION_STATUS: test=testStartServer
INSTRUMENTATION_STATUS: class=com.android.uiautomator.client.Initialize
INSTRUMENTATION_STATUS: current=1
INSTRUMENTATION_STATUS_CODE: 1
uiautomator start socket server.
>> socket server ready
>> socket client ready
recive: {"cmd":"wake","args":{}}
return: {"success":true,"data":{"status":0,"value":true}}
recive: {"cmd":"getWindowSize","args":{}}
return: {"success":true,"data":{"status":0,"value":"{\"width\":1080,\"height\":1794}"}}
>> current window size {"width":1080,"height":1794}
recive: {"cmd":"find","args":{"strategy":"class name","selector":"android.widget.EditText","multiple":true}}
return: {"success":true,"data":{"status":0,"value":[{"ELEMENT":"1"},{"ELEMENT":"2"}]}}
recive: {"cmd":"clearText","args":{"elementId":"1"}}
return: {"success":true,"data":{"status":0,"value":true}}
5.脚本初始化参数
5.1 常见的参数
- platformName String 当前用例运行的平台 { iOS / Android / Desktop }
- browserName String 当前测试的浏览器名称 { iOS: Safari } { Android: Chrome } { Desktop: Chrome / Electron }
5.2 App 相关参数
- deviceName String 模拟器的名称,例如 ‘iPhone 6’ 或者 ‘Nexus 5x’。
- app Stirng .ipa,.app 或者 .apk 文件的绝对地址或者远程地址,或者是包含上述文件格式的 Zip 文件。
- udid String 测试设备的唯一设备 ID。
5.3 Android 的参数介绍
- reuse Number 0: 启动并安装 app。{1 (默认): 卸载并重装 app。 2: 仅重装 app。3: 在测试结束后保持 app 状态。}
- package String Android app 的 package name。
- activity String 启动时的 Activity name。
5.4 iOS 的参数介绍
- reuse Number 0: 清楚数据并重装 app。 1: (默认) 卸载并重装 app。 2: 仅重装 app。 3: 在测试结束后保持 app 状态。
- bundleId String 应用的 Bundle ID,例如 com.apple.Maps。
- autoAcceptAlerts Boolean 自动接受所有的系统弹窗信息。默认是 false。
- autoDismissAlerts Boolean 自动拒绝所有的系统弹窗信息。默认是 false。
5.5 基本用法
'use strict';
require('should');
var xml2map = require('xml2map');
var platform = process.env.platform || 'ios';
platform = platform.toLowerCase();
var pkg = require('../package');
/**
* download app form npm
*
* or use online resource: https://npmcdn.com/ios-app-bootstrap@latest/build/ios-app-bootstrap.zip
*
* npm i ios-app-bootstrap --save-dev
*
* var opts = {
* app: path.join(__dirname, '..', 'node_modules', 'ios-app-bootstrap', 'build', 'ios-app-bootstrap.zip');
* };
*/
// see: https://macacajs.github.io/desired-caps
var iOSOpts = {
deviceName: 'iPhone 5s',
platformName: 'iOS',
autoAcceptAlerts: false,
//reuse: 3,
//udid: '',
//bundleId: 'xudafeng.ios-app-bootstrap',
app: 'http://localhost:8087/ios-app-bootstrap.zip'
};
var androidOpts = {
platformName: 'Android',
autoAcceptAlerts: false,
// reuse: 3,
// udid: '',
// package: 'com.github.android_app_bootstrap',
// activity: 'com.github.android_app_bootstrap.activity.WelcomeActivity',
app: 'http://localhost:8087/android_app_bootstrap-debug.apk'
};
const isIOS = platform === 'ios';
const infoBoardId = isIOS ? 'info' : 'com.github.android_app_bootstrap:id/info';
const wd = require('macaca-wd');
// override custom wd
require('./wd-extend')(wd, isIOS);
describe('macaca mobile sample', function() {
this.timeout(5 * 60 * 1000);
const driver = wd.promiseChainRemote({
host: 'localhost',
port: 3456
});
driver.configureHttp({
timeout: 600 * 1000
});
before(function() {
return driver
.init(isIOS ? iOSOpts : androidOpts);
});
after(function() {
return driver
.sleep(1000)
.quit();
});
it('#1 should login success', function() {
return driver
.getWindowSize()
.then(size => {
console.log(`current window size ${JSON.stringify(size)}`);
})
.appLogin('中文+Test+12345678', '111111')
.sleep(1000);
});
Macaca自动化测试Android和IOS应用,基本上说到这里就要结束。后面我们还是学习如何自己写测试脚本。