

Selenium4+Python3系列(十) - Page Object设计模式 - 久曲健
source link: https://www.cnblogs.com/longronglang/p/16930414.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Page Object(PO)
模式,是Selenium
实战中最为流行,并且被自动化测试同学所熟悉和推崇的一种设计模式之一。在设计测试时,把页面元素定位和元素操作方法按照页面抽象出来,分离成一定的对象,然后再进行组织。
相信每个做自动化测试的同学,一定会遇到这样一个非常头疼的问题,那就是页面变化,如果没有使用Page Object
设计模式,这就意味着以前的定位元素方法不能用了,需要重新修改元素定位方式。你需要一个一个从测试脚本中把需要修改的元素定位方式找出来,然后再进行修改。这势必会使脚本维护的成本变高,显然这样的自动化脚本就不会有人愿意使用。
那这时我们使用Page Object
模式就可以解决这个问题了。
PageObject 的优点
- 减少代码冗余
- 业务和实现分离
- 降低代码维护成本
Page Object模式
Page Object 见名知意,就是页面对象,并将页面元素定位方法和元素操作进行分离。
在实际自动化测试实战过程中,我们一般对脚本的实现分为三层:
- 对象层:用于存放页面元素定位和控件操作。
- 逻辑层:则是一些封装好的功能用例模块。
- 业务层:则是我们真正的测试用例的操作部分。
使用 Page Object 类来分离页面元素
首先我们新建一个类login_page
,登录页面内编写需要操作的元素定位方式和控件操作,具体代码示例如下:
# -*- coding: utf-8 -*- """ # @Time : 2022/11/26 22:16 # @Author : longrong.lang # @FileName: login_page.py # @Software: PyCharm # @Blog :https://www.cnblogs.com/longronglang/ # @Motto:ABC(Always Be Coding) """ import time from selenium.webdriver.common.by import By class LoginPage: """ 封装元素定位及控件 """ def __int__(self, driver): self.driver = driver # 打开浏览器 def open(self, url): self.driver.get(url) # 用户名元素定位 def user_name(self): return self.driver.find_element(By.CSS_SELECTOR, "input[type='text']") # 密码元素定位 def pass_word(self): return self.driver.find_element(By.CSS_SELECTOR, "input[type='password']") # 登录元素定位 def login_btn(self): return self.driver.find_element(By.CSS_SELECTOR, "button[name='submit']") # 错误提示 def error_msg(self): return self.driver.find_element(By.ID, "alert") # 输入用户名 def send_username(self, username): self.user_name().clear() self.user_name().send_keys(username) # 输入密码 def send_password(self, password): self.pass_word().clear() self.pass_word().send_keys(password) # 点击登录 def click_login(self): self.login_btn().click() # 获取错误提示 def get_errorMsg(self): time.sleep(1) return self.error_msg().text # 退出浏览器 def quit(self): self.driver.quit()
这里我只对用户名和密码输入框进行了封装,有兴趣的同学也可以接着进行全部元素操作封装。
我们再新建一个类login_action
,用于登录逻辑的封装,供业务层调用,具体代码示例如下:
# -*- coding: utf-8 -*- """ # @Time : 2022/11/26 22:33 # @Author : longrong.lang # @FileName: login_action.py # @Software: PyCharm # @Blog :https://www.cnblogs.com/longronglang/ # @Motto:ABC(Always Be Coding) """ import time from pageobject.login_page import LoginPage class LoginAction(LoginPage): def login(self, username, password, expected): self.open("http://localhost:8080/login") self.send_username(username) self.send_password(password) self.click_login() time.sleep(1) msg = self.get_errorMsg() assert msg == expected self.quit()
最后我们新建一个类test_login
,用于业务层的封装,具体代码示例如下:
# -*- coding: utf-8 -*- """ # @Time : 2022/11/26 22:43 # @Author : longrong.lang # @FileName: test_login.py # @Software: PyCharm # @Blog :https://www.cnblogs.com/longronglang/ # @Motto:ABC(Always Be Coding) """ from pageobject.login_action import LoginAction from selenium import webdriver from webdriver_manager.chrome import ChromeDriverManager class TestLogin(LoginAction): def test_login(self): self.driver = webdriver.Chrome(ChromeDriverManager().install()) self.driver.maximize_window() self.driver.implicitly_wait(5) self.login("username", "pwd", "登录失败!")
虽然该实现方法看上去复杂多了,但其中的设计好处是不同层关心不同的问题。页面对象只关心元素的定位,测试用例只关心测试数据。
login_page
类中主要对登录页面上元素进行封装,使其成为具体的操作方法。如对用户名、密码框都封装成方法,然后定义login(self, username, password, expected)
方法将单个元素操作组成一个完整的动作,包含输入用户名、密码并点击登录按钮等。
使用时将driver、username、pwd、expected
作为函数的入参,这样的方法具有很强的可重用性。
最后使用test_login()
方法进行用户操作行为,现在只关心用哪个浏览器、登录的用户名和密码是什么,至少输入框、按钮是如何定位的,则不关心。即实现了不同层关心不同问题。如果再有定位元素变化,只需login_page
这个类维护即可,显然方便了很多。
__EOF__
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK