web自动化测试-搭建python+selenium框架项目实战+源代码(免费)

Python 中搭建一个完整的 Selenium +unitest框架需要考虑多个方面,包括浏览器驱动管理、页面元素定位、测试用例组织、日志记录和报告生成等。以下是一个结构化的实现方案:

1. 项目结构设计

推荐采用分层架构,将不同功能分离:

dsr_selenium/
├── config/                 # 配置文件
│   ├── config.ini          # 全局配置
│   └── browser.yaml        # 浏览器配置
├── drivers/                # 浏览器驱动(可通过WebDriverManager自动管理)
├── pages/                  # 页面对象模型
│   ├── base_page.py        # 基础页面对象
│   ├── login_page.py       # 登录页面对象
│   └── home_page.py        # 主页对象
├── tests/                  # 测试用例
│   ├── test_base.py        # 测试基类
│   ├── test_login.py       # 登录测试
│   └── test_search.py      # 搜索测试
├── utils/                  # 工具类
│   ├── logger.py           # 日志工具
│   ├── driver_factory.py   # 驱动工厂
│   └── excel_reader.py     # 数据读取工具
├── reports/                # 测试报告
├── screenshots/            # 截图目录
├── requirements.txt        # 依赖包
└── run_tests.py            # 测试执行入口

2. 核心组件实现

2.1 配置管理(config/config.ini)
#设置测试链接base_url
[environment]
base_url = https://example.com
timeout = 10

#设置测试浏览器chrome
[browser]
browser_name = chrome
headless = false
window_size = 1920x1080
2.2 浏览器驱动管理(utils/driver_factory.py)
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager
from webdriver_manager.firefox import GeckoDriverManager


#浏览器渠道管理(工厂模式),这里是适配谷歌浏览器、火狐浏览器,
class DriverFactory:
    @staticmethod
    def create_driver(browser_name, headless=False, window_size=None):
        if browser_name.lower() == "chrome":
            #这里我设置直接使用我之前用的镜像,如果使用镜像管理会慢很多,如果本身下载了镜像建议使用我这种写法
            driver = webdriver.Chrome()
            driver.maximize_window()
            driver.implicitly_wait(30)
            return driver

            #使用driver服务管理,自动适配镜像,但是这种会很慢,容易报错,不建议使用这个写法
            # options = webdriver.ChromeOptions()
            # if headless:
            #     options.add_argument("--headless")
            # if window_size:
            #     options.add_argument(f"--window-size={window_size}")
            # service = Service(ChromeDriverManager().install())
            # return webdriver.Chrome(service=service, options=options)

        elif browser_name.lower() == "firefox":
            options = webdriver.FirefoxOptions()
            if headless:
                options.add_argument("--headless")
            service = Service(GeckoDriverManager().install())
            return webdriver.Firefox(service=service, options=options)

        else:
            raise ValueError(f"Unsupported browser: {browser_name}")
2.3 页面对象模型(pages/base_page.py)
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC


# pages/base_page.py,页面对象模型基础类,属于父类,这里设置页面操作组件,后面子类可以直接继承使用
class BasePage:
    def __init__(self, driver, timeout=10):
        self.driver = driver
        self.timeout = timeout

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

    def click(self, by):
        element = WebDriverWait(self.driver, self.timeout).until(
            EC.element_to_be_clickable((by))
        )
        element.click()

    def send_keys(self, by, text):
        element = self.find_element(by)
        element.clear()
        element.send_keys(text)

    def get_title(self):
        return self.driver.title


2.4页面对象实例(pages/login_page.py)

from pages.base_page import BasePage
from selenium.webdriver.common.by import By


# pages/login_page.py,页面对象模型,子类,继承base_page,存放具体的页面属性
class LoginPage(BasePage):
    USERNAME_INPUT = (By.ID, "username")
    PASSWORD_INPUT = (By.ID, "password")
    LOGIN_BUTTON = (By.ID, "login-button")

    def login(self, username, password):
        self.send_keys(self.USERNAME_INPUT, username)
        self.send_keys(self.PASSWORD_INPUT, password)
        self.click(self.LOGIN_BUTTON)
2.5测试基类(tests/test_base.py)
#测试用例基本类,读取config.ini配置,设置浏览器驱动,测试链接
import time
import unittest
from utils.driver_factory import DriverFactory
from configparser import ConfigParser


#设置浏览器配置,setUpClass()方法初始化测试环境,这里设置浏览器对象属性(也可以连接数据库),在测试所有用例之前执行,只执行一次
class TestBase(unittest.TestCase):
    @classmethod
    def setUpClass(cls):
        config = ConfigParser()
        config.read("config/config.ini")

        cls.browser = config.get("browser", "browser_name")
        cls.headless = config.getboolean("browser", "headless")
        cls.window_size = config.get("browser", "window_size")
        cls.base_url = config.get("environment", "base_url")
        cls.timeout = config.getint("environment", "timeout")

        cls.driver = DriverFactory.create_driver(
            cls.browser, cls.headless, cls.window_size
        )
        cls.driver.maximize_window()
        cls.driver.implicitly_wait(cls.timeout)

    #setUp()方法为单个测试用例准备环境,这里设置driver浏览器对象,在setUpClass()后面执行
    def setUp(self):
        self.driver.get(self.base_url)

    #tearDownClass()方法清理共享环境,这里清除driver浏览器对象,即关闭浏览器(也可以设置关闭连接数据库)
    @classmethod
    def tearDownClass(cls):
        if cls.driver:
            cls.driver.quit()
