尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
Selenium+Pytest+Allure自动化测试环境搭建与报告生成
很多测试朋友第一次接触自动化测试时卡住的地方往往不是测试用例本身而是“把环境跑起来”这一步。我也见过不少同学照着网上一堆教程敲了半天命令最后连一个简单登录用例都跑不出报告来。这篇笔记就用我自己实际动手的顺序完整讲清楚 Python Selenium Pytest Allure 这套组合从裸机到产出可视化报告的搭建过程包含会遇到哪些标志性报错、为什么会报错、怎么解决。适合刚入行想告别手工点点点的人也适合已经在写脚本但还没接 Allure 报告的人作参考。1. 这套技术栈到底解决什么问题1.1 四个组件在框架里各司其职如果一句话概括这套组合就是“用真实浏览器跑一遍用户操作自动校验结果再把执行过程和失败原因整理成一份能看懂的报告”。Python 在这里是编程语言也是整个框架的粘合剂。Selenium 负责打开浏览器、模拟点击输入、提取页面信息它本质上是浏览器提供的一层外部控制接口标准称呼是 WebDriver。Pytest 是测试执行框架负责收集用例、管理前后置动作、做断言判断、产出 JUnit 风格的执行结果。Allure 则是报告展示层把 Pytest 生成的结果文件渲染成带统计图表、步骤日志、失败截图的历史报告。四者之间的关系是单向依赖的Pytest 中调用 Selenium 写测试步骤执行时把结果交给 Allure 插件最终由 Allure 命令行工具生成 HTML 报告。每一层只干一件事出了问题也更容易定位。1.2 为什么不是别的组合网上方案不止这一种比如 Robot Framework 搭配 SeleniumLibrary或者 Java 体系里的 TestNG Selenium甚至有人直接用 Python 自带的 unittest。我选这套组合的理由比较务实Pytest 的断言语法贴近原生 Python不用学关键字语法写起来更像普通代码unittest 虽然不用额外安装但它的组织结构比较死板一个类的 setUp 和 tearDown 分散注意力测试数据驱动也不如 Pytest 的若干机制来得痛快。Robot Framework 确实适合用例维护者不懂代码的团队但如果你本身能写 Python从这类“伪代码”框架里绕一圈反而增加一层理解成本。Java 体系不是说不好只是对很多测试员来说 Python 的学习曲线更平滑出结果更快。选型这事没有绝对最优关键是团队里谁能维护、项目周期允许多长的学习时间我在这套技术栈上的实际感受是从环境搭建到出第一份报告熟练的话一小时左右能完成这个速度很适合技术调研和面试造轮子。2. 环境准备从裸机到工具链可用的完整步骤2.1 Python 环境与虚拟环境第一步不是直接装 Selenium而是先确保 Python 本身没问题。建议安装 Python 3.10 或更高版本官网下载安装包时务必勾选“Add Python to PATH”这一步最容易被忽略。没勾选的话后续在命令行敲 python 会提示“不是内部或外部命令”虽然可以用全路径调用但没必要给自己挖这个坑。装完在终端验证python --version能输出 Python 3.x.x 就说明基础环境正常。接着我习惯先建虚拟环境再装依赖不直接往全局环境里塞包裹python -m venv automation_envWindows 下激活命令是 automation_env\Scripts\activatemacOS/Linux 则是 source automation_env/bin/activate。终端提示符出现 (automation_env) 前缀后再安装包就都和全局环境隔离了。这个习惯能避免不同项目之间的包版本冲突尤其是 Pytest 插件这类全局影响明显的东西。我见过不少同事先全局装一堆包结果某个项目需要降级 pytest 版本时把别的项目搞崩最后只能整环境重来。2.2 安装依赖与浏览器驱动激活虚拟环境后安装四个核心依赖pip install selenium pytest allure-pytest如果下载速度比较慢可以临时换成国内镜像源pip install selenium pytest allure-pytest -i https://pypi.tuna.tsinghua.edu.cn/simple这里特别说一下 Selenium 版本。如果你是 Selenium 4.6 及以上版本驱动这块省了不少心它内置了 Selenium Manager第一次启动浏览器时会自动识别浏览器版本并下载匹配的驱动不需要手动去下载 ChromeDriver。但自动下载依赖网络而且有可能因为远端服务超时而失败。所以我也保留了手动下载驱动的能力先确认浏览器版本打开浏览器访问 chrome://settings/help 看版本号再去对应驱动站点下载相同版本的驱动文件把它放到环境变量 PATH 中的某个目录或者直接放项目根目录并在代码里指定路径。驱动和浏览器版本不匹配是最经典的报错后面排查章节我会专门展开。自动化测试这件事90% 的时间其实都花在环境对齐上这里多啰嗦几句不亏。3. 搭一个能跑通的最小自动化测试项目3.1 项目目录结构的规划思路很多人学自动化时有个坏习惯所有代码堆在同一个目录的几个脚本里。测试用例一旦超过十个维护成本立刻上升。我在搭建初期就会按职责分目录哪怕项目很小也保持清晰分层project/ ├── config/ │ └── config.py ├── pages/ │ └── login_page.py ├── testcases/ │ └── test_login.py ├── common/ │ ├── webdriver_factory.py │ └── screenshot.py ├── report/ │ ├── allure-results/ │ └── allure-report/ ├── requirements.txt └── pytest.inipages 目录放页面对象模型每个页面一个类封装元素定位和操作动作比如输入用户名、点击登录按钮。testcases 目录只放测试用例用例里不直接写 find_element而是调用 pages 层的方法。这样做的好处是页面结构变了只需要改 pages 层断言逻辑变了只需要改 testcases 层。common 目录放公共工具比如启动浏览器的工厂函数、截图处理函数。config 存放项目全局配置比如域名、超时时间、截图路径。这个结构不是拍脑袋定的而是根据实际维护经验总结出来的。刚开始项目小可能感受不到分层的好处等用例量上来、页面频繁改版时就知道把定位器和测试逻辑分开有多重要。3.2 第一个真实用例登录场景演示我先写一个简化的登录页面封装演示怎么把 Selenium 的机械操作用代码表达出来# pages/login_page.py from selenium.webdriver.common.by import By class LoginPage: def __init__(self, driver): self.driver driver # 集中管理元素定位 self.username_input (By.ID, username) self.password_input (By.NAME, password) self.login_button (By.CSS_SELECTOR, button[typesubmit]) def input_username(self, text): self.driver.find_element(*self.username_input).send_keys(text) def input_password(self, text): self.driver.find_element(*self.password_input).send_keys(text) def click_login(self): self.driver.find_element(*self.login_button).click()对应的测试用例# testcases/test_login.py from selenium import webdriver from pages.login_page import LoginPage def test_login_success(): driver webdriver.Chrome() driver.get(https://example.com/login) login LoginPage(driver) login.input_username(test_user) login.input_password(test_password) login.click_login() assert dashboard in driver.current_url driver.quit()这里有几个值得留意的点。第一定位符以元组形式集中存放在类属性里后续修改定位手段时只需要改一处。第二用例尽量做到一个用例验证一个核心行为比如只验证登录成功后的页面跳转不要又验证登出又验证密码错误提示否则断言失败时定位问题要多绕很多弯路。第三driver.quit() 放在用例末尾用例失败时不会执行更稳的做法是放到 Pytest 的 fixture 清理阶段下一小节展开。3.3 用 Pytest Fixture 管好浏览器生命周期直接在每个用例里写 webdriver.Chrome() 和 driver.quit() 也能跑但用例多了以后会有大量重复代码而且用例中途断言失败会导致浏览器进程残留拖慢后续执行甚至造成端口冲突。Pytest 的 fixture 机制可以优雅解决前后置管理问题。在项目根目录创建 conftest.pyPytest 会自动识别这个文件里的 fixture# conftest.py import pytest from selenium import webdriver pytest.fixture def driver(): _driver webdriver.Chrome() _driver.implicitly_wait(10) _driver.maximize_window() yield _driver _driver.quit()注意这段代码放弃了原来的 yield 前启动、yield 后清理的写法回归到比较典型的 fixture 结构用例执行前启动浏览器用例结束后无论失败成功都会执行 _driver.quit()。implicitly_wait(10) 是隐式等待意思是查找元素时最多等 10 秒如果元素提前出现就提前返回这个设置能减少不少由于页面加载慢导致的找不到元素问题。用例改造后# testcases/test_login.py from pages.login_page import LoginPage def test_login_success(driver): driver.get(https://example.com/login) login LoginPage(driver) login.input_username(test_user) login.input_password(test_password) login.click_login() assert dashboard in driver.current_url这样写的好处是浏览器管理逻辑完全和用例解耦。后续想加浏览器失败截图、执行日志只需要在 fixture 里做文章不用每个用例都改。想维护多浏览器跑用例时把 fixture 的参数改成从配置文件读取浏览器类型也能做到尽量少的改动量。4. 接入 Allure从日志到可视化报告的最后一公里4.1 Allure 命令行工具安装前面提到的 allure-pytest 只是 Pytest 和 Allure 之间的“搬运工”真正生成 HTML 报告还需要 Allure 命令行工具本身。它是 Java 生态的工具所以前提条件是有可用的 JDK建议 JDK 8 以上。安装方式根据系统有所不同。Windows 用户可以直接下载 allure 命令行的 zip 压缩包解压后将 bin 目录加入 PATHmacOS 用户用 brew 一行搞定brew install allure验证是否安装成功allure --version这条命令能输出版本号说明 Java 环境和工具都正常。如果提示“找不到或无法加载主类”基本就是 JDK 没装好而不是 allure 本身的问题。真正执行测试前还需要在 pytest.ini 里声明 Allure 结果目录。创建 pytest.ini[pytest] addopts -v --alluredirreport/allure-results testpaths testcasesaddopts 里的 --alluredir 指定原始结果的输出目录testpaths 则限定 Pytest 去 testcases 目录下找用例。加上 testpaths 有个好处就是防止 Pytest 误收集 common 或其他目录下名字像用例的文件。4.2 在用例里埋入步骤与附件Allure 报告如果只是罗列用例名和通过/失败状态意义会打折扣。真正有价值的是它能把用户操作拆成分步记录并且在失败时附上当时页面的截图。装饰器和动态方法可以实现这些能力。给用例加上 Allure 特性标签import allure allure.feature(用户登录) allure.story(登录成功后跳转首页) allure.title(正常用户名密码登录) def test_login_success(driver): ...在关键操作处用 with allure.step 包裹def test_login_success(driver): with allure.step(打开登录页面): driver.get(https://example.com/login) login_page LoginPage(driver) with allure.step(输入用户名密码并登录): login_page.input_username(test_user) login_page.input_password(test_password) login_page.click_login() with allure.step(校验是否跳转到仪表盘): assert dashboard in driver.current_url失败时自动截图需要写一个 Pytest 的钩子方法。在 conftest.py 中追加pytest.hookimpl(tryfirstTrue, hookwrapperTrue) def pytest_runtest_makereport(item, call): outcome yield report outcome.get_result() if report.failed: driver item.funcargs.get(driver) if driver: allure.attach( driver.get_screenshot_as_png(), namefailure_screenshot, attachment_typeallure.attachment_type.PNG, )这段代码的含义是在每个测试用例完成后检查结果如果结果为失败就从 fixture 参数中取出 driver 对象把当前浏览器画面截图并以 PNG 格式附加到 Allure 报告中。这样报告里失败用例下方直接可见现场比看一堆 console 日志直观得多。4.3 生成并打开报告执行测试pytest跑完以后 report/allure-results 会生成一系列 json 文件这些是原始数据浏览器直接打开没有意义。需要生成静态报告allure generate report/allure-results -o report/allure-report --clean想要更方便的预览方式可以启动一个本地服务allure serve report/allure-results这个命令会启动临时 Web 服务并在默认浏览器打开报告首页适合快速查看本次执行结果。报告首页有整体通过率、耗时统计、用例层级树、失败信息摘要等内容点进具体用例能看到前面写的每个 step 都有独立记录失败时还有截图和断言错误堆栈。这里补充一个常见误区每次执行前最好清空上一次的 allure-results否则新旧结果会混在一起。我在 generate 命令里加了 --clean但更保险的做法是在执行前手动删除或定期清理该目录。5. 跑自动化测试绕不开的坑与排查对策5.1 元素定位失败的典型场景NoSuchElementException 应该是 Selenium 自动化里出现频率最高的异常报错信息通常会在末尾给出当时尝试定位的表达式。大部分场景逃不过这几类原因第一是元素没有加载完成代码执行过快。解决方法已在 fixture 里用了隐式等待但某些异步渲染的页面更适合显式等待需要等待某个条件成立后再继续from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC WebDriverWait(driver, 10).until( EC.visibility_of_element_located((By.ID, login_button)) )显式等待的作用域比隐式等待精准适合页面里某些元素是接口返回后才出现的场景。实际项目里我通常二者都保留隐式等待兜底显式等待处理关键节点。第二是元素在 iframe 里。Selenium 默认找不到 iframe 内部元素需要先切换进去driver.switch_to.frame(frame_name_or_id) # 操作完成后 driver.switch_to.default_content()第三是定位表达式写得不准。比如 element 有两个相似 class 属性用 find_element 默认返回第一个匹配元素如果你要点的恰恰是第二个就会点错对象。这类问题用 xpath 配合索引或配合父节点定位会更可靠但 xpath 写得太长也会脆。我建议定位器优先级尽量 ID data 属性 CSS 选择器 XPath命名稳定且可读性好。5.2 驱动与浏览器版本不匹配Selenium 启动浏览器时常见的错误是 SessionNotCreatedException提示信息里经常包含 “This version of ChromeDriver only supports Chrome version XXX”。意思是驱动版本和浏览器版本对不上。轻度不匹配可能只是警告但主版本号不一致基本跑不了。如果你开了 Selenium Manager 自动下载驱动多数情况它会自动选对版本。但公司网络环境有限制、或者下载源不稳定时手动放一个 chromedriver 到项目目录里在代码里指定位置from selenium.webdriver.chrome.service import Service service Service(drivers/chromedriver.exe) driver webdriver.Chrome(serviceservice)同一台机器换浏览器版本之后别忘了同步换驱动。这个坑我踩过多回因为这问题表现得非常突然——早上还好好的下午浏览器悄悄自动升级了测试就全红了。遇到这种“昨天能跑今天不能跑”的现象优先怀疑浏览器升级。5.3 Allure 相关疑难杂症Allure 这一侧也容易踩几个隐蔽的坑。比如执行完 pytest 想生成报告却提示 “Allure command not found”这多半是命令行工具没装或 PATH 没生效重新安装并重启终端即可。另一个更常见的问题是报告里没有步骤和截图数据只有一条干巴巴的测试用例名字。排查思路是打开 report/allure-results 目录看里面的 json 文件是否包含步骤信息。如果不包含十有八九是 allure-pytest 插件没装好或者 pytes 和插件版本之间不匹配。重新指定版本安装能解决大多数疑难杂症。还有一次我在 Windows 上执行 allure generate明明命令没问题却提示路径不存在。最后发现是因为项目路径带有中文和空格命令行工具解析路径时产生了歧义。解决方式是把项目尽量放在纯英文路径下或者给命令加双引号把参数引起来。这也是我建议虚拟环境和项目目录都用英文命名的原因之一。5.4 用例执行效率问题用例数量上到一定量级以后串行执行会很费时间。两条路可以缓解一是给用例提升粒度比如验证完登录不需要真的等待 10 秒能用 waited 条件的地方千万别用 time.sleep二是引入并发机制pytest-xdist 可以让用例在多个进程里并行跑pip install pytest-xdist pytest -n 4注意并行执行时如果用例之间共用登录状态或操作同一个浏览器实例会产生数据竞争。所以我在设计用例时就严格要求用例间相互独立不依赖执行顺序尽量不共享状态减少耦合。配合 Allure 报告并发跑完的结果仍然统一汇总不会有几份零散的报告需要人工合并。用例稳定性这块还可以加 pytest-rerunfailures 插件对偶发失败场景做一个重试机制。对于某些因弱网或资源加载慢导致的偶发失败重试一次能极大减少误报。但重试不能滥用如果同一个用例重试三次还挂基本就是真实业务或脚本本身有问题应立即排查而不是盲目依赖重试掩盖问题。写在最后的一点个人体会这套框架本身并不神秘技术点都不难难的是把工程化习惯摆正。我在实际操作中最大的收获是优先保障用例的稳定性和可读性再谈工具链的丰富程度。Pytest 的 fixture、Allure 的步骤日志、页面对象模型这些都不是炫技手段而是为了让人在报告里一眼看出“哪个环节坏了”。最后分享一个我坚持了很久的小技巧每次执行结束后顺手在 Allure 报告里翻一遍失败用例把失败原因归类元素定位问题就优化定位器环境问题就补等待或重试脚本逻辑问题就尽快修代码。一个星期后你的用例稳定性会有明显变化。这套组合后续还能接 CI让它每天早上自动跑一遍然后把报告链接发到团队群这些扩展等基础跑顺了再去研究一点都不会晚。
RELATED

