一、Appium介绍

Appium是一个开源的自动化测试工具,其支持iOS和安卓平台上的原生的,基于移动浏览器的,混合的应用。

1、Appium 理念

Appium是基于以下的四个理念设计来满足移动平台测试自动化的要求的:

1)您不应该因为需要自动化测试您的应用而不得不以任何形式去重新编译或者修改你的app

2)您不应该把自己固定在一门特定的语言和一个特定的框架上去实现和运行你的测试

3)当说到测试自动化APIs的时候,一个移动测试框架不应该做“重新发明轮子”的事情,

4)一个移动测试自动化框架应该是开源的,无论是在精神上,实际上,还是名义上!

2、使用Appium进行自动化测试有两个好处

Appium在不同平台中使用了标准的自动化APIs,所以在跨平台时,不需要重新编译或者修改自己的应用。

Appium支持Selenium WebDriver支持的所有语言,如java、Object-C、JavaScript、Php、Python、Ruby、C#、Clojure,或者Perl语言,更可以使用Selenium WebDriver的Api。Appium支持任何一种测试框架.Appium实现了真正的跨平台自动化测试。(本文主要介绍Python的用法)

3、Appium架构

Appium 是一个用Node.js编写的HTTP server,它创建、并管理多个 WebDriver sessions 来和不同平台交互,如 iOS ,Android等等.

Appium 开始一个测试后,就会在被测设备(手机)上启动一个 server ,监听来自 Appium server的指令. 每种平台像 iOS 和Android都有不同的运行、和交互方式。所以Appium会用某个桩程序“侵入”该平台,并接受指令,来完成测试用例的运行。

二、Appium环境搭建(Android)

1、首先需要准备

1) jdk(步骤不再啰嗦)

2) android SDK,下载地址:http://developer.android.com/sdk/index.html,下载sdk tools,可能需要FQ,提供一个国内下载地址:http://www.androiddevtools.cn/

3) appium,下载地址:http://appium.io/

4) nodejs,下载地址:https://nodejs.org/en/

5) appium lib,下载地址:http://appium.io/downloads.html

选择Python版本的Lib: Appium-Python-Client-0.22.tar.gz

由于Appium依赖于Selemium,所以还要下载 Selemium Lib: selenium-2.53.2.tar.gz   https://pypi.python.org/pypi/selenium

6) python, 下载地址:https://www.python.org/, 下载2.X 的版本。

上述软件都准备好后,则进入搭建步骤。

2、安装、配置

将上述软件依次安装。

1) android sdk安装完毕后,需要配置环境变量

新建ANDROID_HOME    D:\ProgramFiles (x86)\Android\android-sdk

在PATH中添加:%ANDROID_HOME%\platform-tools;%ANDROID_HOME%\tools;

2)  nodejs安装完毕后,需要配置环境变量

在PATH中添加:D:\Program Files\nodejs;

3) appium安装完毕后,需要配置环境变量

D:\Program Files (x86)\Appium\node_modules\.bin;

4) 配置好后,启动cmd,

输入node -v,查看node安装版本

输入appium-doctor检查appium的安装环境是否成功,如下图:

5) 安装Python,配置环境变量,如C:\Python27,检查是否设置成功,如下图:

三、开始例子(Python)

1) 启动Appium

打开命令行,输入appium, 显示成功启动:

2)连接Android手机(或者模拟器)

3)编写客户端代码

假设我们的代码放在目录E:\PythonTest\AppiumClientPython 中。首先把 Appium-Python-Client-0.22.tar.gz 里面的 appium 目录解压到AppiumClientPython 中, 把 selenium-2.53.2.tar.gz里面的 selenium 目录解压到AppiumClientPython中。

创建文件hello_appium.py , 编辑内容:

#coding=utf-8

from appium import webdriver

desired_caps = {}

desired_caps['platformName'] = 'Android'

desired_caps['platformVersion'] = '4.4.2'

desired_caps['deviceName'] = 'Android Emulator'

desired_caps['appPackage'] = 'com.android.calculator2'

desired_caps['appActivity'] = '.Calculator'

driver = webdriver.Remote('http://localhost:4723/wd/hub', desired_caps)

driver.find_element_by_name("1").click()

driver.find_element_by_name("5").click()

driver.find_element_by_name("9").click()

driver.find_element_by_name("9").click()

driver.find_element_by_name("5").click()

driver.find_element_by_name("+").click()

driver.find_element_by_name("6").click()

driver.find_element_by_name("=").click()

driver.quit()

4)运行

打开命令行,cd到E:\PythonTest\AppiumClientPython 中,运行 python hello_appium.py, 正常情况可以看到手机按照代码控制,打开计算器,逐个点击按钮完成计算。

四、Appium文档

1、安装应用后打开

import os

