页面对象模型(Page Objects Model, POM )是一组旨在表示一个或多个网页的类, 用1个类来保存1个网页上所有的元素,相似的网页可以重用此类。
1个网站通常有多个页面,可以用多个页面类对象分别代表各个页面,其好处有:
使用页面对象的项目的通常结构类似于
|-- pages
|--- locators.py
|--- elements.py
|--- pages.py
|-- tests
|--- test_contact_page.py
各文件说明:
本例 test_contact_page.py 用于在colibri-software.com网站填写 Contact Me表单,判断是否填写结果是否成功
import unittest
from selenium import webdriver
import pages
class TestColibriSoftwareContactMe(unittest.TestCase):
def setUp(self):
self.driver = webdriver.Firefox()
self.driver.get("https://www.colibri-software.com")
def test_submit_contact_me_form(self):
"""
"Contact me" 测试表单
填写各字段,提交表单,验证提交是否成功
"""
# 加载主页,本例为 colibri-software.com主页
contact_page = pages.ContactPage(self.driver)
# Checks if the word "Contact" is in title
assert contact_page.is_title_matches()
# 向表单各字段填写内容
contact_page.name_input = 'John Doe'
contact_page.company_name_input = 'John Doe\'s paper company'
contact_page.email_input = '[email protected]'
contact_page.additional_info_input = 'I need a website to sell paper online'
# 提前表单
contact_page.click_submit_form_button()
# 验结果是否成功
assert contact_page.success_message_is_displayed()
def tearDown(self):
self.driver.close()
if __name__ == "__main__":
unittest.main()
pages.py 介绍如何编写页面对象类
from elements import BasePageElement
from locators import ContactPageLocators
class NameElement(BasePageElement):
"""
This class gets the search text from the specified locator
"""
# The locator for text box where name is entered
locator = 'wpforms-236-field_0'
# Similar classes for other text fields
class CompanyNameElement(BasePageElement):
locator = 'wpforms-236-field_4'
class EmailElement(BasePageElement):
locator = 'wpforms-236-field_1'
class AdditionalInfoElement(BasePageElement):
locator = 'wpforms-236-field_0'
class BasePage(object):
"""
Base class to initialize the base page that will be called from all pages
"""
def __init__(self, driver):
self.driver = driver
class ContactPage(BasePage):
"""
Contact page action methods come here
"""
# Declares text input fields
name_input = NameElement()
company_name_input = CompanyNameElement()
email_input = EmailElement()
additional_info_input = AdditionalInfoElement()
def is_title_matches(self):
"""
Verifies that the text "Contact" appears in page title
"""
return 'Contact' in self.driver.title
def click_submit_form_button(self):
"""
Submits the form
"""
element = self.driver.find_element(*ContactPageLocators.SUBMIT_FORM_BUTTON)
element.click()
def success_message_is_displayed(self):
success_message = 'Thanks for contacting us! We will be in touch with you shortly.'
return success_message in self.driver.page_source
elements.py 定义1个页面元素的基类,提供set(), get()方法
from selenium.webdriver.support.ui import WebDriverWait
class BasePageElement(object):
"""
Base page class that is initialized on every page object class.
"""
def __set__(self, obj, value):
"""
Sets the text to the value supplied
"""
driver = obj.driver
WebDriverWait(driver, 100).until(lambda driver: driver.find_element_by_id(self.locator))
driver.find_element_by_id(self.locator).clear()
driver.find_element_by_id(self.locator).send_keys(value)
def __get__(self, obj, owner):
"""
Gets the text of the specified object
"""
driver = obj.driver
WebDriverWait(driver, 100).until(lambda driver: driver.find_element_by_id(self.locator))
element = driver.find_element_by_id(self.locator)
return element.get_attribute("value")
6.2.4 locators 定位器类
一个好的编程习惯做法是,分离定位字符。在这个例子中,同一页面的定位器属于同一个类。
from selenium.webdriver.common.by import By
class ContactPageLocators(object):
"""
A class for all Contact page locators.
"""
SUBMIT_FORM_BUTTON = (By.CSS_SELECTOR, 'button[type="submit"]')
class SearchResultsPageLocators(object):
"""A class for search results locators. All search results locators should come here"""
pass