1. 背景介绍:
为了在自动化测试中节省时间节省真机的成本,而且更高效的覆盖所有的Android版本,避免兼容性问题和实现全面自动化测试,我们采用saucelabs(saucelabs.com)平台提供的虚拟设备。使用简单易书写的Python语言和appium开源框架以及单元测试behave,结合build工具jenkins 实现全自动化android 自动化测试。
2. 环境搭建:
2.1 安装python(www.python.org/downloads/)
2.2 安装pip(pip.pypa.io/en/stable/i…)
2.3 注册saucelabs 账号,用于获取SAUCE_USERNAME和SAUCE_ACCESS_KEY
2.4 用pip 安装 appium client和sauceclient:
pip install behave Appium-Python-Client sauceclient
2.5下载安装Win下的Appium(Appium Server)安装并配置环境变量.
2.6下载python IDE (PyCharm)用于编写脚本.
2.7 下载安装Cygwin 用于在windows下运行可以并行执行测试的makefile文件,如果你选择在unix下运行就没必要安装Cygwin,默认可以执行make命令。
3. 关于单元测试behave的介绍:
3.1 Behave是BDD(Behavior drive development - 行为驱动开发)的框架。这个框架用来做敏捷开发比较多。其中behave包括的feature部分。Behave既可以用来测试网页的功能,也可以用来单元测试测试开发者的代码。
3.2 feature文件包括5行: Feature行: 介绍这个feature用来干什么的; Scenario行:介绍这个scenario用来干什么的;Given: 一般数据的初始化在这里执行;When:执行操作;Then:验证结果。
3.3 environment.py文件介绍,environment.py文件定义了一些当测试脚本在run的过程中之前和之后完成的任务:
- before_step(context, step), after_step(context, step)
- 在这里面的脚本会在每一个步骤之前,之后执行
- before_scenario(context, scenario), after_scenario(context, scenario)
- 在这里面的脚本会在每一个场景之前,之后执行
- before_feature(context, feature), after_feature(context, feature)
- 在这里面的脚本会在每一个feature之前,之后执行
- before_tag(context, tag), after_feature(context, tag)
- 在脚本里面可以设置tag(这个之后会介绍),这里面的脚本会在含有tag的模块里面之前,之后执行
- before_all(context), after_all(context)
- 这里面的脚本会在整个脚本开始之前,之后执行 例如登录或者是退出
4. 下面以一个例子来演示工程的新建以及testcase的书写和运行:
4.1 新建一个工程:
4.1.1 打开python IDE(PyCharm) File->New Project->Pure Python 并在Interpreter中选择你的python安装路径,工程名为python-behave-appium(如下图)
4.1.2 在工程中导入behave 单元测试的包,直接复制进来就好了.
4.1.3 在工程中新建文件夹features和 文件makefile,并在features 下新建文件夹steps和文件environment和test.feature(如下图)
4.2 test case 文件内容:
4.2.1 test.feature
Feature: Adding a contact via an Android App
Scenario: Test spotlight application
Given I click on the add contact button
When I enter a name and email
Then I click the Save button
4.2.2 steps.py
#!/usr/bin/python
# -*- coding: UTF-8 -*-
import behave
from features.module.testcustomview import TestCustomView
from features.module.testsetting import TestSetting
from features.module.testoverview import TestOverView
from features.module.testheatmap import TestHeatMap
from features.module.testconnectionsearch import TestConnectionSearch
from features.module.testalarm import TestAlarm
from features.module.testconnection import TestConnection
@behave.given('I click on the add contact button')
def step_impl(context):
context.test_connection = TestConnection(context.driver)
context.test_connection.check_connection()
context.test_alarm = TestAlarm(context.driver)
context.test_alarm.check_alarms()
context.connection_search = TestConnectionSearch(context.driver)
context.connection_search.check_connection_search()
context.test_heat_map = TestHeatMap(context.driver)
context.test_heat_map.check_heat_map()
context.test_over_view = TestOverView(context.driver)
context.test_over_view.check_over_view()
@behave.when('I enter a name and email')
def step_impl(context):
context.custom_view = TestCustomView(context.driver)
context.custom_view.add_one_customer_view(4, "special")
context.custom_view.add_more_customer_view(3, 3)
context.custom_view.delete_more_customer_view(4)
@behave.then('I click the Save button')
def step_impl(context):
context.test_setting = TestSetting(context.driver)
context.test_setting.check_setting()
4.2.3 devices.py
import os
from appium import webdriver
username = "lindawang123456"
access_key = "e06e33ef-9e66-4b36-8865-e99ad2929626"
url = 'http://%s:%s@ondemand.saucelabs.com:80/wd/hub' % (username, access_key)
assert username, "Unable to pull username from environment variables"
assert access_key, "Unable to pull access_key from environment variables"
def make_driver(name):
desired_caps = {
"name": name + os.environ.get('deviceName'),
"app": "sauce-storage:app-release.apk",
"platformName": "Android",
"deviceName": os.environ.get('deviceName'),
"browserName": "",
"platformVersion": "4.4",
"appiumVersion": "1.5.3",
"deviceOrientation": "portrait"
}
driver = webdriver.Remote(url, desired_caps)
return driver
4.2.4 login.py
from features.module.constant import Constant
class LogIn(object):
def __init__(self,appium_driver):
self.driver = appium_driver
def log_in(self):
self.driver.find_element_by_id(Constant.sign_in_enter).click()
text_fields = self.driver.find_elements_by_class_name(Constant.edit_text_field)
text_fields[0].send_keys(Constant.email)
text_fields[1].send_keys(Constant.password)
self.driver.find_element_by_id(Constant.right_button).click()
self.driver.implicitly_wait(5000)
self.driver.find_element_by_id(Constant.title_view).click()
user_name = self.driver.find_element_by_id(Constant.top_user_name)
email_name = user_name.text
print ("email is :", email_name)
self.driver.find_element_by_id(Constant.section_header_ll).click()
self.driver.find_element_by_id(Constant.refresh_btn).click()
self.driver.find_element_by_id(Constant.title_view).click()
self.driver.find_element_by_id(Constant.more_count_btn).click()
4.2.5 Makefile 文件:
run_all_in_parallel:
make -j android_emulator samsung_galaxy_s4_emulator
android_emulator:
deviceName="Android Emulator" behave-1.2.5/bin/behave
samsung_galaxy_s4_emulator:
deviceName="Samsung Galaxy S4 Emulator" behave-1.2.5/bin/behave
其他文件内容都是相关模块的的testcase文件就不一一列出了,最后的工程结构如下:
4.3 关于如何运行:
4.3.1 在模拟器上运行:
启动appium sever
启动Android 模拟器
打开cygwin 窗口 进入进入工程目录下,执行如下命令(如下图)
make run_all_in_parallel
>
4.3.2 在saucelabs平台运行:
在代码里有saucelabs 的username,access_key,就不需要手动启动appium server和android模拟器
username = "lindawang123456"
access_key = "e06e33ef-9e66-4b36-8865-e99ad2929626"
url = 'http://%s:%s@ondemand.saucelabs.com:80/wd/hub' % (username, access_key)
直接在cygwin或者unix下执行上面的make命令,并且可以在makefile文件中添加任何Android版本实现并行运行,并且可以回放测试的视频来查看失败的原因(如下图),当然可以安装jenkins把makefile 文件直接配置到jenkins上运行。