from appium import webdriver

APK_PATH = 'apk/ECloud-debug.apk'

COMMAND_EXECUTOR_URL = 'http://localhost:4723/wd/hub'

desired_caps = {}

desired_caps['platformName'] = 'Android'

desired_caps['platformVersion'] = '5.0'

desired_caps['deviceName'] = 'Android Emulator'

desired_caps['app'] = os.path.abspath(APK_PATH)

driver = webdriver.Remote(COMMAND_EXECUTOR_URL, desired_caps)

2、查找控件

1)通过名称查找

btn = driver.find_element_by_name("+")

2)  通过ID查找

start_btn =driver.find_element_by_id('com.cn21.ecloud:id/instruction_close_btn')

或 start_btn = driver.find_element_by_id('instruction_close_btn')

3)通过类名查找

child_text =parent.find_element_by_class_name('android.widget.TextView')

4)通过android_uiautomator查找

start_btn =driver.find_element_by_android_uiautomator('new UiSelector().clickable(true)')

以上find_element_by_XX 都是返回符合条件的第一个控件,如果要返回多个控件,可以调用 find_elements_by_XX, 返回的是一个list。

注意:如果找不到符合条件的控件,会抛出异常。

5)查找结点,不希望返回异常,写个函数就行了

def find_element_by_id_no_except(driver, id):

element = None

try :

element = driver.find_element_by_id(id)

except Exception,e:

print Exception, ':', e

return element

3、模拟按钮点击

login_btn.click()

注意:有的点击如果需要等待动画、或者网络请求,建议等待一会:

import time

time.sleep(2)  # 睡眠2秒

4、输入框输入文本

user_input.send_keys('123456')

注意:Android如果要正确输入,需要把使用系统自带的输入法,第三方输入法无法正确输入。

5、模拟点击返回键

driver.press_keycode(4)

其中按钮的定义,由Android里的KeyEvent.java里定义的,所以其它的Android按钮也是支持的。

6、关闭driver

driver.quit()

注意:一定要记得关闭driver, 否则下次连接的时候可能会出异常,因为Appium以为你上次未关闭,会创建Session失败。

为了避免代码出现异常而没有关闭,可以在捕获异常时再关闭。

7、滑动界面

下面的例子,演示点击屏幕中间,并向上拉动(相当于查看列表下面的内容了)。

from appium.webdriver.common.touch_action import TouchAction

def test_scroll_down(driver):

screen = driver.get_window_size()

action = TouchAction(driver)

action.press(x=screen['width']/2,y=screen['height']/2)

action.move_to(x=0,y=-screen['height']/10)

action.release()

action.perform()

等等,怎么获取界面的属性来验证正确性?

8、获取界面属性,控件属性

1)获取当前Activity名称

activity = driver.current_activity

2) 获取屏幕宽高

screen = driver.get_window_size()

3)获取控件文本

mobile_name.get_attribute('text') 或者 mobile_name.text

4)获取控件类名

mobile_name.get_attribute('className')

5)判断控件是否显示

mobile_name.is_displayed() 或者 mobile_name.get_attribute('displayed')

6)获得控件位置

mobile_name.location

7)获得控件大小

mobile_name.size

8)查找控件子结点

parent.find_elements_by_class_name('android.widget.TextView')

同样:查找控件的其它方法,也适用于查找子结点。

对于交互后的验证,无法验证到具体的数据内容,可以验证当前的Activity,或者文本,或者列表是否为空等等。

更多参考:http://blog.csdn.net/crisschan/article/details/50416860

五、结合单元测试框架编写用例

Python自带有unittest用于单元测试,其结构类似于JUnit。

一个测试类需要继承于unittest.TestCase, 方法setUp 用于测试初始化,每个用例开始前都会调用,tearDown用于用例结束时调用,每个以test开始的函数被当成一个用例。

test_random.py

import random

import unittest

class TestSequenceFunctions(unittest.TestCase):

def setUp(self):

self.seq = range(10)

def test_shuffle(self):

# make sure the shuffled sequence does not lose any elements

random.shuffle(self.seq)

self.seq.sort()

self.assertEqual(self.seq, range(10))

# should raise an exception for an immutable sequence

self.assertRaises(TypeError, random.shuffle, (1,2,3))

def test_choice(self):

element = random.choice(self.seq)

self.assertTrue(element in self.seq)

def test_sample(self):

with self.assertRaises(ValueError):

random.sample(self.seq, 20)

for element in random.sample(self.seq, 5):

self.assertTrue(element not in self.seq)

if __name__ == '__main__':

unittest.main(verbosity=2)

运行此测试: python test_random.py 可以查看测试的结果

上面结果显示,有2个用例测试通过,1个用例不通过。

可以在一个目录下写多个以test开头的测试文件,然后通过以下命令运行所有测试类:

