Page Object 设计原理

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

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

它的好处如下:

集中管理元素对象

集中管理一个page内的公共方法

后期维护方便

Page Object 的对象

WebDriver封装

这里是对Selenium的封装,完成封装以后的基本封装代码。

Page 基类

设计了一个基本的Page类,以便所有的页面进行继承,该类标明了一个sub page类的基本功能和公共的功能。

Sub Pages(s)子类

具体的页面的类,定义了某个具体的页面的功能。

Tests 类

这部分描述的是具体的测试用例。

定义Test Suite

多个测试用例添加在一个Test套件里面,一起执行。

定义Test Runner

设计测试的Runner,开启整个测试,并且对测试的结果生成HTML测试报告,并通过邮件发送到指定邮箱。

定义测试的主入口

定义测试的主要入口类,代码的入口

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")

参考阅读

评论可见,请评论后查看内容,谢谢!!!评论后请刷新页面。