跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客我的书AI学习GitHub 精选镜像AI 生图工具UI配色美学关于
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
Python

一个博客系统的 Python + Selenium 自动化测试记录

记录一次给博客系统编写 Python + Selenium 自动化测试的过程。覆盖登录、博客列表、博客详情三个核心模块,按正常与异常场景设计用例。代码通过工具类管理驱动和截图,各模块独立封装,最终串联执行并生成简单报告。强调先跑通再优化的思路,适合内部工具快速落地。

链路追踪发布于 2026/6/18更新于 2026/10/1568 浏览
一个博客系统的 Python + Selenium 自动化测试记录

前段时间给手头一个博客系统补了自动化测试,用 Python + Selenium。套路不复杂,但有几个点踩过坑之后觉得还是要记一下。

测试流程示意

测试范围

系统不大,核心就是登录、博客列表、博客详情这几个高频操作,所以没搞全覆盖。用例按'正常路径 + 一个典型异常'来设计,够用,也不至于写一堆一年跑不了两次的脚本。

脚本结构

项目结构大致这样:

  • common/Utils.py:初始化 ChromeDriver、截图
  • cases/BlogLogin.py:登录(成功 + 失败)
  • cases/BlogList.py:列表页检查与跳转
  • cases/BlogDetail.py:详情页元素验证
  • cases/RunCases.py:用例串联入口

通用工具

ChromeDriver 用 webdriver-manager 自动管理,省得手动下载。截图按日期分目录,文件名带用例名和时间戳,回看的时候容易定位。

import datetime
import os.path
import sys
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager


class Driver:
    driver = ""

    def __init__(self):
        options = webdriver.ChromeOptions()
        # options.page_load_strategy = 'eager'
        self.driver = webdriver.Chrome(
            service=Service(ChromeDriverManager().install()),
            options=options
        )

    def getScreenShot(self):
        dirname = datetime.datetime.now().strftime('%Y-%m-%d')
        if not os.path.exists("../images/" + dirname):
            os.mkdir("../images/" + dirname)
        filename = (
            sys._getframe().f_back.f_code.co_name
            + "-"
            + datetime.datetime.now().strftime('%Y-%m-%d-%H%M%S')
            + ".png"
        )
        self.driver.save_screenshot(f'../images/{dirname}/' + filename)


BlogDriver = Driver()

登录模块

两个用例:admin 正确密码登录成功,admin 错误密码登录失败并断言提示文案。元素定位用 CSS 选择器,直接又稳定。登录成功后通过头像元素确认登录态,失败则比对 body 文本。每步都截图,哪怕断言失败也能翻图看现场。

import time
from selenium.webdriver.common.by import By
from common.Utils import BlogDriver


class BlogLogin:
    def __init__(self):
        self.url = "http://192.168.47.135:8653/blog_system/blog_login.html"
        self.driver = BlogDriver.driver
        self.driver.get(self.url)

    def loginSucTest(self):
        time.sleep(2)
        self.driver.find_element(By.CSS_SELECTOR, "#username").clear()
        self.driver.find_element(By.CSS_SELECTOR, "#password").clear()
        self.driver.find_element(By.CSS_SELECTOR, "#username").send_keys("admin")
        self.driver.find_element(By.CSS_SELECTOR, "#password").send_keys("123")
        self.driver.find_element(By.CSS_SELECTOR, "#submit").click()
        # 登录后应有头像元素
        self.driver.find_element(
            By.CSS_SELECTOR, "body > div.container > div.left > div > img"
        )
        BlogDriver.getScreenShot()
        self.driver.back()

    def loginFailTest(self):
        self.driver.find_element(By.CSS_SELECTOR, "#username").clear()
        self.driver.find_element(By.CSS_SELECTOR, "#password").clear()
        self.driver.find_element(By.CSS_SELECTOR, "#username").send_keys("admin")
        self.driver.find_element(By.CSS_SELECTOR, "#password").send_keys("111")
        self.driver.find_element(By.CSS_SELECTOR, "#submit").click()
        expect = "用户名或密码错误!"
        actual = self.driver.find_element(By.CSS_SELECTOR, "body").text
        print(actual)
        BlogDriver.getScreenShot()
        assert expect == actual
        self.driver.back()

列表页

列表页测试需要先处于登录态,所以它得在登录用例之后执行。检查头像存在、第一篇文章链接可点击、文章数量大于 10(业务要求),然后点击第一篇文章,断言跳转到详情页。

from selenium.webdriver.common.by import By
from common.Utils import BlogDriver


