POM是PageObjectModule(页面对象模式)的缩写,其目的是为了Web UI测试创建对象库。在这种模式下,应用涉及的每一个页面应该定义为一个单独的类。类中应该包含此页面上的页面元素对象和处理这些元素对象所需要的方法等。将流程所关联的页面作为对象,将对象串联起来,形成一个个不同的流程,POM是业内公认最佳的设计模式。
(1)PO提供了页面元素操作和业务流程相分离的模式,可以使测试的代码结构比之前清晰,可读性强。
(2)更方便地复用对象和方法。
(3)对象库是独立于测试用例的、统一的对象库,可以通过集成不同的工具类来达到不同的测试目的。比如集成UnitTest可以用来做单元测试、自动化/功能测试,同时也可以集成JBehave/Cucumber等来做验收测试。
(4)使得整体自动化测试的优点变得更容易一些,如果有某个页面的元素需要变更,那么就可以直接更改封装好的页面元素类即可,而不用更改调用它的其他测试类/代码。这样整个的代码维护成本也会缩减。
PO的核心就是分层思想,把同属于一个页面的元素都放在一个页面类中。
以上概念内容来源于某书籍

2. 在base包下新建一个base_page.py文件,在base_page.py文件下新建一个BasePage类作为基类,提供各个常用的已封装好的函数,便于后续的页面对象类进行调用。selenium中常用的函数:元素定位、输入、点击、访问URL、等待、关闭等。代码如下:
- '''
- 基类:提供各个常用的已封装好的函数,便于后续的页面对象类进行调用。
- selenium中常用的函数:元素定位、输入、点击、访问URL、等待、关闭
- '''
- from time import sleep
- from selenium import webdriver
-
- class BasePage:
-
- driver = webdriver.Chrome()
-
- # 访问URL
- def visit(self, url):
- self.driver.get(url)
-
- # 元素定位
- def locator(self, loc):
- return self.driver.find_element(*loc)
-
- # 输入
- def input(self, loc, txt):
- self.locator(loc).send_keys(txt)
-
- # 点击
- def click(self, loc):
- self.locator(loc).click()
-
- # 等待
- def wait(self, time):
- sleep(time)
-
- # 关闭
- def close(self):
- self.driver.quit()
SearchPage类继承BasePage类,调用基础类中的方法实现页面操作,生成对应的页面对象。代码如下:- '''
- 百度查询页面,搜索功能
- '''
- from selenium.webdriver.common.by import By
- from base.base_page import BasePage
- from selenium import webdriver
-
- class SearchPage(BasePage):
-
- url = 'http://www.baidu.com'
-
- # 定位百度输入框
- search_input = (By.NAME, 'wd')
- # 定位百度一下按钮
- search_button = (By.ID, 'su')
-
- # 封装实现业务流程的函数
- def search(self, txt):
- self.visit(self.url)
- self.wait(2)
- self.input(self.search_input, txt)
- self.wait(2)
- self.click(self.search_button)
- '''
- 测试类
- '''
- import unittest
- from page_object.search_page import SearchPage
- from selenium import webdriver
-
- class Case(unittest.TestCase):
-
- def test_search1(self):
- driver = webdriver.Chrome()
- txt = 'selenium'
- SearchPage(driver).search(txt)
-
- def test_search2(self):
- driver = webdriver.Chrome()
- txt = 'python'
- SearchPage(driver).search(txt)
-
- if __name__ == '__main__':
- unittest.main()
运行以上代码发现,因为创建了两次webdriver,所以每运行一次代码都会打开一个Chrome浏览器,同时,代码中也存在冗余。优化方案:可以增加@classmethod作为前置条件和后置条件,搜索的条件也可以采用数据驱动的方式完成,提高代码的可读性与维护性。
在data包下新建一个searchTXT.yaml文件,存放搜索的内容如下:

优化之后代码如下:
- '''
- 测试类
- '''
- import unittest
- from page_object.search_page import SearchPage
- from selenium import webdriver
- import ddt
-
- @ddt.ddt()
- class Case(unittest.TestCase):
-
- @classmethod
- def setUpClass(cls) -> None:
- cls.driver = webdriver.Chrome()
- cls.se = SearchPage(cls.driver)
-
- @classmethod
- def tearDownClass(cls) -> None:
- cls.driver.quit()
-
- @ddt.file_data('../data/searchTXT.yaml')
- def test_search(self, txt):
- self.se.search(txt)
-
- if __name__ == '__main__':
- unittest.main()
运行以上代码,发现测试用例执行了四次,分别搜索了selenium、python、java、php,如此实现了数据驱动,同时也在一个浏览器中完成了操作。
以上简单的实现了POM的设计模式,完成了基类、页面对象层、数据层、测试层的代码编写,若读者有兴趣,可以完成报告层、日志层等内容的编写,最终实现完整的框架。
最后:下面是配套学习资料,对于做【软件测试】的朋友来说应该是最全面最完整的备战仓库,这个仓库也陪伴我走过了最艰难的路程,希望也能帮助到你!【100%无套路免费领取】

被百万人刷爆的软件测试题库!!!谁用谁知道!!!全网最全面试刷题小程序,手机就可以刷题,地铁上公交上,卷起来!
涵盖以下这些面试题板块:
1、软件测试基础理论 ,2、web,app,接口功能测试 ,3、网络 ,4、数据库 ,5、linux
6、web,app,接口自动化 ,7、性能测试 ,8、编程基础,9、hr面试题 ,10、开放性测试题,11、安全测试,12、计算机基础

