基于appium实现的线性代码引用unittest单元测试框架

Posted 温一壶清酒

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了基于appium实现的线性代码引用unittest单元测试框架相关的知识,希望对你有一定的参考价值。

在前段时间,分享了几篇关于appium基础的博文,再加上期间也有讲到unittest测试框架,所以今天就来一个专题,在appium+python实现的线性代码基础上,引入unittest框架,使代码更简洁。

之前的博客,可以见以下链接快速阅读:

基于Python的Appium环境搭建合集

Genymotion模拟器的安装及脚本制作

Appium Python API 中文版

Appium-Server与Appium-Desktop的区别

单元测试框架Uinttest一文详解

在以上博文中,代码示例,很多只是个线性脚本,没有太多的实用之处,用来写个demo还是可以,但实际运用到产品中,就不行了。脚本还是得引用框架,这样看起来,代码就不会那么乱,更有逻辑性,便于维护。

好了,进入正题,对unittest以及appium还不熟悉的,可以先阅读如上的博文了解,此篇文中,就不赘述了。

unittest代码优化一

优化逻辑:

①将启用服务字段放到初始化当中

②将输入账号、输入密码、获取当前activity的操作封装成一个个函数

③在用例中去调用需要执行的函数

示例代码如下:

import selenium
import time
from appium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
import unittest

\'\'\'
@author: wenyihuqingjiu
@project: appiumcode
@file: test_login.py
@time: 2019-10-20 22:11
@desc:
\'\'\'

print(\'selenium version = \', selenium.__version__)


def input_account(self):
    account = self.driver.find_element_by_id(\'id/rel_content\')
    account.find_element_by_id(\'id/edit_acount\')
    print("定位输入框")
    self.driver.press_keycode(61)
    print("换行操作")
    account.send_keys(\'\')
    print("账号输入完毕")
    time.sleep(2)


def current(self):
    ac = self.driver.current_activity
    print(\'当前activity:\' + ac)


def input_password(self):
    # genymotion只需要一次换行
    self.driver.press_keycode(61)
    print("换行操作")
    password = self.driver.find_element_by_id(\'id/rel_content\')
    password.find_element_by_id(\'id/edit_pass\')
    print("定位输入框")
    password.send_keys(\'\')
    print("输入密码")
    self.driver.find_element_by_xpath(\'//android.widget.TextView[@text="登 录"]\').click()
    print("点击登录")
    time.sleep(5)
    print(\'登录成功\')


class case_01(unittest.TestCase):
    @classmethod
    def setUpClass(cls):

        desired_caps = {

            \'platformName\': \'Android\',
            \'platformVersion\': \'4.4.4\',
            \'deviceName\': \'S5\',
            \'appPackage\': \'\',
            # 非首次登录的activity
            \'appActivity\': \'.ui.login.view.LoginActivity\',
            \'udid\': \'192.168.66.101:5555\',
            \'noReset\': \'true\',


        }
        cls.driver = webdriver.Remote(\'http://192.168.1.101:4723/wd/hub\', desired_caps)
        print("服务启动成功")

    @classmethod
    def tearDownClass(cls):
        cls.driver.quit()

    def add_img(self):
        self.imgs.append(self.driver.get_screenshot_as_base64())
        return True

    def setUp(self):
        # 在是python3.x 中,如果在这里初始化driver ,因为3.x版本 unittestbasic1 运行机制不同,会导致用力失败时截图失败
        self.driver.implicitly_wait(30)
        self.imgs = []
        self.addCleanup(self.cleanup)

    def cleanup(self):
        pass

    def test_login01(self):
        input_account(self)
        current(self)
        input_password(self)


if __name__ == "__main__":
    suites = unittest.TestSuite()
    suites.addTest(case_01("test_login01"))
    runner = unittest.TextTestRunner(verbosity=2)
    runner.run(suites)

unittest代码优化二

优化逻辑:

①将启用服务字段放到初始化当中

②将输入账号、输入密码、获取当前activity的操作封装成一个个函数,并将数据参数做成形参

③在用例中去调用需要执行的函数并入参

示例代码如下:

import selenium
import time
from appium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
import unittest

\'\'\'
@author: wenyihuqingjiu
@project: appiumcode
@file: test_login.py
@time: 2019-10-20 22:11
@desc:
\'\'\'

print(\'selenium version = \', selenium.__version__)


def input_account(self, username):
    account = self.driver.find_element_by_id(\'id/rel_content\')
    account.find_element_by_id(\'id/edit_acount\')
    print("定位输入框")
    self.driver.press_keycode(61)
    print("换行操作")
    account.send_keys(username)
    print("账号输入完毕")
    time.sleep(2)


def current(self):
    ac = self.driver.current_activity
    print(\'当前activity:\' + ac)


def input_password(self, send_password):
    # genymotion只需要一次换行
    self.driver.press_keycode(61)
    print("换行操作")
    password = self.driver.find_element_by_id(\'id/rel_content\')
    password.find_element_by_id(\'id/edit_pass\')
    print("定位输入框")
    password.send_keys(send_password)
    print("输入密码")
    self.driver.find_element_by_xpath(\'//android.widget.TextView[@text="登 录"]\').click()
    print("点击登录")
    time.sleep(5)
    print(\'登录成功\')


class case_01(unittest.TestCase):
    @classmethod
    def setUpClass(cls):

        desired_caps = {

            \'platformName\': \'Android\',
            \'platformVersion\': \'4.4.4\',
            \'deviceName\': \'S5\',
            \'appPackage\': \'\',
            # 非首次登录的activity
            \'appActivity\': \'.ui.login.view.LoginActivity\',
            \'udid\': \'192.168.66.101:5555\',
            \'noReset\': \'true\',


        }
        cls.driver = webdriver.Remote(\'http://192.168.1.101:4723/wd/hub\', desired_caps)
        print("服务启动成功")

    @classmethod
    def tearDownClass(cls):
        cls.driver.quit()

    def add_img(self):
        self.imgs.append(self.driver.get_screenshot_as_base64())
        return True

    def setUp(self):
        # 在是python3.x 中,如果在这里初始化driver ,因为3.x版本 unittestbasic1 运行机制不同,会导致用力失败时截图失败
        self.driver.implicitly_wait(30)
        self.imgs = []
        self.addCleanup(self.cleanup)

    def cleanup(self):
        pass

    def test_login01(self):
        # 正常登录
        input_account(self, "")
        current(self)
        input_password(self, "")
        
    def test_login02(self):
        # 异常登录
        input_account(self, "")
        current(self)
        input_password(self, "")


if __name__ == "__main__":
    suites = unittest.TestSuite()
    suites.addTest(case_01("test_login01"))
    suites.addTest(case_01("test_login02"))
    runner = unittest.TextTestRunner(verbosity=2)
    runner.run(suites)

通过上述代码可看出,使用更方便了,可以满足正向/反向的用例设计了,是不是很简单。

代码可扩展性还有很多,在unittest基础上,再引入PO模式,那代码的健壮性就更高了,以后有时间再出类似博文。

以上是关于基于appium实现的线性代码引用unittest单元测试框架的主要内容,如果未能解决你的问题,请参考以下文章

Appium 并发多进程基于 Pytest框架

Python unittest框架实现appium登录

Appium python unittest pageobject如何实现加载多个case

python+appium+unittest 启动一次app,执行多条test

Python unittest appium

python-appium520-2引入unittest,编写自动化用例