相关推荐

Python爬虫实战:抓取豆瓣Top250并完成数据清洗与可视化分析

Python爬虫实战:抓取豆瓣Top250并完成数据清洗与可视化分析

搞爬虫和数据这块,Top250榜单是个绕不开的经典练手素材。它数据量不大不小,正好够你完整走一遍“请求页面 → 解析内容 → 清洗存储 → 分析可视化”的流程,而且结果天然带有话题性,谁看了都想知道这些高分电影到底分布在哪几年、…

📅 2026/10/21 18:57:43
国产大模型编程能力横评:GLM-5.1与Qwen-3.6首次反超海外标杆

国产大模型编程能力横评:GLM-5.1与Qwen-3.6首次反超海外标杆

过去半年我一直在做一件事:把市面上主流的大模型拉回同一个测试台,用同一批编程任务反复复试。编程能力已经成了大模型最硬核的试金石——代码生成、缺陷修复、工程理解,每一项都比聊天对话更难伪装。这次横评的主角是国产模型的两位代表 GLM…

📅 2026/10/21 18:57:43
零基础转行AI工程师:从后端开发到大模型应用的实战路径

零基础转行AI工程师:从后端开发到大模型应用的实战路径

1. 转型前夜:我一度以为大模型只属于数学天才我到现在还记得去年春天那个晚上,我在出租屋里盯着屏幕上那个开源模型跑出来的第一句对话发呆。那句话写得乱七八糟,错别字都有,但我整个人是颤的——不是因为它多聪明,而是…

