zoukankan      html  css  js  c++  java
  • PO设计模式

    Page Object Model:

    PO设计模式是selenium自动化测试中最佳的设计模式之一,主要体现在对界面交互细节的封装,也就是在实际测试中只关注业务流程就OK了

    传统的设计中,在新增测试用例之后,代码会有以下几个问题:

    1.易读性差:一连串的find element会使代码显得杂乱无章

    2.可扩展性不好:用例孤立,无法扩展

    3.可复用性差:无公共方法,很难复用

    4.可维护性差:一旦元素变化,需要维护修改大量测试用例

    因此考虑到优化:

      PO模式是一种自动化测试设计模式,讲页面定位和业务操作分开,也就是把对象的定位和测试脚本分开,从而提供可维护性。

      首先抽象封装一个BasePage类,这个基类拥有一些指向Webdriver实例的属性,然后每一个Page继承基类BasePage,可以通过driver管理每一个Page中的元素,而且在Page中将这些操作封装为一个一个的方法。TestCase继承unittest里面的TestCase类,并且依赖page类,进行组织测试步骤的工作。

      这样做的好处,就是有元素变化,只需要维护每一个Page就行了,测试步骤变化,只需要维护TestCase即可

    PO各个核心要素的介绍:

    BasePage:

    class BasePage(object):
        def __init__(self,driver):
            self.driver = driver
    
        pass

    Page:

    from SeleniumProject.PO.BasePage import BasePage
    class LoginBase(BasePage):
        # 定位元素,括号中是通过find_element来获取元素的属性
        uname = ()
        pwd = ()
    
        def set_uname(self,uname):
            name =self.driver.find_element(*LoginBase.uname)
            name.send_keys("用户名")
        def set_pwd(self,pwd):
            password = self.driver.find_element(*LoginBase.pwd)
            password.send_keys("密码")
    
        pass

    TestCase:

    from unittest import TestCase
    import unittest
    from selenium import webdriver
    class Test_Login(TestCase):
        def setUp(self):
            self.driver = webdriver.Chrome()
            self.driver.get("https://cn.bing.com/")
    
        # 测试步骤
        def test_Login(self):
            self.driver.get(self.base_url)
            pass
    
        def tearDown(self):
            self.driver.quit()
    
    if __name__ == "__main__":
        unittest.main()

    下面举一个简单的例子来看一下PO模式:

      业务要求就是,用Chrome浏览器,在https://cn.bing.com/中搜索“墨菲特”,然后点击搜索按钮,再关闭浏览器

    基类BasePage类:

    from selenium import webdriver
    from selenium.webdriver.support.wait import WebDriverWait
    from selenium.webdriver.support import expected_conditions as EC
    
    
    class BasePage(object):
        """BasePage封装所有页面的公有方法,例如url、driver、find_element"""
        # 构造函数里面的参数就是类的所有参数
        def __init__(self,selenuime_driver,base_url):
            self.driver = selenuime_driver
            self.url = base_url
    
        # 定义一个私有方法,其他类不能调用该方法
        def _open(self,url):
            self.driver.get(url)
            self.driver.maximize_window()
    
        # 定义open()方法,调用_open()方法
        def open(self):
            self._open(self.base_url)
    
        # 重写find_element()方法,参数为任意数量的(带*的参数)
        # 此方法是为了保证元素是可见的
        def find_emelemt(self,*loc):
            try:
                # 保证元素可见
                WebDriverWait(self.driver,10).until(EC.visibility_of_all_elements_located(loc))
                return self.driver.find_element(*loc)
            except:
                print("页面中没有%s %" % (self.loc))
    
        # 定义script()方法,用于执行JS脚本,比方上上传文件啥的
        def script(self,src):
            self.driver.excute_script(src)
    
        # 定义页面跳转方法,比方说有的页面有frame嵌套
        def switch_frame(self,loc):
            return self.driver.switch_to_frame(loc)
    
        # 重新定义send_keys()方法,为了保证搜索按钮是否存在,还有有的输入框中默认有值,要清空
        def send_keys(self,loc,value,clear_first=True,click_first=True):
            try:
                # getattr方法相当于实现了self.loc
                loc = getattr(self,"_%s"%loc)
                # 是否存在搜索按钮
                if click_first:
                    self.find_element(*loc).click()
                # 清空搜索框中的值,并输入需要搜索的值
                if clear_first:
                    self.find_emelemt(*loc).clear()
                    self.find_emelemt(*loc).send_keys(value)
    
            except:
                print("页面上未找到%s元素"%(self.loc))

    Page类:

    from selenium.webdriver.common.by import By
    from SeleniumProject.PO.BasePage import BasePage
    
    class SearchPage(BasePage):
        # 定位元素
        search_loc = (By.NAME,"q") #搜索框
        btn_loc = (By.NAME,"go")    #搜索按钮
    
        # 重写父类的open()方法
        def open(self):
            self._open(self.base_url)
    
        def search_content(self,content):
            # 调用父类的find_emelemt,然后将本类的参数传入
            content1 =  self.find_emelemt(*self.search_loc)
            content1.send_keys(content)
    
        def btn_click(self):
            btn1 = self.find_emelemt(*self.btn_loc)
            btn1.click()

    TestCase类:

    from unittest import TestCase
    import unittest
    from selenium import webdriver
    from time import sleep
    from SeleniumProject.PO.Search import SearchPage
    class CaseRun(TestCase):
        def setUp(self):
            self.driver = webdriver.Chrome()
            sleep(3)
            self.url = "https://cn.bing.com/"
            sleep(3)
            self.content = "墨菲特"
        # 测试步骤
        def test_search(self):
            bing_page = SearchPage(self.driver,self.url)
            bing_page.open()
            sleep(3)
            bing_page.search_content(self.content)
            sleep(3)
            bing_page.btn_click()
            sleep(3)
    
        def tearDown(self):
            self.driver.quit()
    
    if __name__ == "__main__":
        unittest.main()
  • 相关阅读:
    DNS
    NTP服务
    DHCP服务
    NFS服务、SSHD服务
    samba 、 FTP 、 lrzsz工具
    centos7系统忘记root密码
    linux系统rpm和yum软件包管理
    linux系统命令(调试命令)(nmtui,ip a、ss、ps、uptime、top、lsof、grep,iotop、iftop)
    浅聊TCP的三次握手和四次挥手
    C语言学习笔记--动态库和静态库的使用
  • 原文地址:https://www.cnblogs.com/bigbigtong/p/10294516.html
Copyright © 2011-2022 走看看