• UnitTest + Selenium 完成在线加法器自动化测试


    1. 任务概述

    利用 UnitTest 与 Selenium 编写自动化用例,测试在线加法器中的整数单次加法功能【如1+2=3 】

    image-20231116123419627

    人工操作流程(测试 1+2 是否等于 3):

    1. 打开在线加法器
    2. 点击按钮1,再点击按钮+,再点击按钮2,再次点击按钮=
    3. 观察计算机框框的计算结果是否等于3,若出现错误则截图保留,否则测试通过
    4. 关闭浏览器

    自动化测试编写流程:

    1. 使用 selenium 实例化浏览器,打开在线加法器并最大化窗口

    2. 使用 CSS 选择器定位至按钮清屏,点击【此处是为了保险】

      使用 CSS 选择器定位至按钮1,点击

      使用 CSS 选择器定位至按钮+,点击

      使用 CSS 选择器定位至按钮2,点击

      使用 CSS 选择器定位至按钮=,点击

    3. 使用 CSS 选择器定位至结果框框,获取此组件value值并与预期结果3进行比对,过程中发生错误截图保留

    4. 关闭浏览器

    2. PO模式

    Page Objece,分层机制,让不同层去做不同类型的事情,让代码结构清晰,增加复⽤性

    • 两层:对象逻辑层 + 业务数据层
    • 三层:对象库层 + 逻辑层 + 业务数据层【本案例所使用】
    • 四层:对象库层 + 逻辑层 + 业务层 + 数据层

    base层

    将最基础的一类方法进行封装,如点击click,获取value值,浏览器实例化等操作,通过被继承从而实现复用

    page层

    定义一些配置数据,如在线计算器网址,各按钮的定位方式等,同时通过继承 Base 类得到一些基础方法,在此基础上进一步完善处理逻辑

    scripts层

    编写测试类,完善业务处理流程,script 调用 page 并设置断言【即结果是否正确】,发生错误时完成截图并存储至于 image 层

    3. 源码详情

    image-20231116133902844

    base层

    base.py

    import time
    from selenium.webdriver.support.wait import WebDriverWait
    class Base:
        # 初始化方法
        def __init__(self,driver):
            self.driver = driver
        # 查找元素
        def base_find_element(self,loc,timeout=30,poll_frequency=0.5):
            """
            :param loc: 元素的定位信息,格式为元组
            :param timeout: 显式等待最长时间
            :param poll_frequency: 显式等待请求间隔
            :return:  返回查找到的对象
            """
            # 显式等待特定组件
            return WebDriverWait(self.driver,
                                 timeout=timeout,
                                 poll_frequency=poll_frequency).until(lambda x:x.find_element(*loc))
        # 点击
        def base_click(self,loc):
            self.base_find_element(loc).click()
        # 获取组件value属性值
        def base_get_value(self,loc):
            return self.base_find_element(loc).get_attribute('value')
        # 截图
        def base_get_img(self):
            self.driver.get_screenshot_as_file(f'../image/{time.strftime("%Y_%m_%d %H_%M_%S")}.png')
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    get_driver.py

    from selenium import webdriver
    from calcTestProject import page
    class GetDriver:
        driver = None
        # 获取driver
        @classmethod
        def get_driver(cls):
            if cls.driver is None:
                option = webdriver.ChromeOptions()
                # 指定chrome存储路径的二进制形式
                option.binary_location = page.binary_location
                # 实例化浏览器
                cls.driver = webdriver.Chrome(options=option)
                # 最大化窗口
                cls.driver.maximize_window()
                # 打开浏览器
                cls.driver.get(page.url)
            return cls.driver
        # 推出driver
        @classmethod
        def quit_driver(cls):
            if cls.driver:
                cls.driver.quit()
                # 置空
                cls.driver=None
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    page层

    __init__.py

    from selenium.webdriver.common.by import By
    """"以下为服务器域名配置数据"""
    url = "http://zaixianjisuanqi.bmcx.com"
    # 谷歌浏览器位置
    binary_location='D:\Chrome\Google\Chrome\Application\chrome.exe'
    """以下为计算器配置数据"""
    # 加号
    clac_add = (By.CSS_SELECTOR,'#simpleAdd')
    # 等号
    clac_eq = (By.CSS_SELECTOR,'#simpleEqual')
    # 获取结果
    clac_result = (By.CSS_SELECTOR,'#resultIpt')
    # 清屏
    clac_clear = (By.CSS_SELECTOR,'#simpleClearAllBtn')
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    page_calc.py

    from calcTestProject.base.base import Base
    from selenium.webdriver.common.by import By
    from calcTestProject import page
    class PageCalc(Base):
        # 点击数字方法
        def page_click_num(self,num):
            for n in str(num):
                # 按照计算需求拼接数字按键的loc
                loc = (By.CSS_SELECTOR,f'#simple{n}')
                self.base_click(loc)
        # 点击加号
        def page_click_add(self):
            self.base_click(page.clac_add)
        # 点击等号
        def page_click_eq(self):
            self.base_click(page.clac_eq)
        # 获取结果方法
        def page_get_value(self):
            self.base_get_value(page.clac_result)
        # 点击清屏
        def page_click_clear(self):
            self.base_click(page.clac_clear)
        # 截图
        def page_get_image(self):
            self.base_get_img()
        # 组装加法业务方法
        def page_add_calc(self,a,b):
            # 清屏
            self.page_click_clear()
            # 点击第一个数
            self.page_click_num(a)
            # 点击加号
            self.page_click_add()
            # 点击第二个数
            self.page_click_num(b)
            # 点击等号
            self.page_click_eq()
            # 返回计算结果
            return self.page_get_value()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39

    script层

    test_calc.py

    import unittest
    from parameterized import parameterized
    from calcTestProject.page.page_calc import PageCalc
    from calcTestProject.base.get_driver import GetDriver
    
    class TestCalc(unittest.TestCase):
        # 类前置操作
        @classmethod
        def setUpClass(cls):
            # 获取driver对象
            cls.driver = GetDriver().get_driver()
            cls.calc = PageCalc(cls.driver)
            # 下拉条,防止广告遮挡
            js = "window.scrollTo(0,256)"
            cls.driver.execute_script(js)
    
        # 类后置操作
        @classmethod
        def tearDownClass(cls):
            GetDriver().quit_driver()
        # 测试加法方法(1+2是否等于3)
        @parameterized.expand(((1,2,3),))
        def test_add_calc(self,a,b,expect):
            # 调用计算业务方法
            self.calc.page_add_calc(a,b)
            try:
                # 断言【判断测试结果】
                self.assertEqual(self.calc.page_get_value(),str(expect))
            except:
                # 截图
                self.calc.page_get_image()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
  • 相关阅读:
    Linux的查找,压缩,别名,用户管理的相关命令
    ESP32 ① 编译环境
    基于Docker的JMeter分布式压测
    JS函数(function)的定义和使用
    MyBatis3.4全集笔记
    [附源码]java毕业设计教师档案管理系统
    基于Java毕业设计养老机构管理信息系统源码+系统+mysql+lw文档+部署软件
    halcon学习和实践(设备要求)
    WorkManager学习一
    连续时间随机游走(Continuous-time random walk, CTRW)
  • 原文地址:https://blog.csdn.net/weixin_45488428/article/details/134440134