Appium | (转)Appium使用教程


by keeng2008@qq.com 2016-05-16

一、Appium介绍


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

Appium 理念


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

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

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

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

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


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


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

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

Appium架构


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

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

二、Appium环境搭建(Android)


首先需要准备


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) python, 下载地址:https://www.python.org/, 下载3.X 的版本。

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

安装、配置


将上述软件依次安装。

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)编写客户端代码

创建文件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文档


安装应用后打开


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)

查找控件


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

模拟按钮点击


login_btn.click()

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

import time

time.sleep(2)  # 睡眠2秒

输入框输入文本


user_input.send_keys('123456')

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

模拟点击返回键


driver.press_keycode(4)

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

关闭driver


driver.quit()

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

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

滑动界面


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

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()


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

获取界面属性,控件属性


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


六、完整例子


测试登陆登出功能


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)


自动乱点测试崩溃的情况


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 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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,033评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,725评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,473评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,846评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,848评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,691评论 1 282
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,053评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,700评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,856评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,676评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,787评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,430评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,034评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,990评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,218评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,174评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,526评论 2 343