TA的每日心情 | 擦汗 4 小时前 |
---|
签到天数: 1047 天 连续签到: 5 天 [LV.10]测试总司令
|
Appium是一款开源测试工具,可以用来测试安卓/iOS/Windows端的原生应用和Web混合应用。
工作原理
Appium有一个客户端-服务器架构。Appium客户端向Appium服务器(一个Node.js HTTP服务器)发送请求,反过来,Appium服务器向执行动作的设备发送请求。然后,服务器将结果返回给客户端,让你知道测试的状态。
功能
·跨平台
· 多开发语言支持
· 不需要重新编译应用程序
· 不需要重复找轮子,可共用API
· 市场占有率TOP1
优点
1. 方便的切换测试原生应用或App内嵌的web页面,对Hybrid App友好。
2. 使用各个平台自身提供的测试框架,因此无需引入第三方代码或重新打包应用。
3. 开源,维护频率很高,社区也有相对较高的活跃度。
4. 支持通过自定义插件寻找元素。
缺点
1. 不支持单元测试、跨应用测试。
2. 测试效率相对较低。
使用
默认您已经安装node以及对应的Android或IOS等相关环境
使用appium有两种方式:
方式1:npm;
方式2:下载Appium Desktop,这是一种基于图形的、基于桌面的方式来启动 Appium 服务器。
这里主要介绍npm的使用方式
step 1: 安装appium
npm install -g appium
step 2: 安装webdriverio
npm install --save webdriverio @wdio/cli
webdriverio是什么?
基于Node.js的下一代浏览器和移动自动化测试框架。
生成 Web 驱动程序配置文件以在测试时应用配置。
step 3: 配置webdriverio
执行npx wdio config:
生成的文件目录如下:
及wdio.conf.js配置文件复制并修改有注释的字段到你的wdio.config.js文件。
- exports.config = {
- port: 4723,
- services: [['appium', {command: 'appium'}]],
- runner: 'local',
- specs: ['./test/specs/**/*.js'], // 测试目录
- maxInstances: 1,
- capabilities: [
- {
- maxInstances: 1,
- browserName: '',
- appiumVersion: '1.22.3', // appium -v 获取
- platformName: 'Android',
- platformVersion: '9', // 安卓版本
- deviceName: 'Nexus_S_API_28', // 设备名称 执行adb -s emulator-5554 emu avd name 获取
- app: './android/app/build/outputs/apk/debug/app-debug.apk', // apk目录, 没有的话先在Android studio build一个
- automationName: 'UiAutomator2',
- },
- ],
- logLevel: 'trace',
- bail: 0,
- waitforTimeout: 10000,
- connectionRetryTimeout: 90000,
- connectionRetryCount: 3,
- framework: 'mocha',
- reporters: ['dot'],
- mochaOpts: {
- ui: 'bdd',
- timeout: 60000,
- },
- };
复制代码
step 4: 创建一个测试用例
修改test/specs/example.e2e.js文件。
- describe('Simple App testing', () => {
- beforeEach(async () => {
- const app = await $('~app-root');
- await app.waitForDisplayed(10000, false);
- });
- it('Login test: valid case', async () => {
- const username = await $('~username');
- await username.setValue('codemagic');
- const password = await $('~password');
- await password.setValue('nevercode');
- const loginBtn = await $('~login');
- await loginBtn.click();
- await $('~loginstatus').waitForDisplayed(11000);
- const status = await $('~loginstatus').getText();
- expect(status).toHaveValueContaining('登录成功');
- });
- it('Login test: invalid case', async () => {
- await $('~username').setValue('nevercode');
- await $('~password').setValue('codemagic');
- await $('~login').click();
- await $('~loginstatus').waitForDisplayed(11000);
- const status = await $('~loginstatus').getText();
- expect(status).toHaveValueContaining('未登录'); // 断言https://webdriver.io/docs/api/expect-webdriverio
- });
- });
复制代码
step 5: 创建一个app页面
如图:
修改你的App.js:
- import React, {Component} from 'react';
- import {
- TouchableHighlight,
- StyleSheet,
- Text,
- TextInput,
- View,
- } from 'react-native';
- export default class App extends Component {
- constructor() {
- super();
- this.state = {
- username: '',
- password: '',
- isLogined: false,
- };
- }
- inputChangeHandler = (value, name) => {
- this.setState({
- [name]: value,
- });
- };
- login = () => {
- if (
- this.state.username === 'codemagic' &&
- this.state.password === 'nevercode'
- ) {
- this.setState({isLogined: true});
- } else {
- this.setState({isLogined: false});
- }
- };
- render() {
- return (
- <View
- style={LOCAL_STYLES.wrapper}
- testID="app-root"
- accessibilityLabel="app-root">
- <Text style={{fontSize: 22, marginBottom: 20}}>登录页面</Text>
- <View style={LOCAL_STYLES.inputContainer}>
- <TextInput
- name="username"
- accessibilityLabel="username"
- style={LOCAL_STYLES.input}
- onChangeText={text => this.inputChangeHandler(text, 'username')}
- />
- </View>
- <View style={LOCAL_STYLES.inputContainer}>
- <TextInput
- name="password"
- accessibilityLabel="password"
- secureTextEntry={true}
- style={LOCAL_STYLES.input}
- onChangeText={text => this.inputChangeHandler(text, 'password')}
- />
- </View>
- <Text accessibilityLabel="loginstatus">
- {this.state.isLogined ? '登录成功' : '未登录'}
- </Text>
- <TouchableHighlight
- style={LOCAL_STYLES.buttonContainer}
- accessibilityLabel="login"
- onPress={this.login}>
- <Text style={{color: 'white'}}>Login</Text>
- </TouchableHighlight>
- </View>
- );
- }
- }
- const LOCAL_STYLES = StyleSheet.create({
- wrapper: {
- flex: 1,
- alignItems: 'center',
- justifyContent: 'center',
- },
- inputContainer: {
- borderBottomColor: '#AFAFAF',
- backgroundColor: '#FFFFFF',
- borderRadius: 10,
- borderBottomWidth: 1,
- marginBottom: 16,
- flexDirection: 'row',
- alignItems: 'center',
- width: '80%',
- borderColor: 'blue',
- borderWidth: 1,
- },
- buttonContainer: {
- height: 45,
- width: 250,
- flexDirection: 'row',
- justifyContent: 'center',
- alignItems: 'center',
- marginBottom: 20,
- borderRadius: 20,
- backgroundColor: '#00b5ec',
- },
- });
复制代码
step 6: 编译你的应用到模拟器
yarn android
yarn start
step 7: 执行测试用例
npx wdio ./wdio.conf.js
执行通过后会有passed的打印:
Spec Files: 1 passed, 1 total (100% completed) in 00:00:32
至此,测试结束!
Q&A
如何来标识RN组件?
对于 Android,添加accessibilityLabel属性;
对于 iOS,添加testID属性。
- <View style={LOCAL_STYLES.inputContainer}>
- <TextInput name="password" accessibilityLabel="password" testID='password' secureTextEntry={true} style={LOCAL_STYLES.input} onChangeText={(text) => this.inputChangeHandler(text, "password")} />
- </View>
复制代码
|
|