Python自动化测试实战:从零搭建企业级测试框架
一、测试框架技术选型
企业级测试框架核心组件:
- Pytest:测试执行与报告
- Selenium:Web UI自动化
- Requests:API测试库
- Allure:测试报告生成
- Jenkins:持续集成
二、框架架构设计
1. 项目目录结构
test_framework/
├── config/ # 配置文件
│ ├── settings.py # 全局配置
│ └── pytest.ini # Pytest配置
├── pages/ # 页面对象模型
│ ├── login_page.py
│ └── home_page.py
├── tests/ # 测试用例
│ ├── ui/ # UI测试
│ ├── api/ # API测试
│ └── unit/ # 单元测试
├── utils/ # 工具类
│ ├── driver.py # 浏览器驱动
│ └── report.py # 报告生成
├── conftest.py # Pytest插件
└── requirements.txt # 依赖文件
三、核心模块实现
1. 浏览器驱动封装
# utils/driver.py
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from config import settings
class Driver:
_instance = None
def __new__(cls):
if cls._instance is None:
cls._instance = super().__new__(cls)
cls._instance._init_driver()
return cls._instance
def _init_driver(self):
options = Options()
if settings.HEADLESS:
options.add_argument("--headless")
options.add_argument("--window-size=1920,1080")
self.driver = webdriver.Chrome(
executable_path=settings.CHROME_DRIVER_PATH,
options=options
)
self.driver.implicitly_wait(settings.IMPLICIT_WAIT)
@classmethod
def quit(cls):
if cls._instance and cls._instance.driver:
cls._instance.driver.quit()
cls._instance = None
2. 页面对象模型
# pages/login_page.py
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
class LoginPage:
def __init__(self, driver):
self.driver = driver
self.url = "https://example.com/login"
def open(self):
self.driver.get(self.url)
return self
def login(self, username, password):
username_field = WebDriverWait(self.driver, 10).until(
EC.presence_of_element_located((By.ID, "username"))
username_field.send_keys(username)
password_field = self.driver.find_element(By.ID, "password")
password_field.send_keys(password)
login_button = self.driver.find_element(By.XPATH, "//button[@type='submit']")
login_button.click()
return HomePage(self.driver)
四、测试用例开发
1. UI自动化测试
# tests/ui/test_login.py
import pytest
from pages.login_page import LoginPage
from utils.driver import Driver
@pytest.fixture(scope="function")
def setup():
driver = Driver()
yield driver
Driver.quit()
class TestLogin:
def test_successful_login(self, setup):
login_page = LoginPage(setup.driver).open()
home_page = login_page.login("admin", "password123")
assert "Dashboard" in home_page.get_title()
assert home_page.is_logout_button_displayed()
@pytest.mark.parametrize("username,password", [
("wrong", "password123"),
("admin", "wrong"),
("", "")
])
def test_failed_login(self, setup, username, password):
login_page = LoginPage(setup.driver).open()
login_page.login(username, password)
assert "Invalid credentials" in login_page.get_error_message()
2. API自动化测试
# tests/api/test_user_api.py
import requests
import pytest
BASE_URL = "https://api.example.com/v1"
class TestUserAPI:
def test_get_user(self):
response = requests.get(f"{BASE_URL}/users/1")
assert response.status_code == 200
assert response.json()["id"] == 1
assert "username" in response.json()
def test_create_user(self):
payload = {
"username": "testuser",
"email": "test@example.com"
}
response = requests.post(f"{BASE_URL}/users", json=payload)
assert response.status_code == 201
assert response.json()["username"] == "testuser"
assert "id" in response.json()
五、测试报告与持续集成
1. Allure测试报告
# 安装Allure
pip install allure-pytest
# 运行测试并生成报告
pytest --alluredir=./reports/allure_results
# 生成HTML报告
allure serve ./reports/allure_results
2. Jenkins持续集成
pipeline {
agent any
stages {
stage('Checkout') {
steps {
git 'https://github.com/your-repo/test-framework.git'
}
}
stage('Install Dependencies') {
steps {
sh 'pip install -r requirements.txt'
}
}
stage('Run Tests') {
steps {
sh 'pytest --alluredir=./reports/allure_results'
}
}
stage('Generate Report') {
steps {
allure includeProperties: false, jdk: '', results: [[path: 'reports/allure_results']]
}
}
}
}