ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

Python Selenium自动化测试入门:从环境搭建到Pytest框架实战

2026/9/4 11:30:32 拓冰建站 浏览量
Python Selenium自动化测试入门:从环境搭建到Pytest框架实战 1. 先搞清楚“自动化测试”到底要解决什么问题如果你刚接触测试或者写Python不久看到“自动化测试”这个词可能会觉得很高大上感觉要学很多框架、工具甚至担心自己代码能力不够。其实没那么复杂自动化测试的核心目标就一个用代码代替人工去重复执行那些枯燥、易错但又必须做的检查工作。比如你开发了一个网站每次改完代码都要手动点一遍登录、注册、搜索功能看有没有报错。做一两次还行但如果每天要发布十几次或者有几百个页面人工根本忙不过来还容易漏测。这时候写一段Python脚本让程序自动打开浏览器、输入数据、点击按钮、检查结果就是自动化测试。所以这个主题适合两类人一是想从手工测试转向自动化测试的测试工程师二是开发人员想给自己的代码加一层“自动质检”保证每次修改不会把旧功能搞坏。最关键的它不是让你成为测试理论专家而是让你立刻能写出可运行、能发现问题的测试脚本。很多人卡在第一步是因为教程一上来就讲Selenium、Pytest、UnitTest这些框架的概念但没讲清楚它们各自在什么场景下用。我的建议是先别管那么多框架从你最可能遇到的一个具体任务开始给一个Web页面做自动化测试。通过这个任务你会自然接触到环境配置、元素定位、脚本编写和报告生成整个过程跑通再去看其他工具和项目就清晰多了。2. 环境准备别在第一步就卡住开始写自动化脚本之前需要一个能运行Python和浏览器驱动的基础环境。很多新手在这里浪费大量时间问题往往出在版本冲突、路径不对或者权限不足。2.1 Python安装与验证现在Python官网提供了非常清晰的安装程序。对于Windows和macOS用户我建议直接从官网下载安装包安装时务必勾选“Add Python to PATH”这个选项这能省去后续手动配置环境变量的麻烦。安装完成后需要验证。不要只看安装界面提示成功一定要打开命令行Windows的CMD或PowerShellmacOS/Linux的终端输入以下命令python --version或者python3 --version如果正确显示版本号如Python 3.10.6说明安装成功。如果提示“不是内部或外部命令”那就是环境变量没配好需要回头检查安装步骤或手动添加PATH。注意有些系统预装了Python 2命令python可能指向旧版本。自动化测试强烈建议使用Python 3.7及以上版本。如果python命令显示2.x版本而python3显示3.x版本后续所有操作请统一使用python3和pip3。2.2 包管理工具pip与虚拟环境Python的强大在于丰富的第三方库通过pip工具安装。同样在命令行验证pip --version为了项目依赖隔离避免不同项目间的库版本冲突强烈建议使用虚拟环境。这是新手容易忽略但老手一定会做的步骤。创建一个名为auto_test_env的虚拟环境# Windows python -m venv auto_test_env # macOS/Linux python3 -m venv auto_test_env激活虚拟环境# Windows (在CMD中) auto_test_env\Scripts\activate # Windows (在PowerShell中) .\auto_test_env\Scripts\Activate.ps1 # macOS/Linux source auto_test_env/bin/activate激活后命令行提示符前会出现(auto_test_env)字样表示你后续的所有安装和操作都局限在这个独立环境里。2.3 核心测试库安装在激活的虚拟环境中安装我们第一个实战案例需要的库pip install selenium pip install webdriver-manager pip install pytestSelenium: 核心浏览器自动化库可以模拟用户操作。Webdriver-manager: 一个非常实用的工具它能自动下载和管理不同浏览器Chrome, Firefox, Edge的驱动省去手动下载和配置驱动路径的麻烦。Pytest: 一个比Python自带unittest更简洁、功能更强大的测试框架用于组织测试用例和生成报告。至此最基本的环境就准备好了。记住这个顺序装Python - 配好PATH - 建虚拟环境 - 在虚拟环境里装库。很多“莫名其妙”的报错都是因为跳过了虚拟环境导致全局Python环境被污染。3. 第一个实战脚本自动化登录测试理论讲再多不如动手跑一遍。我们用一个最常见的场景——网站登录来串起整个流程。假设我们要测试一个登录页面可以用任何公开的测试网站例如https://www.example.com但为了更真实我们以https://the-internet.herokuapp.com/login这个著名的测试页为例。3.1 脚本编写思路自动化测试脚本不是乱点一通它应该有清晰的步骤和断言Assertion打开浏览器导航到登录页面。找到用户名输入框输入测试用户名。找到密码输入框输入测试密码。找到登录按钮点击它。等待页面跳转验证是否登录成功例如检查页面是否出现“Welcome”或“Logout”文字。3.2 完整代码示例创建一个名为test_login.py的文件写入以下代码from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from webdriver_manager.chrome import ChromeDriverManager from selenium.webdriver.chrome.service import Service import time def test_login(): 测试登录功能 # 1. 设置驱动使用webdriver-manager自动管理 service Service(ChromeDriverManager().install()) driver webdriver.Chrome(serviceservice) # 设置一个隐式等待让脚本在找不到元素时等待一段时间而不是立刻报错 driver.implicitly_wait(10) try: # 2. 打开登录页面 driver.get(https://the-internet.herokuapp.com/login) print(已打开登录页面) # 3. 定位元素并操作 # 找到用户名输入框通过元素的id属性定位 username_box driver.find_element(By.ID, username) username_box.send_keys(tomsmith) # 输入用户名 # 找到密码输入框 password_box driver.find_element(By.ID, password) password_box.send_keys(SuperSecretPassword!) # 输入密码 # 找到登录按钮并点击 login_button driver.find_element(By.CSS_SELECTOR, button[typesubmit]) login_button.click() print(已点击登录按钮) # 4. 验证登录结果 # 显式等待直到“登录成功”的区域出现 wait WebDriverWait(driver, 10) # 等待页面上出现包含‘You logged into a secure area!’文本的元素 success_message wait.until( EC.presence_of_element_located((By.XPATH, //*[contains(text(), You logged into a secure area!)])) ) # 断言如果找到了成功信息测试通过 assert success_message is not None print(登录成功测试通过。) # 为了看清结果等待3秒 time.sleep(3) except Exception as e: # 如果出现任何异常打印错误并认为测试失败 print(f测试失败错误信息{e}) # 这里可以截图保存便于排查 driver.save_screenshot(login_failure.png) raise e finally: # 5. 无论成功失败最后都要关闭浏览器 driver.quit() print(浏览器已关闭) if __name__ __main__: test_login()3.3 逐行解析与避坑点驱动管理ChromeDriverManager().install()会自动检查你电脑Chrome浏览器的版本并下载匹配的ChromeDriver这是避免“版本不匹配”报错的最佳实践。元素定位这是Selenium的核心也是脚本最脆弱的地方。代码中用了By.ID和By.CSS_SELECTOR。优先使用ID因为它是唯一的。如果没有ID可以用CSS_SELECTOR或XPATH。如何找到这些值你需要打开浏览器的开发者工具F12使用“检查”功能去查看页面元素的属性。等待机制implicitly_wait(10)隐式等待全局生效。在查找元素时如果没立刻找到会最多等10秒。WebDriverWait显式等待更精确。这里我们明确等待某个特定文本出现最多等10秒。页面加载慢或元素动态生成时必须用显式等待否则脚本会因找不到元素而失败。异常处理与截图try...except块捕获异常失败时用driver.save_screenshot保存当前页面截图。这是排查问题的黄金手段比看日志文字直观得多。finally关闭浏览器确保无论测试成功与否浏览器进程都会被关闭避免残留进程占用内存。运行这个脚本你会看到浏览器自动打开、输入、点击、然后提示成功。恭喜你第一个Web自动化测试脚本就完成了。它虽然简单但包含了环境、定位、操作、断言、异常处理所有关键环节。4. 从脚本到项目用Pytest框架组织测试单个脚本可以工作但当你有了几十上百个测试用例时就需要框架来管理。Pytest是目前Python生态里最主流的测试框架它能让测试的编写、运行和报告变得非常规范。4.1 使用Pytest改造登录测试首先Pytest约定测试文件以test_开头测试函数也以test_开头。我们把刚才的脚本改造成Pytest风格。新建一个文件test_login_pytest.py:import pytest from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from webdriver_manager.chrome import ChromeDriverManager from selenium.webdriver.chrome.service import Service # 这是一个fixture用于初始化和清理driver作用类似于setup/teardown pytest.fixture(scopefunction) def driver(): 为每个测试函数提供一个新的driver实例 service Service(ChromeDriverManager().install()) driver webdriver.Chrome(serviceservice) driver.implicitly_wait(5) yield driver # 将driver对象传递给测试函数 driver.quit() # 测试函数执行完后执行清理工作 def test_successful_login(driver): 测试正确的用户名密码能否登录成功 driver.get(https://the-internet.herokuapp.com/login) driver.find_element(By.ID, username).send_keys(tomsmith) driver.find_element(By.ID, password).send_keys(SuperSecretPassword!) driver.find_element(By.CSS_SELECTOR, button[typesubmit]).click() success_text WebDriverWait(driver, 10).until( EC.presence_of_element_located((By.XPATH, //*[contains(text(), You logged into a secure area!)])) ) assert success_text is not None def test_failed_login(driver): 测试错误的密码能否被正确拦截 driver.get(https://the-internet.herokuapp.com/login) driver.find_element(By.ID, username).send_keys(tomsmith) driver.find_element(By.ID, password).send_keys(WrongPassword!) driver.find_element(By.CSS_SELECTOR, button[typesubmit]).click() # 等待并检查错误提示信息 error_message WebDriverWait(driver, 10).until( EC.presence_of_element_located((By.XPATH, //*[contains(text(), Your password is invalid!)])) ) assert error_message is not None4.2 Pytest带来的好处结构清晰每个测试函数独立互不干扰。driverfixture确保了每个测试都有干净的浏览器环境。断言更强大Pytest的断言就是普通的Pythonassert语句失败时会输出详细的对比信息。运行灵活在项目根目录下直接运行pytest命令它会自动发现并运行所有test_开头的文件和函数。运行单个文件pytest test_login_pytest.py运行单个函数pytest test_login_pytest.py::test_successful_login输出详细结果pytest -v生成报告可以生成多种格式的报告例如HTML报告方便查看和分享。pytest --htmlreport.html运行后会在当前目录生成一个report.html文件用浏览器打开可以看到清晰的测试通过/失败汇总、每个用例的执行详情甚至截图需要额外插件。4.3 测试数据分离把测试数据如用户名、密码、URL硬编码在脚本里不是好习惯。Pytest支持通过参数化pytest.mark.parametrize来批量运行多组数据。import pytest # 参数化用一组数据驱动同一个测试逻辑 pytest.mark.parametrize(username, password, expected_message, [ (tomsmith, SuperSecretPassword!, You logged into a secure area!), # 成功案例 (tomsmith, wrong, Your password is invalid!), # 密码错误 (alice, SuperSecretPassword!, Your username is invalid!), # 用户名错误 ]) def test_login_with_parameters(driver, username, password, expected_message): 使用参数化测试多组登录场景 driver.get(https://the-internet.herokuapp.com/login) driver.find_element(By.ID, username).send_keys(username) driver.find_element(By.ID, password).send_keys(password) driver.find_element(By.CSS_SELECTOR, button[typesubmit]).click() # 动态等待预期的消息出现 message_element WebDriverWait(driver, 10).until( EC.presence_of_element_located((By.XPATH, f//*[contains(text(), {expected_message})])) ) assert message_element is not None这样你只需要维护一个数据列表就能轻松扩展测试场景。这是自动化测试框架化的核心价值之一。5. 进阶与扩展搭建你的自动化测试项目掌握了单点脚本和Pytest框架后就可以考虑搭建一个结构清晰、易于维护的自动化测试项目了。一个典型的项目目录结构如下my_auto_test_project/ ├── conftest.py # Pytest全局配置和共享fixture ├── requirements.txt # 项目依赖库列表 ├── pages/ # 页面对象模型Page Object Model, POM │ ├── __init__.py │ └── login_page.py ├── tests/ # 测试用例目录 │ ├── __init__.py │ ├── test_login.py │ └── test_search.py ├── data/ # 测试数据文件如JSON, YAML, Excel │ └── test_data.json ├── reports/ # 测试报告输出目录 │ └── (由pytest-html等插件生成) └── utils/ # 工具类如读取配置文件、处理日志 ├── __init__.py └── config_reader.py5.1 页面对象模型POM这是大型自动化测试项目的基石。核心思想是将页面元素定位和操作封装成类测试脚本只调用类的方法不直接操作Selenium API。这样当页面UI变化时你只需要修改对应的页面类而不需要修改大量测试脚本。以登录页面为例pages/login_page.pyfrom selenium.webdriver.common.by import By from selenium.webdriver.support.wait import WebDriverWait from selenium.webdriver.support import expected_conditions as EC class LoginPage: 登录页面的封装 # 将元素定位器集中管理 URL https://the-internet.herokuapp.com/login USERNAME_INPUT (By.ID, username) PASSWORD_INPUT (By.ID, password) LOGIN_BUTTON (By.CSS_SELECTOR, button[typesubmit]) FLASH_MESSAGE (By.ID, flash) # 成功或错误信息的容器 def __init__(self, driver): self.driver driver self.wait WebDriverWait(driver, 10) def open(self): 打开登录页面 self.driver.get(self.URL) return self def enter_username(self, username): 输入用户名 self.driver.find_element(*self.USERNAME_INPUT).send_keys(username) return self def enter_password(self, password): 输入密码 self.driver.find_element(*self.PASSWORD_INPUT).send_keys(password) return self def click_login(self): 点击登录按钮 self.driver.find_element(*self.LOGIN_BUTTON).click() return self def get_message(self): 获取页面上的提示信息 element self.wait.until(EC.presence_of_element_located(self.FLASH_MESSAGE)) return element.text.strip()然后在测试脚本中使用就变得非常简洁from pages.login_page import LoginPage def test_login_with_pom(driver): 使用POM模式的登录测试 login_page LoginPage(driver) # 链式调用清晰表达操作流程 message (login_page.open() .enter_username(tomsmith) .enter_password(SuperSecretPassword!) .click_login() .get_message()) assert You logged into a secure area! in message5.2 配置管理与数据驱动将环境配置如浏览器类型、基础URL、超时时间和测试数据从代码中分离。可以使用config.ini或config.yaml文件然后用工具类读取。config.yaml示例test_env: base_url: https://the-internet.herokuapp.com browser: chrome implicit_wait: 5 explicit_wait: 10 login_test_data: valid: username: tomsmith password: SuperSecretPassword! expected_message: You logged into a secure area! invalid_password: username: tomsmith password: wrong expected_message: Your password is invalid!在conftest.py中读取配置并通过fixture提供给所有测试用例。5.3 持续集成CI接入项目稳定后可以接入Jenkins、GitLab CI、GitHub Actions等持续集成工具实现代码提交后自动触发测试。以GitHub Actions为例可以在项目根目录创建.github/workflows/test.ymlname: Python UI Automation Test on: [push, pull_request] jobs: test: runs-on: ubuntu-latest steps: - uses: actions/checkoutv3 - name: Set up Python uses: actions/setup-pythonv4 with: python-version: 3.10 - name: Install dependencies run: | python -m pip install --upgrade pip pip install -r requirements.txt - name: Install Chrome and ChromeDriver run: | sudo apt-get update sudo apt-get install -y wget unzip wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | sudo apt-key add - echo deb [archamd64] http://dl.google.com/linux/chrome/deb/ stable main | sudo tee /etc/apt/sources.list.d/google-chrome.list sudo apt-get update sudo apt-get install -y google-chrome-stable - name: Run tests with pytest run: | pytest tests/ --htmlreports/report.html --self-contained-html - name: Upload test report uses: actions/upload-artifactv3 if: always() with: name: html-report path: reports/这样每次代码推送都会在云端自动运行你的自动化测试套件并生成可下载的测试报告。6. 常见问题排查与性能优化自动化测试脚本不是一次写完就高枕无忧运行中会遇到各种问题。以下是几个高频问题及排查思路。6.1 元素定位失败NoSuchElementException这是最常见的问题。检查定位器首先确认你用的ID、CSS Selector或XPath是否正确。页面改版后定位器很可能失效。用浏览器开发者工具重新检查。检查等待时间元素还没加载出来脚本就去找了。增加隐式等待时间或在关键操作前添加显式等待WebDriverWait。检查iframe如果目标元素在iframe里需要先使用driver.switch_to.frame()切换到对应的iframe内才能定位其中的元素。检查页面是否跳转点击某个按钮后页面可能刷新或跳转此时旧的元素引用会失效。需要在操作后重新定位元素。6.2 测试运行速度慢优化等待策略减少固定的time.sleep()多用智能的显式等待。显式等待会在条件满足后立即继续而不是傻等固定时间。使用无头模式Headless在不需要观察浏览器界面的CI环境或后台执行时可以启用无头模式节省渲染开销。from selenium.webdriver.chrome.options import Options options Options() options.add_argument(--headless) # 启用无头模式 options.add_argument(--disable-gpu) driver webdriver.Chrome(optionsoptions)复用浏览器会话对于一组关联的测试可以考虑使用scopesession的fixture来初始化一次driver所有测试共用而不是每个测试都开闭一次浏览器。但要注意测试之间的数据隔离避免相互影响。并行执行Pytest支持通过pytest-xdist插件并行运行测试充分利用多核CPU。pip install pytest-xdist pytest -n 4 # 使用4个worker并行运行6.3 测试不稳定Flaky Tests有时成功有时失败的测试最让人头疼。增强等待条件不要只等待元素出现presence_of_element_located有时需要等待元素可点击element_to_be_clickable或可见visibility_of_element_located。重试机制对于已知的不稳定操作可以使用重试装饰器。Pytest也有插件pytest-rerunfailures支持整个用例失败后重跑。pip install pytest-rerunfailures pytest --reruns 3 --reruns-delay 2 # 失败后重试3次每次间隔2秒隔离测试环境确保每个测试用例都是独立的不依赖于前一个测试留下的数据或状态。善用fixture的setup和teardown来清理环境。6.4 报告与日志清晰的报告和日志是快速定位问题的关键。使用Pytest内置报告pytest -v输出详细结果pytest --tbshort简化错误回溯信息。集成Allure报告Allure能生成非常美观且信息丰富的交互式测试报告。pip install allure-pytest pytest --alluredir./allure-results allure serve ./allure-results # 生成并打开本地报告自定义日志在关键步骤如开始测试、执行操作、断言前打印日志并记录到文件。import logging logging.basicConfig(levellogging.INFO, format%(asctime)s - %(levelname)s - %(message)s) logger logging.getLogger(__name__) def test_something(driver): logger.info(开始执行登录测试...) # ... 操作步骤 logger.info(断言登录成功消息...)7. 技术选型与学习路线建议看到这里你已经掌握了从零开始搭建一个Web UI自动化测试项目的基本能力。但自动化测试领域很广除了Selenium做的UI自动化还有接口自动化、移动端自动化等。不要试图一次性学完所有工具按需学习。7.1 不同测试类型工具选型测试类型推荐工具/框架适用场景学习优先级针对新手Web UI 自动化SeleniumPytest测试网站前端功能用户交互流程。最高。应用最广入门直观。接口自动化RequestsPytest测试后端API的正确性、性能和稳定性。高。比UI测试更快、更稳定是测试金字塔的中坚。移动端App自动化Appium测试Android/iOS原生、混合或Web应用。中。原理与Selenium类似但环境搭建更复杂。单元测试Pytest/Unittest测试单个函数、类或模块的逻辑。高对开发人员。是代码质量的基石。性能测试Locust(Python) / JMeter测试系统在高并发下的表现。中后期。需要基础扎实后再接触。对于新手我建议的路径是Selenium UI自动化 - Requests 接口自动化 - Pytest 测试框架深入 - 整合成项目POM、数据驱动、CI。这个路径能让你快速获得正反馈并建立起对自动化测试的完整认知。7.2 关于“AI驱动自动化测试”和“录制工具”输入材料里提到了“AI驱动智能自动化测试平台”和“录制工具”。我的看法是录制工具像Selenium IDE、Katalon Recorder这类工具可以录制你的操作并生成脚本。非常适合快速生成原型或学习定位器但录制的脚本通常冗长、难以维护不适合复杂项目。可以作为辅助但不能依赖。AI驱动测试目前更多体现在智能元素定位、测试用例生成、视觉测试、缺陷预测等方面。它是强大的辅助但不是银弹。底层仍然需要你具备扎实的编程和测试框架知识来整合、维护和判断AI的输出。对于初学者先打好Selenium和Pytest的基础远比追逐“AI自动化”更重要。7.3 持续学习资源官方文档永远是第一选择Selenium、Pytest、Requests的官方文档写得非常好遇到问题先查文档。GitHub找开源项目搜索“selenium pytest example”、“web automation framework”等关键词看别人是怎么组织项目的。动手做个人小项目找一个你经常使用的网站注意遵守robots.txt和服务条款尝试为其核心流程如搜索、加入购物车、下单编写自动化测试。这是最好的练习。自动化测试是一个实践性极强的领域看十遍教程不如动手写一个脚本并让它稳定运行起来。过程中遇到的每一个报错都是你深入理解一个知识点的机会。从环境搭建到第一个脚本从单个用例到框架项目每一步都踩实你就能真正从零走到精通。