POM 模式自动化测试

POM 模式自动化测试

一、Page Object Model(POM)登陆案例

1. POM 概述

Page Object Model(页面对象模型)是一种设计模式,将页面元素和操作封装成对象,使测试代码和页面元素的定位及操作分离,提高了测试代码的可维护性和可复用性。在典型的 POM 实现中,通常包含四层对象:基础页面对象、具体页面对象、测试用例对象和测试数据对象。

2. 登陆案例实现

2.1 目录结构
project/
│
├── pages/              # 页面对象模块
│   ├── base_page.py    # 基础页面对象
│   ├── login_page.py   # 登录页面对象
│
├── tests/              # 测试用例模块
│   ├── test_login.py   # 登录测试用例
│
├── utils/              # 工具模块
│   ├── data_utils.py   # 测试数据对象
│
├── config/             # 配置模块
│   ├── config.ini      # 配置文件
│
├── run_tests.py        # 测试运行文件
2.2 基础页面对象(pages/base_page.py
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

class BasePage:
    def __init__(self, driver):
        self.driver = driver

    def find_element(self, by, value, timeout=10):
        return WebDriverWait(self.driver, timeout).until(
            EC.presence_of_element_located((by, value))
        )

    def click(self, by, value):
        element = self.find_element(by, value)
        element.click()

    def send_keys(self, by, value, text):
        element = self.find_element(by, value)
        element.send_keys(text)
2.3 具体页面对象(pages/login_page.py
from pages.base_page import BasePage
from selenium.webdriver.common.by import By

class LoginPage(BasePage):
    USERNAME_INPUT = (By.ID, 'username')
    PASSWORD_INPUT = (By.ID, 'password')
    LOGIN_BUTTON = (By.ID, 'login-button')

    def __init__(self, driver):
        super().__init__(driver)

    def enter_username(self, username):
        self.send_keys(*self.USERNAME_INPUT, username)

    def enter_password(self, password):
        self.send_keys(*self.PASSWORD_INPUT, password)

    def click_login_button(self):
        self.click(*self.LOGIN_BUTTON)

    def login(self, username, password):
        self.enter_username(username)
        self.enter_password(password)
        self.click_login_button()
2.4 测试用例对象(tests/test_login.py
import unittest
from selenium import webdriver
from pages.login_page import LoginPage
from utils.data_utils import get_test_data

class TestLogin(unittest.TestCase):
    def setUp(self):
        self.driver = webdriver.Chrome()
        self.driver.get('https://example.com/login')
        self.login_page = LoginPage(self.driver)

    def test_successful_login(self):
        username, password = get_test_data()
        self.login_page.login(username, password)
        # 这里可以添加断言来验证登录是否成功
        # 例如:self.assertEqual(self.driver.current_url, 'https://example.com/dashboard')

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

if __name__ == '__main__':
    unittest.main()
2.5 测试数据对象(utils/data_utils.py
def get_test_data():
    # 这里可以从配置文件、数据库等获取测试数据
    username = 'testuser'
    password = 'testpassword'
    return username, password
2.6 测试运行文件(run_tests.py
import unittest

if __name__ == "__main__":
    suite = unittest.TestLoader().loadTestsFromTestCase(TestLogin)
    unittest.TextTestRunner(verbosity=2).run(suite)

3. 代码解释

  • 基础页面对象(BasePage:封装了一些通用的操作方法,如查找元素、点击元素和输入文本等,为具体页面对象提供了基础功能。
  • 具体页面对象(LoginPage:继承自 BasePage,定义了登录页面的元素定位器和操作方法,将登录页面的元素和操作封装在一起。
  • 测试用例对象(TestLogin:使用 unittest 框架编写测试用例,创建 LoginPage 对象并调用其方法进行登录操作,最后添加断言来验证登录结果。
  • 测试数据对象(get_test_data:负责提供测试所需的数据,这里简单地返回了一个用户名和密码,实际应用中可以从配置文件、数据库等获取数据。

通过这种四层对象的设计,测试代码和页面元素的定位及操作分离,提高了代码的可维护性和可复用性。当页面元素发生变化时,只需要修改具体页面对象中的元素定位器和操作方法,而不需要修改测试用例代码。

二、基于策略模式的数据获取在自动化测试中的应用

1. 策略模式概述

策略模式是一种行为设计模式,它定义了一系列的算法,并将每个算法封装起来,使它们可以相互替换。策略模式让算法的变化独立于使用算法的客户端。在自动化测试的数据获取场景中,我们可以使用策略模式来根据不同的数据源类型(数据库、CSV 文件、Excel 文件)获取测试数据。

2. 代码实现

2.1 项目目录结构
data_fetching_strategy/
│
├── data_fetch_strategy.py  # 策略接口和具体策略类
├── data_fetcher.py         # 上下文类
├── db_config.py            # 数据库配置文件
├── main.py                 # 主程序
├── sample.csv              # 示例 CSV 文件
├── sample.xlsx             # 示例 Excel 文件
2.2 数据库配置文件(db_config.py
# 假设使用 SQLite 数据库
DB_CONFIG = {
    'database': 'example.db'
}
2.3 策略接口和具体策略类(data_fetch_strategy.py
import sqlite3
import csv
import pandas as pd

# 策略接口
class DataFetchStrategy:
    def fetch_data(self):
        pass

# 从数据库获取数据的策略类
class DatabaseFetchStrategy(DataFetchStrategy):
    def __init__(self, db_config):
        self.db_config = db_config

    def fetch_data(self):
        conn = sqlite3.connect(self.db_config['database'])
        cursor = conn.cursor()
        cursor.execute('SELECT * FROM your_table')
        data = cursor.fetchall()
        conn.close()
        return data

# 从 CSV 文件获取数据的策略类
class CSVFetchStrategy(DataFetchStrategy):
    def __init__(self, file_path):
        self.file_path = file_path

    def fetch_data(self):
        data = []
        with open(self.file_path, 'r', newline='') as csvfile:
            reader = csv.reader(csvfile)
            for row in reader:
                data.append(row)
        return data

# 从 Excel 文件获取数据的策略类
class ExcelFetchStrategy(DataFetchStrategy):
    def __init__(self, file_path):
        self.file_path = file_path

    def fetch_data(self):
        df = pd.read_excel(self.file_path)
        return df.values.tolist()
2.4 上下文类(data_fetcher.py
from data_fetch_strategy import DataFetchStrategy, DatabaseFetchStrategy, CSVFetchStrategy, ExcelFetchStrategy
from db_config import DB_CONFIG

class DataFetcher:
    def __init__(self, source_type):
        self.source_type = source_type
        self.strategy = self._get_strategy()

    def _get_strategy(self):
        if self.source_type == 'DB':
            return DatabaseFetchStrategy(DB_CONFIG)
        elif self.source_type == 'CSV':
            return CSVFetchStrategy('sample.csv')
        elif self.source_type == 'Excel':
            return ExcelFetchStrategy('sample.xlsx')
        else:
            raise ValueError(f"Unsupported source type: {self.source_type}")

    def fetch_data(self):
        return self.strategy.fetch_data()
2.5 主程序(main.py
from data_fetcher import DataFetcher

def main():
    # 从数据库获取数据
    db_fetcher = DataFetcher('DB')
    db_data = db_fetcher.fetch_data()
    print("从数据库获取的数据:")
    for row in db_data:
        print(row)

    # 从 CSV 文件获取数据
    csv_fetcher = DataFetcher('CSV')
    csv_data = csv_fetcher.fetch_data()
    print("\n从 CSV 文件获取的数据:")
    for row in csv_data:
        print(row)

    # 从 Excel 文件获取数据
    excel_fetcher = DataFetcher('Excel')
    excel_data = excel_fetcher.fetch_data()
    print("\n从 Excel 文件获取的数据:")
    for row in excel_data:
        print(row)

if __name__ == "__main__":
    main()

3. 代码解释

3.1 策略接口(DataFetchStrategy

定义了一个抽象方法 fetch_data,所有具体的策略类都需要实现这个方法,用于获取数据。

3.2 具体策略类
  • DatabaseFetchStrategy:实现了从数据库中获取数据的逻辑。使用 sqlite3 连接到数据库,执行 SQL 查询语句获取数据,并在操作完成后关闭数据库连接。
  • CSVFetchStrategy:实现了从 CSV 文件中获取数据的逻辑。使用 Python 的内置 csv 模块读取 CSV 文件内容,并将每行数据添加到列表中返回。
  • ExcelFetchStrategy:实现了从 Excel 文件中获取数据的逻辑。使用 pandas 库读取 Excel 文件,将数据转换为列表形式返回。
3.3 上下文类(DataFetcher
  • 在初始化时,根据传入的 source_type 参数选择相应的策略类。
  • _get_strategy 方法根据 source_type 决定返回哪种具体的策略对象。
  • fetch_data 方法调用当前策略对象的 fetch_data 方法来获取数据。
3.4 主程序(main.py

创建不同 source_typeDataFetcher 对象,调用其 fetch_data 方法获取数据并打印输出。

4. 注意事项

  • 示例中使用的是 SQLite 数据库,实际应用中可以根据需要更换为其他数据库,如 MySQL、PostgreSQL 等,同时需要修改 db_config.pyDatabaseFetchStrategy 类中的数据库连接和操作代码。
  • 请确保已经安装了 pandas 库,可以使用 pip install pandas 进行安装。
  • 示例中的 your_table 需要替换为实际的数据库表名,sample.csvsample.xlsx 需要替换为实际的文件路径。

通过使用策略模式,我们可以方便地根据不同的数据源类型切换数据获取方式,提高了代码的可维护性和可扩展性。在自动化测试中,可将该数据获取策略与 POM 模式结合,为测试用例提供多样化的测试数据。例如,可在 utils/data_utils.pyget_test_data 方法中调用 DataFetcher 来根据配置选择合适的数据源获取测试数据,进一步增强测试的灵活性和可配置性。

你可能感兴趣的:(test,python)