python -m unittest discover . -v

六、完整例子

1、测试登陆登出功能

test_ecloud_login_logout.py

#coding=utf-8
# 测试天翼云登陆登出功能
# 用例1:快速登陆,验证登陆后的Activity为MainPageActivity
# 用例2:普通登陆,输入用户名密码,验证登陆后的Activity为MainPageActivity
# 用例3:快速登陆后注销,验证注销后的Activity为LoginActivity

import unittest
import appium_ecloud
import appium_util
from appium import webdriver
import os

class LoginLogoutTest(unittest.TestCase):
    ##
    
def setUp(self):
        #print('Installing ...')
        
desired_caps = {}
        desired_caps['platformName'] = 'Android'
        desired_caps['platformVersion'] = '5.0'
        desired_caps['deviceName'] = 'Android Emulator'
        desired_caps['app'] = os.path.abspath(appium_ecloud.APK_PATH)
        self.driver = webdriver.Remote(appium_util.COMMAND_EXECUTOR_URL, desired_caps)
        
    def tearDown(self):
        self.driver.quit()
        
    def test_FastLogin(self):
        appium_ecloud.agree_document(self.driver)
        appium_ecloud.quick_login(self.driver)
        self.assertTrue(self.driver.current_activity.endswith('MainPageActivity'))
        
    def test_SlowLigin(self):
        appium_ecloud.agree_document(self.driver)
        appium_ecloud.slow_login(self.driver)
        self.assertTrue(self.driver.current_activity.endswith('MainPageActivity'))
        
    def test_Logout(self):
        appium_ecloud.agree_document(self.driver)
        appium_ecloud.quick_login(self.driver)
        if (self.driver.current_activity.endswith('MainPageActivity')):
            appium_ecloud.test_logout(self.driver)
            self.assertTrue(self.driver.current_activity.endswith('LoginActivity'))

if __name__ == '__main__':
    unittest.main(verbosity=2)

2、自动乱点测试崩溃的情况

auto_test_ecloud.py

#coding=utf-8
import random
import time
import traceback

import appium_ecloud

def auto_interact(driver):
    activity = driver.current_activity
    # 一定的机率滑动,返回键,点击
    
rate = random.random()
    if rate < 0.1:
        print activity + ' Scroll Down'
        appium_ecloud.test_scroll_down(driver)
    elif rate < 0.2:
        print activity + ' Scroll Up'
        appium_ecloud.test_scroll_up(driver)
    elif rate < 0.3:
        print activity + ' Key Back'
        driver.press_keycode(4)
    else:
        btn_list = driver.find_elements_by_android_uiautomator('new UiSelector().clickable(true)')
        if (len(btn_list) > 0):
            index = random.randint(0, len(btn_list) - 1)
            print activity + ' Click Button index = %d' % (index,)
            btn_list[index].click()

def main():
    driver = None
    try:
        driver = appium_ecloud.install_app()
        time.sleep(appium_ecloud.LONG_WAIT_TIME)
        appium_ecloud.agree_document(driver)
        appium_ecloud.quick_login(driver)
        step = 0
        while step < 100:
            if (driver.current_activity.endswith('LoginActivity')):
                appium_ecloud.test_login(driver)
            elif (driver.current_activity.endswith('.Launcher')):
                driver.background_app(1)
                driver.launch_app()
            else:
                auto_interact(driver)
                time.sleep(appium_ecloud.CLICK_WAIT_TIME)
            step += 1
        # 正常退出
        
driver.quit()

    except Exception, e:
        print Exception, ":", e
        traceback.print_exc()
        # 异常退出
        
if (driver != None):
            driver.quit()

if __name__ == '__main__':
    for i in range(20000):
        try:
            main()
        except Exception, e:
            print Exception, ":", e
            traceback.print_exc()

注:为了更方便的编写python代码,推荐使用PyCharm IDE,编辑代码跟Java一样方便。

七、参考资料:

1)官网 http://appium.io/index.html

2)appium/python-client使用文档https://github.com/appium/python-client

3)搭建appium的android环境http://www.cnblogs.com/qiaoyeye/p/5131382.html

4)Appium移动自动化测试(四)http://www.cnblogs.com/fnng/p/4579152.html

5)AppiumPython API http://blog.csdn.net/crisschan/article/details/50416860

6)appium常用方法总结 http://www.cnblogs.com/fanxiaojuan/p/4882676.html

