欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Python语言:一个简单的Appium测试

程序员文章站 2022-04-15 13:07:29
说在前面 随着社会的发展与进步,中国的互联网行业无疑是飞速发展。互联网+的时代,对传统行业有着巨大的冲击,人们互联网意识的觉醒,对IT行业有了更高的要求。软件的安全,软件的质量以及体验成为广...

说在前面

随着社会的发展与进步,中国的互联网行业无疑是飞速发展。互联网+的时代,对传统行业有着巨大的冲击,人们互联网意识的觉醒,对IT行业有了更高的要求。软件的安全,软件的质量以及体验成为广大用户更加关注的焦点。这就意味着互联网公司要更加注重软件的质量问题,软件测试也将成为互联网公司的重头戏。自动化测试在人们眼中无疑是软件测试的“高大上”,AI技术的发展也在诠释着 自动化测试 将是未来测试的发展方向。

一个简单的Appium自动化测试案例

近期也学习了一些自动化测试,下面演示一个登录功能。 如需 下载软件,环境配置 没有什么是“度娘”做不到的!

使用语言: Python3.6

环境: 电脑win10 , 手机oppo-6.0.1

功能模块: QQ登录

运用分层和封装思想

第一层是自己的定义一个工具层,封装了几种定位和四种滑动:

from appium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

'''工具类'''
class baseTools:
    '''初始化方法'''
    def __init__(self,appPackage,appActivity):
        '''方法一'''
        # dictionary = {}#定义空字典
        # dictionary['platformName'] = 'Android'
        # dictionary['platformVersion'] = '6.0.1'
        # dictionary['noReset'] = True
        # dictionary['deviceName'] = 'b973aad5'
        # dictionary['appPackage'] = appPackage
        # dictionary['appActivity'] = appActivity
        '''方法二'''
        desired_caps = {
            'platformName':'Android', # 平台名
            'platformVersion':'6.0.1',# 平台版本号
            'noReset':True, # 不重置
            'deviceName':'b973aad5', # 设备名字
            'appPackage':appPackage, # app包名
            'appActivity':appActivity # app 主Activity
        }
        #  驱动连接
        self.driver = webdriver.Remote('http://localhost:4723/wd/hub', desired_caps)

    '''id定位'''
    def MyfindID(self,id):
        ID = (By.ID,id)
        WebDriverWait(self.driver,30,0.1).until(EC.presence_of_all_elements_located(ID))
        return self.driver.find_element_by_id(id)

    '''xpath定位'''
    def MyfindXPATH(self, xpath):
        XPATH = (By.XPATH, xpath)
        WebDriverWait(self.driver, 30, 0.1).until(EC.presence_of_all_elements_located(XPATH))
        return self.driver.find_element_by_xpath(xpath)

    '''name定位'''
    def MyfindNAME(self, name):
        NAME = (By.NAME, name)
        WebDriverWait(self.driver, 30, 0.1).until(EC.presence_of_all_elements_located(NAME))
        return self.driver.find_element_by_name(name)

    '''class_name定位元素'''
    def MyfindCLASS_NAME(self, class_name):
        CLASS_NAME = (By.CLASS_NAME, class_name)
        WebDriverWait(self.driver, 30, 0.1).until(EC.presence_of_all_elements_located(CLASS_NAME))
        return self.driver.find_element_by_class_name(class_name)

    '''link_name定位'''
    def MyfindLINK_TEXT(self, link_text):
        LINK_TEXT = (By.LINK_TEXT, link_text)
        WebDriverWait(self.driver, 30, 0.1).until(EC.presence_of_all_elements_located(LINK_TEXT))
        return self.driver.find_element_by_name(link_text)

    '''
    全屏滑动   
        上下滑动 X轴(宽)不变,Y轴(高)交换位置
        左右滑动 Y轴(高)不变,X轴(宽)交换位置
    '''
    def MySwipe(self, direction, n, duration = 1000):  # direction为滑动方向(t,d,l,r 四个参数),
                                                        #  n为滑动次数(n应为整数)    duration 为间隔时间
        if direction == 't': # top 上滑动
            d = self.driver
            width = d.get_window_size()['width'] #获取宽度
            height = d.get_window_size()['height'] #获取高度
            for i in range(n):
                d.swipe(width * 0.5, height * 0.75, width * 0.5, height * 0.25,duration)
        elif direction == 'd': # down 下滑动
            d = self.driver
            width = d.get_window_size()['width']
            height = d.get_window_size()['height']
            for i in range(n):
                d.swipe(width * 0.5, height * 0.25, width * 0.5, height * 0.75, duration)
        elif direction == 'l': # left 左滑动
            d = self.driver
            width = d.get_window_size()['width']
            height = d.get_window_size()['height']
            for i in range(n):
                d.swipe(width * 0.75, height * 0.5, width * 0.25, height * 0.5, duration)
        elif direction == 'r': # right 右滑动
            d = self.driver
            width = d.get_window_size()['width']
            height = d.get_window_size()['height']
            for i in range(n):
                d.swipe(width * 0.25, height * 0.5, width * 0.75, height * 0.5, duration)

    '''返回driver'''
    def Mydriver(self):
        return self.driver

