• 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")
  • 相关阅读:
    You are not late! You are not early!
    在同一个服务器(同一个IP)为不同域名绑定的免费SSL证书
    Vue.js Is Good, but Is It Better Than Angular or React?
    It was not possible to find any compatible framework version
    VS增加插件 Supercharger破解教程
    Git使用ssh key
    Disconnected: No supported authentication methods available (server sent: publickey)
    VS 2013打开.edmx文件时报类型转换异常
    asp.net MVC4 框架揭秘 读书笔记系列3
    asp.net MVC4 框架揭秘 读书笔记系列2
  • 原文地址:https://www.cnblogs.com/alamZ/p/6899124.html
Copyright © 2020-2023  润新知