likes
comments
collection
share

用脚教你使用Appium自动测试你的React Native

作者站长头像
站长
· 阅读数 9

| Appium[ æpi'ʌm ]

Appium是一款开源测试工具,可以用来测试安卓/iOS/Windows端的原生应用和Web混合应用。

工作原理 Appium有一个客户端-服务器架构。Appium客户端向Appium服务器(一个Node.js HTTP服务器)发送请求,反过来,Appium服务器向执行动作的设备发送请求。然后,服务器将结果返回给客户端,让你知道测试的状态。 用脚教你使用Appium自动测试你的React Native

功能

  • 跨平台
  • 多开发语言支持
  • 不需要重新编译应用程序
  • 不需要重复找轮子,可共用API
  • 市场占有率TOP1

优点

  1. 方便的切换测试原生应用或App内嵌的web页面,对Hybrid App友好
  2. 使用各个平台自身提供的测试框架,因此无需引入第三方代码或重新打包应用
  3. 开源,维护频率很高,社区也有相对较高的活跃度
  4. 支持通过自定义插件寻找元素

缺点

  • 不支持单元测试、跨应用测试
  • 测试效率相对较低

使用

默认您已经安装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 用脚教你使用Appium自动测试你的React Native 生成的文件目录如下 用脚教你使用Appium自动测试你的React Nativewdio.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页面

如图: 用脚教你使用Appium自动测试你的React Native 修改你的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>

然后在测试脚本通过$('~password')获取 更多标识用法参考官方文档Selector

| 参考资料

# Appium自动化环境搭建保姆级教程 # Appium mobile testing – test React Native apps