基于Selenium中Page Object封装模式介绍及案例讲解

一、Page Object模式概述

Page Object模式是一种在自动化测试(尤其是针对Web应用程序的自动化测试)中广泛使用的设计模式。它的主要目的是将页面的元素定位和操作逻辑与测试用例进行分离,使得测试代码更加清晰、可维护和可复用。

在传统的自动化测试代码中,元素定位和对元素的操作通常直接混合在测试用例中。当页面结构发生变化时,比如元素的属性(如id、class等)改变或者元素的布局调整,就需要在多个测试用例中去逐一修改相关的元素定位和操作代码,这会导致代码的维护成本很高。

而Page Object模式通过将每个页面抽象成一个独立的类(即Page Object类),在这个类中封装了该页面所有相关元素的定位方法以及针对这些元素的操作方法。这样,当页面发生变化时,只需要在对应的Page Object类中修改相关代码即可,而不需要在众多的测试用例中去查找和修改,大大提高了代码的可维护性。

二、Page Object模式的优势

  • 提高代码可维护性:如前面所述,页面结构变化时,只需在Page Object类中修改相关代码,而不影响测试用例本身的逻辑。
  • 增强代码可读性:测试用例专注于业务逻辑的验证,通过调用Page Object类中的方法来操作页面元素,使得测试用例的代码更加清晰易懂,阅读测试用例就可以清楚地知道在进行什么业务操作,而不需要关注具体的元素定位细节。
  • 促进代码复用:不同的测试用例可能会涉及对同一个页面的操作,通过创建Page Object类,可以在多个测试用例中复用这些页面的操作方法,减少代码冗余。

三、代码示例

我以一个简单的Web登录页面为例,展示如何使用Page Object模式进行自动化测试(使用Selenium库进行Web自动化操作)。

Selenium环境安装:首先,需要安装Selenium库(如果还未安装):

pip install selenium
1. 导入必要的库
from selenium import webdriver
from selenium.webdriver.common.by import By
2. 创建登录页面的Page Object类
class LoginPage:
    def __init__(self, driver):
        self.driver = driver

    # 定位用户名输入框
    def locate_username_input(self):
        return self.driver.find_element(By.ID, "username")

    # 定位密码输入框
    def locate_password_input(self):
        return self.driver.find_element(By.ID, "password")

    # 定位登录按钮
    def locate_login_button(self):
        return self.driver.find_element(By.ID, "login-button")

    # 输入用户名
    def enter_username(self, username):
        username_input = self.locate_username_input()
        username_input.clear()
        username_input.send_keys(username)

    # 输入密码
    def enter_password(self, password):
        password_input = self.locate_password_input()
        password_input.clear()
        password_input.send_keys(password)

    # 点击登录按钮
    def click_login_button(self):
        login_button = self.locate_login_button()
        login_button.click()

在上述LoginPage类中:

  • __init__方法接受一个浏览器驱动实例(如Chrome驱动实例),并将其保存为类的属性,以便在后续方法中使用该驱动来定位和操作页面元素。
  • 其他方法分别用于定位登录页面上的各个关键元素(用户名输入框、密码输入框、登录按钮)以及对这些元素进行相应的操作(输入用户名、输入密码、点击登录按钮)。
3. 创建测试用例
class TestLogin:
    def setUp(self):
        self.driver = webdriver.Chrome()
        self.driver.get("http://example.com/login")
        self.login_page = LoginPage(self.driver)

    def tearDown(self):
        self.driver.quit()

    def test_successful_login(self):
        self.login_page.enter_username("test_user")
        self.login_page.enter_password("test_password")
        self.login_page.click_login_button()

        # 这里可以添加更多的断言来验证登录是否成功,比如检查是否跳转到了预期页面等

在上述TestLogin类中:

  • setUp方法在每个测试方法执行之前被调用,它主要负责创建浏览器驱动实例,打开登录页面,并实例化LoginPage类,以便在后续测试方法中可以使用LoginPage类中的方法来操作登录页面。
  • tearDown方法在每个测试方法执行之后被调用,它负责关闭浏览器驱动实例。
  • test_successful_login是一个具体的测试方法,它通过调用LoginPage类中的方法来完成输入用户名、输入密码和点击登录按钮的操作,之后还可以根据需要添加断言来验证登录是否成功(例如,检查是否跳转到了预期的页面等)。

