本文首发于个人博客 Cyy’s Blog
转载请注明出处 https://cyyjs.top/blog/60b0aff0d67bdd000f281386

# 简介

appium是一个开源的自动化测试框架,支持iOS 、 Android上的原生、混合应用及移动 Web 应用。

支持多种语言:Python、Java、Nodejs等。

# 环境准备

# 安装Java JDK

安装JDK8版本(Andriod SDK依赖java8),检查本地是否已经安装:

java --version

如果没有安装,控制台会提醒去安装,也可以点此安装

# 配置JAVA_HOME

查看java指令所在的目录:

which java
# 输出
/usr/bin/java

显示java指令文件的属性:

ls -l /usr/bin/java
# 输出
lrwxr-xr-x  1 root  wheel  74  3 27 11:09 /usr/bin/java -> /System/Library/Frameworks/JavaVM.framework/Versions/Current/Commands/java

从输出结果可以知道/usr/bin/java文件是一个链接文件,实际是指向/System/Library/Frameworks/JavaVM.framework/Versions/Current/Commands/java文件的。
进入实际指令所在的文件夹:

cd /System/Library/Frameworks/JavaVM.framework/Versions/Current/Commands

但是这个目录并不是JAVA_HOME目录,在这个目录下面有一个macJDK特有的java_home指令可以查看JDK的JAVA_HOME目录。
执行指令:

./java_home
# 输出java_home地址
/Library/Java/JavaVirtualMachines/jdk-1.8.0_21.jdk/Contents/Home

编辑.bash_profile文件

vim ~/.bash_profile
# 添加以下内容
export JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk-1.8.0_21.jdk/Contents/Home
export PATH=$JAVA_HOME/bin:$PATH

使修改的文件生效:

# 如果使用`zsh`可将此代码加入~/.zshrc中
source ~/.bash_profile

# 安装Andriod SDK 配置adb环境

下载安装Android Studio然后在里面安装Android SDK

# 配置环境变量

查看SDK路径

vim ~/.bash_profile
# 添加以下内容
export ANDROID_HOME="/Users/yyc/Library/Android/sdk"
export PATH=$PATH:$ANDROID_HOME/tools:$ANDROID_HOME/platform-tools:$ANDROID_HOME/tools
# 修改生效
source ~/.bash_profile

安装完成输入以下命令检查是否设置成功

adb version

# 安装 Python 3.7.x

这里使用Python 3.7.x版本,请点此安装下载,可通过以下命令检查:

python3 --version

# 安装Nodejs

点此下载对应Node版本

检查是否安装成功

node --version

# 安装配置检查工具

npm install appium-doctor -g

使用

appium-doctor

# 安卓环境
appium-doctor --android

查看环境配置是否成功

# 安装Appium服务器

点此下载对应系统的appium-desktop桌面工具

# 安装Appium-Python-Client

pip3 install Appium-Python-Client

# 使用

1、链接手机,打开usb调试,确认设备链接正常adb devices

2、启动appium应用程序,点击启动服务器

3、编写测试代码运行

# 元素定位

###原生应用中元素定位,如微信内

点击启动检查器会话

配置所需功能,可直接在右边使用json生成

配置项示例,详细配置说明,将下列配置替换为测试手机参数。

{
  "platformName": "Android",
  "platformVersion": "8.1.0",
  "deviceName": "9953c4c8",
  "appPackage": "com.tencent.mm",
  "appActivity": ".ui.LauncherUI",
  "automationName": "Uiautomator2",
  "unicodeKeyboard": "True",
  "resetKeyboard": "True",
  "noReset": "True",
  "chromeOptions": {
    "androidProcess": "com.tencent.mm:tools"
  },
  "chromedriverExecutableDir": "/Users/yyc/Workspace/appium/chromedriver"
}

点击启动会话,可使用此工具获取应用内元素定位。

# Webview中元素定位

打开chrome访问chrome://inspect/#devices点击inspect

# 测试代码示例

安装测试框架

# 测试断言
pip3 install pytest

# 生成测试报告
pip3 install pytest-html

公众号内webview测试示例test_demo.py:

from appium import webdriver
from time import sleep
import pytest

# 配置详情 https://github.com/appium/appium/blob/master/docs/cn/writing-running-appium/caps.md
desired_caps = {
  'platformName': 'Android',
  'platformVersion': '8.1.0',
  'deviceName': '9953c4c8',
  'appPackage': 'com.tencent.mm',
  'appActivity': '.ui.LauncherUI',
  'automationName': 'Uiautomator2',
  'unicodeKeyboard': True,
  'resetKeyboard': True,
  'noReset': True,
  'chromeOptions': {'androidProcess': 'com.tencent.mm:tools'}
}

driver = webdriver.Remote('http://localhost:4723/wd/hub',desired_caps)
# 隐式等待元素被发现,超时抛出异常
driver.implicitly_wait(10)