class BlogList:
    def __init__(self):
        self.driver = BlogDriver.driver
        self.url = "http://192.168.47.135:8653/blog_system/blog_list.html"
        self.driver.get(self.url)

    def ListTest(self):
        self.driver.find_element(
            By.CSS_SELECTOR, "body > div.container > div.left > div > img"
        )
        self.driver.find_element(
            By.CSS_SELECTOR,
            "body > div.container > div.right > div:nth-child(1) > a",
        )
        articles = self.driver.find_elements(
            By.CSS_SELECTOR, "body > div.container > div.right > div"
        )
        assert len(articles) > 10
        self.driver.find_element(
            By.CSS_SELECTOR,
            "body > div.container > div.right > div:nth-child(1) > a",
        ).click()
        title = self.driver.title
        assert title == "博客详情页"
        BlogDriver.getScreenShot()

详情页

详情页测试做了点小兼容:如果当前不在列表页,就手动带 blogId=15 跳过去。然后简单验一下标题、日期、正文三个元素是否存在。

from selenium.webdriver.common.by import By
from common.Utils import BlogDriver


class BlogDetail:
    def __init__(self):
        self.url = "http://192.168.47.135:8653/blog_system/blog_detail.html?blogId=15"
        self.driver = BlogDriver.driver
        title = self.driver.title
        if not title == "博客列表页":
            self.driver.get(self.url)

    def DetailCheck(self):
        BlogDriver.getScreenShot()
        self.driver.find_element(
            By.CSS_SELECTOR, "body > div.container > div.right > div > h3"
        )
        self.driver.find_element(
            By.CSS_SELECTOR, "body > div.container > div.right > div > div.date"
        )
        self.driver.find_element(By.CSS_SELECTOR, "#content")

用例串联

入口脚本按登录 → 列表 → 详情的顺序跑,跑完关浏览器。注意导入路径,我这里实际目录是 cases,所以用的 from cases import ...。

from common.Utils import BlogDriver
from cases import BlogLogin
from cases import BlogList
from cases import BlogDetail

if __name__ == "__main__":
    BlogLogin.BlogLogin().loginSucTest()
    BlogList.BlogList().ListTest()
    BlogDetail.BlogDetail().DetailCheck()
    BlogDriver.driver.quit()

报告收尾

自动化跑完不看报告等于白跑。我一般会整理一个简单的测试报告,把截图、断言结果、执行时间列出来。下面这张是当时用的报告模板。

测试执行截图

报告模板

这版实现不花哨,但够直接——没有框架黑盒,每一步都看得见,出问题也好排查。后面要加用例或改成 pytest 组织也很自然。如果你也在给内部工具写 Selenium 测试,这种'先跑通,再优化'的节奏可能会省不少时间。

目录

  1. 测试范围
  2. 脚本结构
  3. 通用工具
  4. 登录模块
  5. 列表页
  6. 详情页
  7. 用例串联
  8. 报告收尾

更多推荐文章

查看全部
  • PyTorch CUDA v2.7 环境支持 Stable Diffusion 等多种模型架构
  • FPGA实现UART串口通信
  • ToDesk 顺网云海马云运行 DeepSeek 模型对比评测
  • Linux Socket 编程核心:深入解析 sockaddr 数据结构族
  • Android System WebView 版本对照与内核更新指南
  • GitHub Copilot 网络代理配置与优化实战指南
  • VS Code 集成 Git 使用指南:从配置到协作实战
  • SDWebImage 在 Flutter 中的使用:通过插件桥接
  • ESLint 深度指南:从原理配置到工程化实践
  • jQuery 系列教程 8:插件生态与最佳实践
  • 二叉树高频节点问题解析
  • AI 大模型时代产品经理核心能力与学习指南
  • 在 Windows 上安装 Claude Code 并接入智谱模型
  • NWPU VHR-10 遥感目标检测数据集详解与 YOLO 训练实战
  • 开源无审核限制大型语言模型概述
  • Qwen3.5 核心特性详解:原生多模态与 Agent 能力解析
  • Flutter 以太坊地址库 ethereum_addresses 在鸿蒙系统下的适配与使用
  • 超越 import 与 pip:深入 Python 模块化与依赖管理核心
  • GitHub 趋势日报:2025 年 06 月 26 日开源项目盘点
  • Claude Code 平替方案:OpenCode 搭配 GitHub Copilot 使用指南

相关免费在线工具

  • curl 转代码

    解析常见 curl 参数并生成 fetch、axios、PHP curl 或 Python requests 示例代码。 在线工具,curl 转代码在线工具,online

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online

  • Markdown转HTML

    将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online

  • HTML转Markdown

    将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online

  • JSON 压缩

    通过删除不必要的空白来缩小和压缩JSON。 在线工具,JSON 压缩在线工具,online