2.6 测试用例(tests/test_login.py)
from selenium.webdriver.common.by import By

from tests.test_base import TestBase
from pages.login_page import LoginPage


#创建测试用例实例类,存放具体的用例,包括正向、反向
class TestLogin(TestBase):
    #创建登录成功用例方法
    def test_successful_login(self):
        login_page = LoginPage(self.driver)
        login_page.login("valid_username", "valid_password")

        # 验证登录成功后的页面元素
        welcome_text = self.driver.find_element(By.CSS_SELECTOR, ".welcome-message").text
        self.assertEqual(welcome_text, "Welcome, User!")

    #创建登录失败用例方法
    def test_failed_login(self):
        login_page = LoginPage(self.driver)
        login_page.login("invalid_username", "invalid_password")

        #验证登录失败提示是否正常
        error_message = self.driver.find_element(By.CSS_SELECTOR, ".error-message").text
        self.assertEqual(error_message, "Invalid credentials")
2.7 日志记录(utils/logger.py)
import logging
import os


#报错打印报错内容,report/report报告显示这个报错内容
def setup_logger(name, log_file, level=logging.INFO):
    os.makedirs(os.path.dirname(log_file), exist_ok=True)

    formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s')

    file_handler = logging.FileHandler(log_file)
    file_handler.setFormatter(formatter)

    stream_handler = logging.StreamHandler()
    stream_handler.setFormatter(formatter)

    logger = logging.getLogger(name)
    logger.setLevel(level)
    logger.addHandler(file_handler)
    logger.addHandler(stream_handler)

    return logger


# 使用示例
logger = setup_logger("selenium_logger", "logs/selenium.log")

3. 测试执行与报告

3.1 使用 Unittest 执行测试(run_tests.py)
import unittest
from unittest import TestLoader, TestSuite
from HtmlTestRunner import HTMLTestRunner
import os


# 创建报告目录
os.makedirs("reports", exist_ok=True)

print("创建测试报告目录")
# 加载测试用例
loader = TestLoader()
suite = TestSuite()
print("加载测试用例成功")
# 添加测试模块,将模块加入测试用例队列中,然后按照排序执行
suite.addTests(loader.loadTestsFromName("tests.test_login"))
# suite.addTests(loader.loadTestsFromName("tests.test_search"))
print('添加测试模板成功')
# 运行测试并生成HTML报告
with open("reports/test_report.html", "w") as f:
    runner = HTMLTestRunner(
        stream=f,
        report_title="Selenium Test Report",
        descriptions=True,
        verbosity=2
    )
    runner.run(suite)
print('测试报告已生成,请到reports/test_report.html目录查看')
3.2 依赖安装(requirements.txt)
selenium==4.0.0
webdriver-manager==4.0.0
html-testRunner==1.3.0
configparser==5.3.0
PyYAML==6.0

注意selenium必须是安装4.0.0以上的版本,可以自己更新,如pip install selenium==4.0.0

4. 扩展功能

4.1 数据驱动测试

使用parameterized库实现多组测试数据:

from parameterized import parameterized

class TestLogin(TestBase):
    @parameterized.expand([
        ("valid_user", "user1", "pass1", True),
        ("invalid_user", "user2", "wrong", False),
    ])
    def test_login(self, name, username, password, expected):
        login_page = LoginPage(self.driver)
        login_page.login(username, password)
        
        # 验证结果
        self.assertEqual(self.is_logged_in(), expected)
4.2 异常处理与截图

在基类中添加异常处理和截图功能:

def tearDown(self):
    if self._outcome.errors[1][1]:  # 如果测试失败
        test_name = self._testMethodName
        self.driver.save_screenshot(f"screenshots/{test_name}.png")

5. 运行测试

  1. 安装依赖:

    pip install -r requirements.txt
    
    #如果文件类型安装依赖失败,可以逐个进行安装如
    
    pip install selenium==4.0.0
    pip install webdriver-manager==4.0.0
    pip install thml-testRunner==1.2.1
    pip install configparser==5.3.0
    pip install PyYAML==6.0
  2. 执行测试:

    python run_tests.py
    
  3. 查看报告:
    打开reports/test_report.html查看测试结果。如下图,如果显示这样的测试报告证明已经搭建成功,可以进行业务编写。web自动化测试-搭建python+selenium框架项目实战+源代码(免费)_第1张图片
  4. web自动化测试-搭建python+selenium框架项目实战+源代码(免费)_第2张图片

6. 项目源代码:https://download.csdn.net/download/m0_55341944/90849921

(非VIP用户,评论后领取免费源代码)

总结

这个框架包含了 Selenium 自动化的核心组件:

  • 页面对象模型:分离测试逻辑和页面元素定位。
  • 配置管理:集中管理环境参数。
  • 浏览器驱动自动管理:无需手动下载和配置驱动。
  • 日志记录:记录测试执行过程。
  • 测试报告:生成可视化的 HTML 报告。
  • 异常处理:自动截图和错误记录。

根据项目需求,你还可以进一步扩展,如集成 Allure 报告、添加 API 测试模块、实现分布式测试等。

备注

安装依赖时可能会多次失败,可能时网络问题可以失败可以重复安装,如果多次失败可以更改安装的版本,如遇到具体的安装错误可以网上查询解决方案。

你可能感兴趣的:(UI自动化测试,python学习,python,selenium,开发语言)