51Testing软件测试论坛

 找回密码
 (注-册)加入51Testing

QQ登录

只需一步,快速开始

微信登录,快人一步

手机号码,快捷登录

查看: 2117|回复: 2
打印 上一主题 下一主题

Appium使用教程_Android篇

[复制链接]
  • TA的每日心情
    郁闷
    2022-8-29 14:43
  • 签到天数: 1 天

    连续签到: 1 天

    [LV.1]测试小兵

    跳转到指定楼层
    1#
    发表于 2018-2-23 15:16:56 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
    一、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 , 编辑内容:
    1. #coding=utf-8
    2. from appium import webdriver

    3. desired_caps = {}
    4. desired_caps['platformName'] = 'Android'
    5. desired_caps['platformVersion'] = '4.4.2'
    6. desired_caps['deviceName'] = 'Android Emulator'
    7. desired_caps['appPackage'] = 'com.android.calculator2'
    8. desired_caps['appActivity'] = '.Calculator'

    9. driver = webdriver.Remote('http://localhost:4723/wd/hub', desired_caps)
    10. driver.find_element_by_name("1").click()
    11. driver.find_element_by_name("5").click()
    12. driver.find_element_by_name("9").click()
    13. driver.find_element_by_name("9").click()
    14. driver.find_element_by_name("5").click()
    15. driver.find_element_by_name("+").click()
    16. driver.find_element_by_name("6").click()
    17. driver.find_element_by_name("=").click()
    18. driver.quit()
    复制代码
    4)运行

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

    四、Appium文档

    1、安装应用后打开
    1. import os
    2. from appium import webdriver
    3. APK_PATH = 'apk/ECloud-debug.apk'
    4. COMMAND_EXECUTOR_URL = 'http://localhost:4723/wd/hub'
    5.   
    6.     desired_caps = {}
    7.     desired_caps['platformName'] = 'Android'
    8.     desired_caps['platformVersion'] = '5.0'
    9.     desired_caps['deviceName'] = 'Android Emulator'
    10.     desired_caps['app'] = os.path.abspath(APK_PATH)

    11.     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)查找结点,不希望返回异常,写个函数就行了
    1. def find_element_by_id_no_except(driver, id):
    2.     element = None
    3.     try :
    4.         element = driver.find_element_by_id(id)
    5.     except Exception,e:
    6.         print Exception, ':', e
    7.     return element
    复制代码
    3、模拟按钮点击

    login_btn.click()

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

    1. import time
    2. 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、滑动界面

    下面的例子,演示点击屏幕中间,并向上拉动(相当于查看列表下面的内容了)。
    1. from appium.webdriver.common.touch_action import TouchAction
    2. def test_scroll_down(driver):
    3.     screen = driver.get_window_size()
    4.     action = TouchAction(driver)
    5.     action.press(x=screen['width']/2,y=screen['height']/2)
    6.     action.move_to(x=0,y=-screen['height']/10)
    7.     action.release()
    8.     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,或者文本,或者列表是否为空等等。
    五、结合单元测试框架编写用例

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

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


    分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
    收藏收藏
    回复

    使用道具 举报

  • TA的每日心情
    郁闷
    2022-8-29 14:43
  • 签到天数: 1 天

    连续签到: 1 天

    [LV.1]测试小兵

    2#
     楼主| 发表于 2018-2-23 15:19:04 | 只看该作者
    1. import random
    2. import unittest

    3. class TestSequenceFunctions(unittest.TestCase):

    4.     def setUp(self):
    5.         self.seq = range(10)

    6.     def test_shuffle(self):
    7.         # make sure the shuffled sequence does not lose any elements
    8.         random.shuffle(self.seq)
    9.         self.seq.sort()
    10.         self.assertEqual(self.seq, range(10))

    11.         # should raise an exception for an immutable sequence
    12.         self.assertRaises(TypeError, random.shuffle, (1,2,3))

    13.     def test_choice(self):
    14.         element = random.choice(self.seq)
    15.         self.assertTrue(element in self.seq)

    16.     def test_sample(self):
    17.         with self.assertRaises(ValueError):
    18.             random.sample(self.seq, 20)
    19.         for element in random.sample(self.seq, 5):
    20.             self.assertTrue(element not in self.seq)

    21. if __name__ == '__main__':
    22.     unittest.main(verbosity=2)
    复制代码
    运行此测试: python test_random.py 可以查看测试的结果


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

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

    python -m unittest discover . -v



    六、完整例子

    1、测试登陆登出功能

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

    6. import unittest
    7. import appium_ecloud
    8. import appium_util
    9. from appium import webdriver
    10. import os

    11. class LoginLogoutTest(unittest.TestCase):
    12.     ##
    13.     def setUp(self):
    14.         #print('Installing ...')
    15.         desired_caps = {}
    16.         desired_caps['platformName'] = 'Android'
    17.         desired_caps['platformVersion'] = '5.0'
    18.         desired_caps['deviceName'] = 'Android Emulator'
    19.         desired_caps['app'] = os.path.abspath(appium_ecloud.APK_PATH)
    20.         self.driver = webdriver.Remote(appium_util.COMMAND_EXECUTOR_URL, desired_caps)
    21.         
    22.     def tearDown(self):
    23.         self.driver.quit()
    24.         
    25.     def test_FastLogin(self):
    26.         appium_ecloud.agree_document(self.driver)
    27.         appium_ecloud.quick_login(self.driver)
    28.         self.assertTrue(self.driver.current_activity.endswith('MainPageActivity'))
    29.         
    30.     def test_SlowLigin(self):
    31.         appium_ecloud.agree_document(self.driver)
    32.         appium_ecloud.slow_login(self.driver)
    33.         self.assertTrue(self.driver.current_activity.endswith('MainPageActivity'))
    34.         
    35.     def test_Logout(self):
    36.         appium_ecloud.agree_document(self.driver)
    37.         appium_ecloud.quick_login(self.driver)
    38.         if (self.driver.current_activity.endswith('MainPageActivity')):
    39.             appium_ecloud.test_logout(self.driver)
    40.             self.assertTrue(self.driver.current_activity.endswith('LoginActivity'))

    41. if __name__ == '__main__':
    42.     unittest.main(verbosity=2)
    复制代码
    2、自动乱点测试崩溃的情况

    auto_test_ecloud.py

    1. #coding=utf-8
    2. import random
    3. import time
    4. import traceback

    5. import appium_ecloud


    6. def auto_interact(driver):
    7.     activity = driver.current_activity
    8.     # 一定的机率滑动,返回键,点击
    9.     rate = random.random()
    10.     if rate < 0.1:
    11.         print activity + ' Scroll Down'
    12.         appium_ecloud.test_scroll_down(driver)
    13.     elif rate < 0.2:
    14.         print activity + ' Scroll Up'
    15.         appium_ecloud.test_scroll_up(driver)
    16.     elif rate < 0.3:
    17.         print activity + ' Key Back'
    18.         driver.press_keycode(4)
    19.     else:
    20.         btn_list = driver.find_elements_by_android_uiautomator('new UiSelector().clickable(true)')
    21.         if (len(btn_list) > 0):
    22.             index = random.randint(0, len(btn_list) - 1)
    23.             print activity + ' Click Button index = %d' % (index,)
    24.             btn_list[index].click()


    25. def main():
    26.     driver = None
    27.     try:
    28.         driver = appium_ecloud.install_app()
    29.         time.sleep(appium_ecloud.LONG_WAIT_TIME)
    30.         appium_ecloud.agree_document(driver)
    31.         appium_ecloud.quick_login(driver)
    32.         step = 0
    33.         while step < 100:
    34.             if (driver.current_activity.endswith('LoginActivity')):
    35.                 appium_ecloud.test_login(driver)
    36.             elif (driver.current_activity.endswith('.Launcher')):
    37.                 driver.background_app(1)
    38.                 driver.launch_app()
    39.             else:
    40.                 auto_interact(driver)
    41.                 time.sleep(appium_ecloud.CLICK_WAIT_TIME)
    42.             step += 1
    43.         # 正常退出
    44.         driver.quit()

    45.     except Exception, e:
    46.         print Exception, ":", e
    47.         traceback.print_exc()
    48.         # 异常退出
    49.         if (driver != None):
    50.             driver.quit()


    51. if __name__ == '__main__':
    52.     for i in range(20000):
    53.         try:
    54.             main()
    55.         except Exception, e:
    56.             print Exception, ":", e
    57.             traceback.print_exc()
    复制代码



    回复 支持 反对

    使用道具 举报

    本版积分规则

    关闭

    站长推荐上一条 /1 下一条

    小黑屋|手机版|Archiver|51Testing软件测试网 ( 沪ICP备05003035号 关于我们

    GMT+8, 2024-9-20 22:27 , Processed in 0.070622 second(s), 23 queries .

    Powered by Discuz! X3.2

    © 2001-2024 Comsenz Inc.

    快速回复 返回顶部 返回列表