• Selenium+Python :WebDriver设计模式( Page Object )


    Page Object 设计原理

    Page Object设计模式是Selenium自动化测试项目的最佳设计模式之一,强调测试、逻辑、数据和驱动相互分离。

    Page Object模式是Selenium中的一种测试设计模式,主要是将每一个页面设计为一个Class,其中包含页面中需要测试的元素(按钮,输入框,标题等),这样在Selenium测试页面中可以通过调用页面类来获取页面元素,这样巧妙的避免了当页面元素id或者位置变化时,需要改测试页面代码的情况。当页面元素id变化时,只需要更改测试页Class中页面的属性即可。

    它的好处如下:

    • 集中管理元素对象
    • 集中管理一个page内的公共方法
    • 后期维护方便

    Page Object 的对象

    1. WebDriver封装
      • 这里是对Selenium的封装,完成封装以后的基本封装代码。
    2. Page 基类
      • 设计了一个基本的Page类,以便所有的页面进行继承,该类标明了一个sub page类的基本功能和公共的功能。
    3. Sub Pages(s)子类
      • 具体的页面的类,定义了某个具体的页面的功能。
    4. Tests 类
      • 这部分描述的是具体的测试用例。
    5. 定义Test Suite
      • 多个测试用例添加在一个Test套件里面,一起执行。
    6. 定义Test Runner
      • 设计测试的Runner,开启整个测试,并且对测试的结果生成HTML测试报告,并通过邮件发送到指定邮箱。
    7. 定义测试的主入口
      • 定义测试的主要入口类,代码的入口

    HTML测试报告

    HTML测试报告需要引入HTMLTestRunner

    from ranzhiWeekend import HTMLTestRunner

    HTMLTestRunner是基于Python2.7的,我们的课程讲义基于Python3.x,那么需要对这个文件做一定的修改。

    测试的示例代码如下

           # 声明一个测试套件
            suite = unittest.TestSuite()
            # 添加测试用例到测试套件
            suite.addTest(RanzhiTests("test_ranzhi_login"))
    
            # 创建一个新的测试结果文件
            buf = open("./result.html", "wb")
    
            # 声明测试运行的对象
            runner = HTMLTestRunner.HTMLTestRunner(stream=buf,
                                                   title="Ranzhi Test Result",
                                                   description="Test Case Run Result")
            # 运行测试,并且将结果生成为HTML
            runner.run(suite)
    
            # 关闭文件输出
            buf.close()

    集成测试报告

    使用邮件发送HTML测试报告的脚本如下

            # 打开测试报告结果
            f = open("./result.html", "rb")
    
            # 将测试结果放到邮件的主体中
            mailBody = f.read()
            # 关闭测试结果的文件
            f.close()
    
            # 声明一个邮件对象,用刚刚得到的邮件主体
            msg = MIMEText(mailBody, "html", "utf-8")
            # 设置邮件的主题
            msg["subject"] = Header("Automation Test Result", "utf-8")
    
            # 创建一个SMTP服务对象
            # simple message transfer protocol
            # 简单的消息转移协议
            smtpMail = smtplib.SMTP()
    
            # 连接SMTP的服务器
            smtpMail.connect("mail.51testing.com")
    
            # 登录SMTP的服务器
            smtpMail.login("liutingli@51testing.com", "123456789")
    
            # 使用SMTP的服务器发送邮件
            smtpMail.sendmail("liutingli@51testing.com", targetEmail, msg.as_string())
    
            # 退出SMTP对象
            smtpMail.quit()

    自动化测试框架示例

    WebDriver封装

    # coding=utf-8
    from selenium import webdriver
    from selenium.webdriver.support.select import Select
    
    
    class AutomateDriver(object):
        """
        a simple demo of selenium framework tool
        """
    
        def __init__(self):
    
            driver = webdriver.Firefox()
            try:
                self.driver = driver
            except Exception:
                raise NameError("Firefox Not Found!")
    
    
        def clearCookies(self):
            """
            clear all cookies after driver init
            """
            self.driver.delete_all_cookies()
    
        def refreshBrowser(self):
            self.driver.refresh()
    
        def maximizeWindow(self):
            self.driver.maximize_window()
    
        def navigate(self, url):
            self.driver.get(url)
    
        def quitBrowser(self):
            self.driver.quit()
    
        def closeBrowser(self):
            self.driver.close()
    
        def getElement(self, selector):
            """
            to locate element by selector
            :arg
            selector should be passed by an example with "i,xxx"
            "x,//*[@id='langs']/button"
            :returns
            DOM element
            """
            if ',' not in selector:
                return self.driver.find_element_by_id(selector)
            selector_by = selector.split(',')[0]
            selector_value = selector.split(',')[1]
    
            if selector_by == "i" or selector_by == 'id':
                element = self.driver.find_element_by_id(selector_value)
            elif selector_by == "n" or selector_by == 'name':
                element = self.driver.find_element_by_name(selector_value)
            elif selector_by == "c" or selector_by == 'class_name':
                element = self.driver.find_element_by_class_name(selector_value)
            elif selector_by == "l" or selector_by == 'link_text':
                element = self.driver.find_element_by_link_text(selector_value)
            elif selector_by == "p" or selector_by == 'partial_link_text':
                element = self.driver.find_element_by_partial_link_text(selector_value)
            elif selector_by == "t" or selector_by == 'tag_name':
                element = self.driver.find_element_by_tag_name(selector_value)
            elif selector_by == "x" or selector_by == 'xpath':
                element = self.driver.find_element_by_xpath(selector_value)
            elif selector_by == "s" or selector_by == 'selector_selector':
                element = self.driver.find_element_by_css_selector(selector_value)
            else:
                raise NameError("Please enter a valid type of targeting elements.")
    
            return element
    
        def type(self, selector, text):
            """
            Operation input box.
    
            Usage:
            driver.type("i,el","selenium")
            """
            el = self.getElement(selector)
            el.clear()
            el.send_keys(text)
    
        def click(self, selector):
            """
            It can click any text / image can be clicked
            Connection, check box, radio buttons, and even drop-down box etc..
    
            Usage:
            driver.click("i,el")
            """
            el = self.getElement(selector)
            el.click()
    
        def selectByIndex(self, selector, index):
            """
            It can click any text / image can be clicked
            Connection, check box, radio buttons, and even drop-down box etc..
    
            Usage:
            driver.select_by_index("i,el")
            """
            el = self.getElement(selector)
            Select(el).select_by_index(index)
    
        def clickByText(self, text):
            """
            Click the element by the link text
    
            Usage:
            driver.click_text("新闻")
            """
            self.getElement('p,' + text).click()
    
        def submit(self, selector):
            """
            Submit the specified form.
    
            Usage:
            driver.submit("i,el")
            """
            el = self.getElement(selector)
            el.submit()
    
        def executeJs(self, script):
            """
            Execute JavaScript scripts.
    
            Usage:
            driver.js("window.scrollTo(200,1000);")
            """
            self.driver.execute_script(script)
    
        def getAttribute(self, selector, attribute):
            """
            Gets the value of an element attribute.
    
            Usage:
            driver.get_attribute("i,el","type")
            """
            el = self.getElement(selector)
            return el.getAttribute(attribute)
    
        def getText(self, selector):
            """
            Get element text information.
    
            Usage:
            driver.get_text("i,el")
            """
            el = self.getElement(selector)
            return el.text
    
        def getDisplay(self, selector):
            """
            Gets the element to display,The return result is true or false.
    
            Usage:
            driver.get_display("i,el")
            """
            el = self.getElement(selector)
            return el.is_displayed()
    
        def getTitle(self):
            '''
            Get window title.
    
            Usage:
            driver.get_title()
            '''
            return self.driver.title
    
        def getUrl(self):
            """
            Get the URL address of the current page.
    
            Usage:
            driver.get_url()
            """
            return self.driver.current_url
    
        def acceptAlert(self):
            '''
                Accept warning box.
    
                Usage:
                driver.accept_alert()
                '''
            self.driver.switch_to.alert.accept()
    
        def dismissAlert(self):
            '''
            Dismisses the alert available.
    
            Usage:
            driver.dismissAlert()
            '''
            self.driver.switch_to.alert.dismiss()
    
        def implicitlyWait(self, secs):
            """
            Implicitly wait. All elements on the page.
    
            Usage:
            driver.implicitly_wait(10)
            """
            self.driver.implicitly_wait(secs)
    
        def switchFrame(self, selector):
            """
            Switch to the specified frame.
    
            Usage:
            driver.switch_to_frame("i,el")
            """
            el = self.getElement(selector)
            self.driver.switch_to.frame(el)
    
        def switchDefaultFrame(self):
            """
            Returns the current form machine form at the next higher level.
            Corresponding relationship with switch_to_frame () method.
    
            Usage:
            driver.switch_to_frame_out()
            """
            self.driver.switch_to.default_content()
    
        def openNewWindow(self, selector):
            '''
            Open the new window and switch the handle to the newly opened window.
    
            Usage:
            driver.open_new_window()
            '''
            original_windows = self.driver.current_window_handle
            el = self.getElement(selector)
            el.click()
            all_handles = self.driver.window_handles
            for handle in all_handles:
                if handle != original_windows:
                    self.driver._switch_to.window(handle)

    Base Page类

    class RanzhiBasePage():
        def __init__(self, driver, baseUrl):
            """
            构造方法
            :param driver: 封装好的webdriver
            :param baseUrl: 然之系统的基本url http://【localhost:808】/ranzhi/www
            """
    
            self.baseUrl = baseUrl
            self.driver = driver
    
        def openPage(self, url):
            """
            打开然之系统的页面,通过拼接URL的方式
            :param url: /sys/index.html
            :return:
            """
            self.driver.navigate(self.baseUrl + url)

    Sub Page类

    from ranzhiWeekend.ranzhi_base_page import RanzhiBasePage
    
    
    class RanzhiSubLoginPage(RanzhiBasePage):
        def __init__(self, driver, baseUrl):
            """
    
            :param driver:
            :param baseUrl:
            """
            # 调用其 基类 RanzhiBasePage的 构造函数
            # 实现 基类 的构造函数的功能
            super().__init__(driver, baseUrl)
            self.loginPageUrl = "/sys/user-login.html"
            self.mainPageUrl = "/sys/index.html"
            self.driver.clearCookies()
    
        def login(self, userName, password):
            self.openPage(self.loginPageUrl)
            # self.driver.clearCookies()
            self.driver.implicitlyWait(5)
            self.driver.type("account", userName)
            self.driver.type("password", password)
            self.driver.click("submit")
    
        def getMainPage(self):
            return self.baseUrl + self.mainPageUrl

    Tests Case 类

    import unittest
    from time import sleep
    
    from ranzhiWeekend.automate_driver import AutomateDriver
    from ranzhiWeekend.ranzhi_sub_login_page import RanzhiSubLoginPage
    
    """
    1. 导入 unittest
    2. 继承 unittest.TestCase
    3. 写用例 方法以 test 开头
    4. 考虑使用 setUp() 和 tearDown()
    """
    
    
    class RanzhiTests(unittest.TestCase):
        def setUp(self):
            """
            开始每个测试前的准备事项
            :return:
            """
            self.autoDriver = AutomateDriver()
            self.baseUrl = "http://localhost:808/ranzhi/www"
    
        def tearDown(self):
            """
            结束每个测试后的清理工作
            :return:
            """
            self.autoDriver.quitBrowser()
    
        def test_ranzhi_login(self):
            """
            测试用例:测试然之登录
            :return:
            """
            # 新建然之的页面对象
            loginPage = RanzhiSubLoginPage(self.autoDriver, self.baseUrl)
    
            # 利用然之的页面对象进行登录
            loginPage.login("admin", "admin")
            sleep(2)
            # 断言 是否登录成功
            self.assertEqual(loginPage.getMainPage(), self.autoDriver.getUrl(), u"登录失败")

    Tests Runner类

    import smtplib
    import unittest
    from email.header import Header
    from email.mime.text import MIMEText
    
    from ranzhiWeekend import HTMLTestRunner
    from ranzhiWeekend.ranzhi_tests_0605 import RanzhiTests
    
    
    class RanzhiTestRunner():
    
        def runTest(self):
            """
            运行测试用例
            :return:
            """
    
            # 声明一个测试套件
            suite = unittest.TestSuite()
            # 添加测试用例到测试套件
            suite.addTest(RanzhiTests("test_ranzhi_login"))
    
            # 创建一个新的测试结果文件
            buf = open("./result.html", "wb")
    
            # 声明测试运行的对象
            runner = HTMLTestRunner.HTMLTestRunner(stream=buf,
                                                   title="Ranzhi Test Result",
                                                   description="Test Case Run Result")
            # 运行测试,并且将结果生成为HTML
            runner.run(suite)
    
            # 关闭文件输出
            buf.close()
    
        def sendEmail(self, targetEmail):
            """
            发送邮件
            :param targetEmail:
            :return:
            """
    
            # 打开测试报告结果
            f = open("./result.html", "rb")
    
            # 将测试结果放到邮件的主体中
            mailBody = f.read()
            # 关闭测试结果的文件
            f.close()
    
            # 声明一个邮件对象,用刚刚得到的邮件主体
            msg = MIMEText(mailBody, "html", "utf-8")
            # 设置邮件的主题
            msg["subject"] = Header("Automation Test Result", "utf-8")
    
            # 创建一个SMTP服务对象
            # simple message transfer protocol
            # 简单的消息转移协议
            smtpMail = smtplib.SMTP()
    
            # 连接SMTP的服务器
            smtpMail.connect(“***.******.com")
    
            # 登录SMTP的服务器
            smtpMail.login(“*******@*****.com", “*********")
    
            # 使用SMTP的服务器发送邮件
            smtpMail.sendmail(“*******@********.com", targetEmail, msg.as_string())
    
            # 退出SMTP对象
            smtpMail.quit()

    main函数入口

    if __name__ == "__main__":
        # 实例化一个runner
        runner = RanzhiTestRunner()
    
        # 执行测试
        runner.runTest()
    
        # 发送测试结果
        runner.sendEmail(“********@******.com")
  • 相关阅读:
    Zabbix安装部署
    设计模式目录导航
    [内排序]八大经典排序合集
    SpringBoot集成基于tobato的fastdfs-client实现文件上传下载和删除
    Docker部署FastDFS(附示例代码)
    Docker部署Portainer搭建轻量级可视化管理UI
    Maven基础知识详解
    SpringBoot整合Swagger2详细教程
    screw一键生成数据库文档
    SpringBoot + Mybatis-Plus 实现多数据源简单示例
  • 原文地址:https://www.cnblogs.com/alamZ/p/6899124.html
Copyright © 2020-2023  润新知