小东子的个人技术专栏

Macaca自动化测试Android和IOS应用

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修改不同的

1
2
3
4
5
6
7
8
文件,比如~/.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。

1
2
3
4
5
$ 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。

1
2
var platform = process.env.platform || 'Android';
platform = platform.toLowerCase();

在mobile-app-sample-nodejs目录下执行

macaca run

测试的过程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
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。

1
2
var platform = process.env.platform || 'ios';
platform = platform.toLowerCase();

在mobile-app-sample-nodejs目录下执行

macaca run

测试过程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
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 常见的参数

  1. platformName String 当前用例运行的平台 { iOS / Android / Desktop }
  2. browserName String 当前测试的浏览器名称 { iOS: Safari } { Android: Chrome } { Desktop: Chrome / Electron }

5.2 App 相关参数

  1. deviceName String 模拟器的名称,例如 ‘iPhone 6’ 或者 ‘Nexus 5x’。

  2. app Stirng .ipa,.app 或者 .apk 文件的绝对地址或者远程地址,或者是包含上述文件格式的 Zip 文件。

  3. udid String 测试设备的唯一设备 ID。

    5.3 Android 的参数介绍

  4. reuse Number 0: 启动并安装 app。{1 (默认): 卸载并重装 app。 2: 仅重装 app。3: 在测试结束后保持 app 状态。}

  5. package String Android app 的 package name。
  6. activity String 启动时的 Activity name。

5.4 iOS 的参数介绍

  1. reuse Number 0: 清楚数据并重装 app。 1: (默认) 卸载并重装 app。 2: 仅重装 app。 3: 在测试结束后保持 app 状态。
  2. bundleId String 应用的 Bundle ID,例如 com.apple.Maps。
  3. autoAcceptAlerts Boolean 自动接受所有的系统弹窗信息。默认是 false。
  4. autoDismissAlerts Boolean 自动拒绝所有的系统弹窗信息。默认是 false。

    5.5 基本用法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
'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应用,基本上说到这里就要结束。后面我们还是学习如何自己写测试脚本。