第二层是UI层,封装所有能看的见操作 主要有 点击 输入 获取文本:

'''导入工具类'''
from Tool_Package.tools.TOOL import baseTools
import unittest
from HTMLTestRunner import HTMLTestRunner

'''UI层'''
class uiAction():
    '''初始化'''
    def __init__(self,appPackage,appActivity):
        '''创建对象,引入baseTools'''
        self.d = baseTools(appPackage,appActivity)

    '''点击'''
    def about_click(self, locate, type):  # 参数type 判断传入定位参数的类型,调用不同的定位方式
        if type == 'id':
            self.d.MyfindID(locate).click()
        elif type == 'xpath':
            self.d.MyfindXPATH(locate).click()
        elif type == 'name':
            self.d.MyfindNAME(locate).click()
        elif type == 'className':
            self.d.MyfindCLASS_NAME(locate).click()
        elif type == 'linkText':
            self.d.MyfindLINK_TEXT(locate).click()

    '''输入'''
    def about_input(self,locate,value,type): # 参数type 判断传入定位参数的类型,调用不同的定位方式
        if type == 'id':
            self.d.MyfindID(locate).send_keys(value)
        elif type == 'xpath':
            self.d.MyfindXPATH(locate).send_keys(value)
        elif type == 'name':
            self.d.MyfindNAME(locate).send_keys(value)
        elif type == 'className':
            self.d.MyfindCLASS_NAME(locate).send_keys(value)
        elif type == 'linkText':
            self.d.MyfindLINK_TEXT(locate).send_keys(value)

    '''滑动'''
    def about_swipe(self,direction,n):
        self.d.MySwipe(direction,n)

    '''切换到H5'''
    def Switch_webview(self):
        self.d.driver._switch_to.context('WEBVIEW_cn.com.gsh.guoshihui')

    '''切换为 原生'''
    def Switch_native(self):
        self.d.driver._switch_to.context('NATIVE_APP')

    '''获取文本内容并返回数据'''
    def get_text(self,locate,type): # type判断传入定位参数的类型
        if type == 'id':
            str_Content = self.d.MyfindID(locate).text
            return str_Content
        elif type == 'xpath':
            str_Content = self.d.MyfindXPATH(locate).text
            return str_Content

    '''退出'''
    def tearDown(self):
        self.d.driver.quit()
第三层是服务层,几乎所有的实参都在此层传输:
from Tool_Package.tools.TOOL import baseTools
import unittest
from HTMLTestRunner import HTMLTestRunner
# QQ 登录
class business():
    def __init__(self,appPackage,appActivity):
        self.qq = uiAction(appPackage,appActivity)

    '''登录'''
    def Login(self):
        self.qq.about_input('android.widget.EditText','1796065407','className') # 输入用户名
        self.qq.about_input('com.tencent.mobileqq:id/password','***********','id') #输入密码
        self.qq.about_click('com.tencent.mobileqq:id/login','id')  #点击登录按钮

    '''清理'''
    def tui(self):
        self.qq.tearDown()
最后一层采用unittest框架,根据用例调用方法, 并打印测试报告。
from Tool_Package.tools.TOOL import baseTools
import unittest
from HTMLTestRunner import HTMLTestRunner

'''
    此层  调用方法,执行用例
    使用unittest框架
'''
class Case(unittest.TestCase):
    '''
    初始化方法  此处传入的两个参数 为QQ的 Package(包名)  和 主Activity
    '''
    def setUp(self):
        self.cs = business('com.tencent.mobileqq','.activity.SplashActivity')

    '''调用登录方法'''
    def test_login(self):
        u'''QQ登录'''
        self.cs.Login()

    '''退出'''
    def t(self):
        self.cs.tui()

if __name__ == '__main__':
    suite = unittest.TestSuite()
    suite.addTest(Case('test_login'))
    # 创建文件 并 设置编码
    file = open('result.html', 'w+', encoding='utf-8')
    # 标题
    t = 'QQ登录自动化测试'
    # 描述
    desc = 'This is MaZhengguang TEST REPORT'
    # 测试报告
    runner = HTMLTestRunner(stream=file, title=t, description=desc)
    # 运行
    runner.run(suite)

让思想成为你的源头活水

有人云:“学而不思则罔”。一个人只知道学习,而不知道思考,就会感到迷惘。学习编程语言亦是如此,如果正真理解了封装的好处,如上述代码,如果把前两层根据测试的需要封装好,那么“一劳永逸”就有可能实现,我们只需要在服务层,写方法,传参数即可。有时还可以根据需要采用不同的设计模式。人与机器最大的区别就是人有意识有思想,代码是死的,人是活的,有了好的想法和思想,剩下的就是用代码实现了。万不可对前人的代码生吞活剥,要取其精华,弃其糟粕。“流水不腐,户枢不蠹”,有独立和独特的思想才是人与人最大的区别。