📅 2026/10/21 18:57:43
MORE NEWS

更多资讯

📰

R语言常用函数汇总:数学统计、概率与字符处理全覆盖

简介:面向数据分析和统计学习者的R语言常用函数速查手册,以PDF格式整理,适合刚接触R语言、备考数据分析岗位,或在建模前需要快速检索函数用法的读者。内容按数学、统计、概率、字符处理与其他实用函数五类系统展开,覆盖…

📰

NAACL论文速览:大模型评测、RAG与可复现性的实践启示

论文放榜那几天,圈子里讨论最多的不是某篇模型涨了多少分,反而是“这个东西到底能不能复现”。我把某中心这30余篇NAACL论文从头到尾翻了一遍,发现这批工作有一个共同气质:与其堆一个更大的模型,不如把评测、数据、训练…

📰

电动汽车电机驱动控制系统核心技术与工程落地指南

简介:本资源是一份聚焦电动汽车电机驱动控制系统前沿发展的专业技术分析报告,面向新能源汽车领域工程师、高校车辆工程/电气自动化专业师生及行业研究人员,旨在系统梳理当前技术瓶颈与未来演进路径。报告深入剖析直流、交流感应、永磁同步及开…

📰

LiteLLM:一个统一多模型API调用的开源网关方案

1. LiteLLM 到底解决什么问题:一个 API 网关的诞生逻辑做 AI 应用做到某个阶段,你一定会遇到这样一个问题:代码里的模型调用五花八门,某家用 OpenAI 的格式,某家用 Anthropic 的格式,本地跑的去连 Ollama&a…

📰

从“ArtCraft”看手作创作:艺术灵感与工艺实现的缝合点

1. 拆解ArtCraft:艺术与手工的“缝合点”在哪我第一次看到“ArtCraft”这个词,第一反应是它像一个调色盘被摔碎后重新拼接的过程。Art是艺术,Craft是工艺,两者放在一起,既不是让艺术屈尊去迁就手工,也不是让…

📰

Java团队用LangChain4j打造医疗智能客服:多轮对话与RAG实战

做医疗智能客服这个项目的时候,我最大的感受是:AI框架的选型真的可以决定一个Java团队的开发节奏。我们内部代号叫"硅谷小智",说白了就是一个面向患者问诊前、问诊后的智能接待机器人,要能回答科室导诊、就诊流程、检查…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