通过这样的方式,将登录页面的元素定位和操作封装在LoginPage类中,而测试用例则专注于业务逻辑的验证,当登录页面的结构发生变化时,只需要在LoginPage类中修改相关元素定位和操作的代码即可,不会影响到测试用例的逻辑。这就是Page Object模式在Python自动化测试中的基本应用方式。

Page Object模式实际代码示例

示例一:电商登录与商品搜索页面

1. 导入所需库
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import time
2. 定义电商登录页面的Page Object类
class LoginPage:
    def __init__(self, driver):
        self.driver = driver

    def locate_username_input(self):
        return self.driver.find_element(By.ID, "username")

    def locate_password_input(self):
        return self.driver.find_element(By.ID, "password")

    def locate_login_button(self):
        return self.driver.find_element(By.ID, "login-button")

    def enter_username(self, username):
        username_input = self.locate_username_input()
        username_input.clear()
        username_input.send_keys(username)

    def enter_password(self, password):
        password_input = self.locate_password_input()
        password_input.clear()
        password_input.send_keys(password)

    def click_login_button(self):
        login_button = self.locate_login_button()
        login_button.click()
3. 定义电商商品搜索页面的Page Object类
class SearchPage:
    def __init__(self, driver):
        self.driver = driver

    def locate_search_box(self):
        return self.driver.find_element(By.ID, "search-box")

    def enter_search_term(self, term):
        search_box = self.locate_search_box()
        search_box.clear()
        search_box.send_keys(term)

    def click_search_button(self):
        search_button = self.driver.find_element(By.ID, "search-button")
        search_button.click()

    def get_search_results(self):
        wait = WebDriverWait(self.driver, 10)
        results = wait.until(EC.presenceOfAllElementsLocatedBy(By.CLASS_NAME, "product-item"))
        return results
4. 定义测试用例类
class TestEcommerce:
    def setUp(self):
        self.driver = webdriver.Chrome()
        self.driver.get("https://www.example-ecommerce.com")

    def tearDown(self):
        self.driver.quit()

    def test_login_and_search(self):
        login_page = LoginPage(self.driver)
        search_page = SearchPage(self.driver)

        login_page.enter_username("test_user")
        login_page.enter_password("test_password")
        login_page.click_login_button()

        time.sleep(2)  # 等待登录完成,可根据实际情况调整

        search_page.enter_search_term("laptop")
        search_page.click_search_button()

        results = search_page.get_search_results()
        assert len(results) > 0, "No search results found."

示例二:社交媒体登录与发布动态页面

1. 导入所需库
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
2. 定义社交媒体登录页面的Page Object类
class SocialMediaLoginPage:
    def __init__(self, driver):
        self.driver = driver

    def locate_email_input(self):
        return self.driver.find_element(By.ID, "email")

    def locate_password_input(self):
        return self.driver.find_element(By.ID, "password")

    def locate_login_button(self):
        return self.driver.find_element(By.ID, "login-button")

    def enter_email(self, email):
        email_input = self.locate_email_input()
        email_input.clear()
        email_input.send_keys(email)

    def enter_password(self, password):
        password_input = self.locate_password_input()
        password_input.clear()
        password_input.send_keys(password)

    def click_login_button(self):
        login_button = self.locate_login_button()
        login_button.click()
3. 定义社交媒体发布动态页面的Page Object类
class SocialMediaPostPage:
    def __init__(self, driver):
        self.driver = driver

    def locate_post_textarea(self):
        return self.driver.find_element(By.ID, "post-textarea")

    def enter_post_content(self, content):
        post_textarea = self.locate_post_textarea()
        post_textarea.clear()
        post_textarea.send_keys(content)

    def click_post_button(self):
        post_button = self.driver.find_element(By.ID, "post-button")
        post_button.click()

    def get_post_status(self):
        wait = WebDriverWait(self.driver, 10)
        status = wait.until(EC.visibilityOfElementLocated(By.ID, "post-status"))
        return status.text