def enterOfficialAccount(name, btn):
  ''' 
  进入公众号,需要当前公众号在会话列表
  '''
  # 进入水滴筹公众号
  driver.find_elements_by_android_uiautomator('text("' + name + '")')[0].click()
  # 点击发起筹款按钮
  driver.find_elements_by_android_uiautomator('text("' + btn + '")')[0].click()
  sleep(2)

def enterWebview(keyword):
  '''
  进入webview,根据keyword定位window handles
  '''
  # 切换到webview
  driver.switch_to.context('WEBVIEW_com.tencent.mm:tools')
  sleep(2)
  # 切换后存在多个window_handle,类似于多个Web页签,需要循环查找定位
  for handle in driver.window_handles:
    driver.switch_to.window(handle)
    if keyword in driver.page_source:
      break
  else:
    print('定位window_handle失败')

def test_open_webview():
  enterOfficialAccount('水滴筹', '❤️发起筹款')
  enterWebview('水滴筹')
  print("test_open_webview:打开发起筹款页面")
  assert '水滴筹-已帮助几十万家庭走出困境' in driver.page_source

def test_open_info():
  # 关闭webview中的二维码弹框
  driver.find_element_by_css_selector('#app > div > div.root > div.overlay > div > div > div.qr-header > a').click()
  sleep(2)
  driver.find_element_by_css_selector('#app > div > div:nth-child(2) > div > div > div.model > div.check').click()
  sleep(2)
  print("test_open_info:打开基本信息页")
  assert '基本信息页' in driver.page_source

def test_input_info():
  # 表单输入
  driver.find_element_by_css_selector('#app > div > div.main > div.main-item.main-item__frist > div.main-input > div.main-input-item > div.main-input-item-select > select')
  driver.find_element_by_css_selector('#app > div > div.main > div.main-item.main-item__frist > div.main-input > div.main-input-item > div.main-input-item-select > select > option:nth-child(2)').click()
  driver.find_element_by_css_selector('#app > div > div.main > div.main-item.main-item__frist > div.main-input > div.self > div:nth-child(1) > div.main-input-item-select > input[type="text"]').send_keys('张思安')
  driver.find_element_by_css_selector('#app > div > div.main > div.main-item.main-item__frist > div.main-input > div.self > div:nth-child(2) > div.main-input-item-select > input[type="text"]').send_keys('320926195511175276')
  
  # 上传图片地址为手机内图片地址
  driver.find_element_by_css_selector('#app > div > div.main > div:nth-child(2) > div.main-upload-pic > div.upload-wrap > div:nth-child(2) > input[type="file"]').send_keys('/sdcard/Download/a.jpg')
  
  print("test_open_info:填写表单")
  assert True
  sleep(10)
  driver.quit()

连接手机,运行程序

pytest --html=report.html

运行后可在当前目录生成测试报告report.html

# 错误排查

1、提示安装失败,需要手机开发模式设置为允许安装应用

selenium.common.exceptions.WebDriverException: Message: An unknown server-side error occurred while processing the command. Original error: Error executing adbExec. Original error: 'Command '/usr/local/bin/adb -P 5037 -s 9953c4c8 shell pm install -g /data/local/tmp/appium_cache/728413456b86856a2003edeb524d6bd577ca6418.apk' exited with code 1'; Stderr: 'Failure [INSTALL_FAILED_USER_RESTRICTED: Install canceled by user]'; Code: '1'

2、JAVA_HOMEANDROID_HOME环境检查失败,检查环境变量设置是否成功,或点击应用中的编辑配置重新配置

selenium.common.exceptions.WebDriverException: Message: An unknown server-side error occurred while processing the command. Original error: JAVA_HOME is not set currently. Please set JAVA_HOME.
selenium.common.exceptions.WebDriverException: Message: An unknown server-side error occurred while processing the command. Original error: Could not find 'aapt' in PATH. Please set the ANDROID_HOME environment variable with the Android SDK root directory path.

3、find_element_by_name API变化

新版appiumfind_element_by_name("水滴筹")不支持,

更改为find_elements_by_android_uiautomator('text("水滴筹")')

4、Chromedriver错误

selenium.common.exceptions.WebDriverException: Message: An unknown server-side error occurred while processing the command. Original error: No Chromedriver found that can automate Chrome '68.0.3440'. See https://github.com/appium/appium/blob/master/docs/en/writing-running-appium/web/chromedriver.md for more details.

此错误原因为Chromedriver版本问题导致

在chrome中查看微信内版本,下载对应的版本

然后打开Appium的高级配置,在Chromediver 二进制路径中填入路径,重新启动服务器

5、关于图片上传错误

图片地址路径是手机内存储的图片路径

driver.find_element_by_css_selector('input[type="file"]').send_keys('/sdcard/Download/a.jpg')