测试_appium测试工具的更多相关文章

  1. 测试耗电量的工具(Android)

    Emmagee是监控指定被测应用在使用过程中占用机器的CPU.内存.流量资源的性能测试小工具. 支持SDK:Android2.2以及以上版本 Emmagee功能介绍 1.检测当前时间被测应用占用的CP ...

  2. 【转】web测试内容及工具经典总结

    基于Web的系统测试在基于Web的系统开发中,如果缺乏严格的过程,我们在开发.发布.实施和维护Web的过程中,可能就会碰到一些严重的问题,失败的可能性很大.而且,随着基于Web的系统变得越来越复杂,一 ...

  3. 30款基本UX工具 - 用户测试与反馈工具

    日期:2013-9-5  来源:GBin1.com 在上一篇30款基本UX工具 - 思维流程工具 & 原型工具中,我们提到了10款用于头脑风暴和原型创建的工具,用于帮助我们在用户体验上可以做的 ...

  4. Apache JMeter开源压力测试/负载测试工具 2.12 官方最新版

    软件介绍   Jmeter是一款使用Java开发的,开源免费的,测试工具, 主要用来做功能测试和性能测试(压力测试/负载测试),而且用Jmeter 来测试 Restful API, 非常好用. 如何学 ...

  5. Android应用测试性能的工具Emmagee,导出文件格式问题分析

    原文引用自:http://www.open-open.com/lib/view/open1367026451078.html Emmagee是监控指定被测应用在使用过程中占用机器的CPU.内存.流量资 ...

  6. 最简单的基于FFmpeg的libswscale的示例附件:测试图片生成工具

    ===================================================== 最简单的基于FFmpeg的libswscale的示例系列文章列表: 最简单的基于FFmpeg ...

  7. 360在线网站安全检测,web安全测试AppScan扫描工具,XSS常用的攻击手法

    360在线网站安全检测,web安全测试AppScan扫描工具,XSS常用的攻击手法 如何做好网站的安全性测试 360网站安全检测 - 在线安全检测,网站漏洞修复,网站后门检测http://websca ...

  8. 测试mysql性能工具

    mysqlslap mysqlslap可以模拟服务器的负载,并输出计时信息.它包含在MySQL 5.1 的发行包中,应该在MySQL 4.1或者更新的版本中都可以使用.测试时可以执行并发连接数,并指定 ...

  9. mysql测试和sysbench工具详解

    前言 作为一名后台开发,对数据库进行基准测试,以掌握数据库的性能情况是非常必要的.本文介绍了MySQL基准测试的基本概念,以及使用sysbench对MySQL进行基准测试的详细方法. 文章有疏漏之处, ...

随机推荐

  1. nginx安全:配置ssl证书(https证书)

    一,配置https证书的意义 https协议是由SSL+http协议构建的安全协议,支持加密传输和身份认证, 安全性比http要更好,因为数据的加密传输,更能保证数据的安全性和完整性 例如:不使用ht ...

  2. C# 将Excel里面的数据填充到DataSet中

    /// <summary> /// 将Excel表里的数据填充到DataSet中 /// </summary> /// <param name="filenam ...

  3. 小C和小派的缠绵爱情——C语言调用Python代码

    我妒忌你的开源,你眼红我的速度,不如我们就在一起吧! --------SJ2050 2019.4.9号更新:实现在未安装python环境的机子上运行调用了python程序的C语言代码! 文章目录 环境 ...

  4. CDH+Kylin三部曲之二:部署和设置

    欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ...

  5. javascript中的描述对象(Descriptor)获取和定义随笔

    最近再看了阮一峰的老师的ES6入门,发现一个有趣的东西,借此纪录以及整理下. 对象的每个属性都有一个描述对象(Descriptor),用来控制该属性的行为.Object.getOwnPropertyD ...

  6. 赛门铁克和DigiCert证书有什么区别?

    在众多国人眼里,赛门铁克Symantec名气更胜于DigiCert证书.但是,我们知道2017年赛门铁克因一系列原因被DigiCert收购,品牌名称也被更新为DigiCert Secure Site. ...

  7. java数据结构-11循环双端队列

    @SuppressWarnings("unchecked") public class CircleDeque<E> { private int front; priv ...

  8. oracle 查询数据库锁及锁处理

    1.数据库锁表查询语句: SELECT SESS.SID, SESS.SERIAL#, LO.ORACLE_USERNAME, LO.OS_USER_NAME, AO.OBJECT_NAME 被锁对象 ...

  9. selenium中如何保证操作元素的成功率?也就是说如何保证我点击的元素一定是可以点击的?

    1.在寻找元素时,加上显示等待或者隐式等待,这样在对元素进行操作之前保证元素被找到,进而提高成功率: 2.在对元素操作之前,比如click,如果该元素未display(非hidden),就需要先滚动到 ...

  10. CSS动画之转换模块

    2D转换模块:注意点:1.可以类似于过渡模块一样简写,但是这里不是用逗号隔开而是用空格 2.2D的转换模块会修改元素的坐标系,所以旋转之后的平移就不是水平平移 格式:旋转:transform: rot ...