• Web自动化测试(5)-POM


    POM设计模式

    1、简介

    POM(Page Object Model)设计模式又被称为页面对象模型,其核心思想是将web项目的每个页面当做一个对象,通过分层实现管理架构的优化,提高代码的复用性、可读性、可扩展性以及可维护性。POM设计模式主要分为Base层、PageObject层、TestCase层以及TestData层。

    名称功能
    Base层页面基础层,处理每个web页面对象的共性,或者说是相同的操作
    PageObject层不同的web页面定义不同的页面类,用于处理不同页面的差异性
    TestCase层用例层,主要包含页面测试的操作流程
    TestData层数据层,主要存储项目数据,包含配置数据、测试数据等

    2、简单示例

    关键字驱动中的示例POM设计模式的更改,首先构建basepage代码:

    from selenium import webdriver
    from selenium.webdriver.support import expected_conditions as EC
    from selenium.webdriver.support.ui import WebDriverWait
    import time
    class BasePage:
        def __init__(self, driver):
            self.driver = driver
            time.sleep(1)
            self.driver.implicitly_wait(2)
            #超时时长为10s,由于自动化需要等待网页控件的加载,所以这里设置一个默认的等待超时,时长为10秒
            self.wait = WebDriverWait(self.driver, 10) 
        # 打开浏览器
        def open_browser(self,browser):
            browser = browser.capitalize()
            if browser in ["Chrome","Edge","Firefox"]:
                browser_driver = {"Chrome":"chromedriver","Edge":"MicrosoftWebDriver","Firefox":"geckodriver"}
                ##利用反射的方式获取浏览器驱动
                self.driver = getattr(webdriver,browser)("../%s.exe"%(browser_driver[browser]))
                self.driver.maximize_window() #窗口最大化
                self.driver.implicitly_wait(5)
            else:
                raise ValueError("未检测到支持的浏览器类型")
        # 加载网页
        def load_url(self,url):
            self.driver.get(url)
            self.driver.implicitly_wait(2)
        # 定位元素
        def locate_element(self,loc):
            # 使用*提取元组中的元素
            return self.driver.find_element(*loc)
        # 定位元素列表
        def locate_elements(self,loc):
            # 使用*提取元组中的元素
            self.wait.until(EC.presence_of_element_located(loc))
            return self.driver.find_elements(*loc)
        #输入信息
        def input(self,loc,value):
            self.locate_element(loc).send_keys(value)
            self.driver.implicitly_wait(1)
        #点击操作
        def click(self,loc):
            self.locate_element(loc).click()
            self.driver.implicitly_wait(1)
        #批量点击操作
        def click_elements(self,elements,attribute):
            for element in elements:
                if element.get_attribute(attribute):
                    element.click()
    
    • 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
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48

    接着分别构建主页搜索mainpage.py以及搜索结果点击的代码:

    import sys
    import time
    sys.path.append("..")
    from base.basepage import BasePage
    from selenium.webdriver.common.by import By
    class MainPage(BasePage):
        url = "https://www.baidu.com/"
    
        def open_page(self, url = url):
            self.load_url(url)
        
        def search_content(self, value):
            self.input((By.ID,"kw"),value)
            time.sleep(1)
            self.click((By.ID,"su"))
            time.sleep(2)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    import sys
    sys.path.append("..")
    from base.basepage import BasePage
    from selenium.webdriver.common.by import By
    import time
    class SearchResults(BasePage):
        def get_results(self,content):
            return self.locate_elements((By.XPATH,"//a[contains(string(), \'%s\')]"%(content)))
        
        def click_results(self, content,attribute):
            self.click_elements(self.get_results(content),attribute)
            time.sleep(5)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    最后构建testCase测试代码:

    from time import time
    import unittest
    import sys
    sys.path.append("..")
    from pageobjects.mainpage import MainPage
    from pageobjects.searchresults import SearchResults
    from selenium import webdriver
    import time
    class TestBaidu(unittest.TestCase):
        search_content = "selenium"
        attribute = "href"
        @classmethod
        def setUpClass(self):
            self.driver = webdriver.Edge("../../MicrosoftWebDriver.exe")
            self.driver.maximize_window()
            time.sleep(2)
            self.main_page = MainPage(self.driver)
            self.search_page = SearchResults(self.driver)
        @classmethod
        def tearDownClass(self):
            self.driver.quit()
        def test_01_openpage(self):
            self.main_page.open_page()
        def test_02_search(self):
            self.main_page.search_content(self.search_content)
        def test_03_click_results(self):
            self.search_page.click_results(self.search_content,self.attribute)
            time.sleep(5)
    
    
    if __name__ == '__main__':
        unittest.main()
    
    • 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

    3、UnitTest框架测试用例执行顺序

    从上述示例中可以看出,测试用例的函数都是以“test_dd_xxxx”的命名格式进行命名,其中“dd”表示手动指定测试用例的执行顺序,通常来说unittest框架进行自动化测试时会对测试用例进行排序,通常情况下排序的结果与字符串排序结果类似,因此如果存在多个测试用例,在不补0的情况下“test_11”会比“test_2”先执行,导致测试用例的执行顺序与预期不符的情况,因此,为了避免此种情况的发生,可以采用补0的方式即将“test_2”改为“test_02”,在这种情况下,“test_02”会先于“test_11”执行,对于测试用例特别多,比如成百上千个,可以考虑修改unittest加载测试用例的排序函数,也可以采取补0的方式。

    4、数据驱动

    数据驱动主要指通过一组数据或者数据文件对同一组脚本进行循环测试,从而实现数据与脚本的分离,从而提供代码的复用性、扩展性。本文利用ddt扩展库实现数据驱动的自动化测试。ddt的安装比较简单,使用如下代码即可完成安装:

    pip install ddt
    
    • 1

    ddt模块主要包含类的装饰器ddt和两个方法装饰器data,具体如下表所示:

    名称功能
    ddt.ddt装饰类,继承了TestCase类
    ddt.data装饰测试方法,参数是一系列的值
    ddt.file_dat装饰测试方法,参数是文件名,文件类型可以是json或者yaml

    5、简单示例

    对上文中的示例进行改进,主要更改testcases.py,主要修改三处,首先引入依赖项,接着对测试类进行装饰,最后对测试方法进行装饰,此外,为了简化测试,删减了test_03测试用例:

    from time import time
    import unittest
    import sys
    sys.path.append("..")
    from pageobjects.mainpage import MainPage
    from pageobjects.searchresults import SearchResults
    from selenium import webdriver
    import time
    from ddt import ddt,data # 第一处修改,引入ddt依赖库
    @ddt # 第二处修改,使用类装饰器
    class TestBaidu(unittest.TestCase):
        search_content = "selenium"
        attribute = "href"
        @classmethod
        def setUpClass(self):
            self.driver = webdriver.Edge("../../MicrosoftWebDriver.exe")
            self.driver.maximize_window()
            time.sleep(2)
            self.main_page = MainPage(self.driver)
            self.search_page = SearchResults(self.driver)
        @classmethod
        def tearDownClass(self):
            self.driver.quit()
        def test_01_openpage(self):
            self.main_page.open_page()
        # 第三处修改,装饰测试方法
        @data("selenium","web自动化","python")
        def test_02_search(self,search_content):
            self.main_page.search_content(search_content)
    
    
    if __name__ == '__main__':
        unittest.main()
    
    • 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
  • 相关阅读:
    ch4-2 音频信号的时域特征
    Python压缩解压–tarfile
    【案例分享】BenchmarkSQL 5.0 压测 openGauss 5.0.0
    第三章:用MPI进行分布式内存编程
    【C++】鱼的一生, 智能指针的实现
    冯喜运:4.24-4.25黄金原油双双跳水、今日走势分析
    蓝牙信标的优势及应用场景
    当酷雷曼VR直播遇上视频号,会摩擦出怎样的火花?
    NVMe SSD 基本功
    记一次生产内存溢出分析解决
  • 原文地址:https://blog.csdn.net/Lxh19920114/article/details/126323976