4. 定义测试用例类
class TestSocialMedia:
    def setUp(self):
        self.driver = webdriver.Chrome()
        self.driver.get("https://www.example-socialmedia.com")

    def tearDown(self):
        self.driver.quit()

    def test_login_and_post(self):
        login_page = SocialMediaLoginPage(self.driver)
        post_page = SocialMediaPostPage(self.driver)

        login_page.enter_email("test_email@example.com")
        login_page.enter_password("test_password")
        login_page.click_login_button()

        post_page.enter_post_content("This is a test post.")
        post_page.click_post_button()

        status = post_page.get_post_status()
        assert "Posted successfully" in status, "Post was not successful."

示例三:在线旅游预订平台登录与酒店预订页面

1. 导入所需库
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
2. 定义在线旅游预订平台登录页面的Page Object类
class TravelBookingLoginPage:
    def __init__(self, driver):
        self.driver = driver

    def locate_username_input(self):
        return self.driver.find_element(By.ID, "username")

    def locate_password_input(self):
        return self.driver.find_element(By.ID, "password")

    def locate_login_button(self):
        return self.driver.find_element(By.ID, "login-button")

    def enter_username(self, username):
        username_input = self.locate_username_input()
        username_input.clear()
        username_input.send_keys(username)

    def enter_password(self, password):
        password_input = self.locus_password_input()
        password_input.clear()
        password_input.send_keys(password)

    def click_login_button(self):
        login_button = self.locate_login_button()
        login_button.click()
3. 定义在线旅游预订平台酒店预订页面的Page Object类
class TravelBookingHotelPage:
    def __init__(self, driver):
        self.driver = driver

    def locate_destination_input(self):
        return self.driver.find_element(By.ID, "destination")

    def enter_destination(self, destination):
        destination_input = self.locate_destination_input()
        destination_input.clear()
        destination_input.send_keys(destination)

    def locate_check_in_date_input(self):
        return self.driver.find_element(By.ID, "check-in-date")

    def enter_check_in_date(self, date):
        check_in_date_input = self.locate_check_in_date_input()
        check_in_date_input.clear()
        check_in_date_input.send_keys(date)

    def locate_check_out_date_input(self):
    return self.driver.find_element(By.ID, "check-out-date")

    def enter_check_out_date(self, date):
        check_out_date_input = self.locate_check_out_date_input()
        check_out_date_input.clear()
        check_out_date_input.send_keys(date)

    def locate_search_button(self):
        return self.driver.find_element(By.ID, "search-button")

    def click_search_button(self):
        search_button = self.locate_search_button()
        search_button.click()

    def get_hotel_results(self):
        wait = WebDriverWait(self.driver, 10)
        results = wait.until(EC.presenceOfAllElementsLocatedBy(By.CLASS_NAME, "hotel-item"))
        return results
4. 定义测试用例类
class TestTravelBooking:
    def setUp(self):
        self.driver = webdriver.Chrome()
        self.driver.get("https://www.example-travelbooking.com")

    def tearDown(self):
        self.driver.quit()

    def test_login_and_book_hotel():
        login_page = TravelBookingLoginPage(self.driver)
        hotel_page = TravelBookingHotelPage(self.driver)

        login_page.enter_username("test_user")
        login_page.enter_password("test_password")
        login_page.click_login_button()

        hotel_page.enter_destination("New York")
        hotel_page.enter_check_in_date("2024-12-01")
        hotel_page.enter_check_out_date("2024-12-05")
        hotel_page.click_search_button()

        results = hotel_page.get_hotel_results()
        assert len(results) > 0, "No hotel results found."

这些代码示例展示了如何在不同类型的Web应用场景下应用Page Object模式,通过将页面元素定位和操作封装在各自的Page Object类中,使得测试用例更加清晰、可维护和可复用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

旺仔Sec

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值