Python Selenium自动化测试入门:从环境搭建到Pytest框架实战
2026/9/5 12:00:01 网站建设 项目流程

1. 先搞清楚“自动化测试”到底要解决什么问题

如果你刚接触测试,或者写Python不久,看到“自动化测试”这个词可能会觉得很高大上,感觉要学很多框架、工具,甚至担心自己代码能力不够。其实没那么复杂,自动化测试的核心目标就一个:用代码代替人工,去重复执行那些枯燥、易错但又必须做的检查工作

比如,你开发了一个网站,每次改完代码,都要手动点一遍登录、注册、搜索功能,看有没有报错。做一两次还行,但如果每天要发布十几次,或者有几百个页面,人工根本忙不过来,还容易漏测。这时候,写一段Python脚本,让程序自动打开浏览器、输入数据、点击按钮、检查结果,就是自动化测试。

所以,这个主题适合两类人:一是想从手工测试转向自动化测试的测试工程师;二是开发人员,想给自己的代码加一层“自动质检”,保证每次修改不会把旧功能搞坏。最关键的,它不是让你成为测试理论专家,而是让你立刻能写出可运行、能发现问题的测试脚本

很多人卡在第一步,是因为教程一上来就讲Selenium、Pytest、UnitTest这些框架的概念,但没讲清楚它们各自在什么场景下用。我的建议是,先别管那么多框架,从你最可能遇到的一个具体任务开始:给一个Web页面做自动化测试。通过这个任务,你会自然接触到环境配置、元素定位、脚本编写和报告生成,整个过程跑通,再去看其他工具和项目,就清晰多了。

2. 环境准备:别在第一步就卡住

开始写自动化脚本之前,需要一个能运行Python和浏览器驱动的基础环境。很多新手在这里浪费大量时间,问题往往出在版本冲突、路径不对或者权限不足。

2.1 Python安装与验证

现在Python官网提供了非常清晰的安装程序。对于Windows和macOS用户,我建议直接从官网下载安装包,安装时务必勾选“Add Python to PATH”这个选项,这能省去后续手动配置环境变量的麻烦。

安装完成后,需要验证。不要只看安装界面提示成功,一定要打开命令行(Windows的CMD或PowerShell,macOS/Linux的终端),输入以下命令:

python --version

或者

python3 --version

如果正确显示版本号(如Python 3.10.6),说明安装成功。如果提示“不是内部或外部命令”,那就是环境变量没配好,需要回头检查安装步骤或手动添加PATH。

注意:有些系统预装了Python 2,命令python可能指向旧版本。自动化测试强烈建议使用Python 3.7及以上版本。如果python命令显示2.x版本,而python3显示3.x版本,后续所有操作请统一使用python3pip3

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 pytest
  • Selenium: 核心浏览器自动化库,可以模拟用户操作。
  • 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):

  1. 打开浏览器,导航到登录页面。
  2. 找到用户名输入框,输入测试用户名。
  3. 找到密码输入框,输入测试密码。
  4. 找到登录按钮,点击它。
  5. 等待页面跳转,验证是否登录成功(例如,检查页面是否出现“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(service=service) # 设置一个隐式等待,让脚本在找不到元素时等待一段时间,而不是立刻报错 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[type='submit']") 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.IDBy.CSS_SELECTOR。优先使用ID,因为它是唯一的。如果没有ID,可以用CSS_SELECTORXPATH如何找到这些值?你需要打开浏览器的开发者工具(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(scope="function") def driver(): """为每个测试函数提供一个新的driver实例""" service = Service(ChromeDriverManager().install()) driver = webdriver.Chrome(service=service) 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[type='submit']").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[type='submit']").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 None

4.2 Pytest带来的好处

  1. 结构清晰:每个测试函数独立,互不干扰。driverfixture确保了每个测试都有干净的浏览器环境。
  2. 断言更强大:Pytest的断言就是普通的Pythonassert语句,失败时会输出详细的对比信息。
  3. 运行灵活:在项目根目录下,直接运行pytest命令,它会自动发现并运行所有test_开头的文件和函数。
    • 运行单个文件:pytest test_login_pytest.py
    • 运行单个函数:pytest test_login_pytest.py::test_successful_login
    • 输出详细结果:pytest -v
  4. 生成报告:可以生成多种格式的报告,例如HTML报告,方便查看和分享。
    pytest --html=report.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[type='submit']").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.py

5.1 页面对象模型(POM)

这是大型自动化测试项目的基石。核心思想是将页面元素定位和操作封装成类,测试脚本只调用类的方法,不直接操作Selenium API。这样,当页面UI变化时,你只需要修改对应的页面类,而不需要修改大量测试脚本。

以登录页面为例,pages/login_page.py

from 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[type='submit']") 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 message

5.2 配置管理与数据驱动

将环境配置(如浏览器类型、基础URL、超时时间)和测试数据从代码中分离。可以使用config.iniconfig.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.yml

name: Python UI Automation Test on: [push, pull_request] jobs: test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - name: Set up Python uses: actions/setup-python@v4 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 [arch=amd64] 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/ --html=reports/report.html --self-contained-html - name: Upload test report uses: actions/upload-artifact@v3 if: always() with: name: html-report path: reports/

这样,每次代码推送,都会在云端自动运行你的自动化测试套件,并生成可下载的测试报告。

6. 常见问题排查与性能优化

自动化测试脚本不是一次写完就高枕无忧,运行中会遇到各种问题。以下是几个高频问题及排查思路。

6.1 元素定位失败(NoSuchElementException)

这是最常见的问题。

  1. 检查定位器:首先确认你用的ID、CSS Selector或XPath是否正确。页面改版后,定位器很可能失效。用浏览器开发者工具重新检查。
  2. 检查等待时间:元素还没加载出来脚本就去找了。增加隐式等待时间,或在关键操作前添加显式等待(WebDriverWait)。
  3. 检查iframe:如果目标元素在<iframe>里,需要先使用driver.switch_to.frame()切换到对应的iframe内,才能定位其中的元素。
  4. 检查页面是否跳转:点击某个按钮后,页面可能刷新或跳转,此时旧的元素引用会失效。需要在操作后重新定位元素。

6.2 测试运行速度慢

  1. 优化等待策略:减少固定的time.sleep(),多用智能的显式等待。显式等待会在条件满足后立即继续,而不是傻等固定时间。
  2. 使用无头模式(Headless):在不需要观察浏览器界面的CI环境或后台执行时,可以启用无头模式,节省渲染开销。
    from selenium.webdriver.chrome.options import Options options = Options() options.add_argument("--headless") # 启用无头模式 options.add_argument("--disable-gpu") driver = webdriver.Chrome(options=options)
  3. 复用浏览器会话:对于一组关联的测试,可以考虑使用scope="session"的fixture来初始化一次driver,所有测试共用,而不是每个测试都开闭一次浏览器。但要注意测试之间的数据隔离,避免相互影响。
  4. 并行执行:Pytest支持通过pytest-xdist插件并行运行测试,充分利用多核CPU。
    pip install pytest-xdist pytest -n 4 # 使用4个worker并行运行

6.3 测试不稳定(Flaky Tests)

有时成功有时失败的测试最让人头疼。

  1. 增强等待条件:不要只等待元素出现(presence_of_element_located),有时需要等待元素可点击(element_to_be_clickable)或可见(visibility_of_element_located)。
  2. 重试机制:对于已知的不稳定操作,可以使用重试装饰器。Pytest也有插件pytest-rerunfailures支持整个用例失败后重跑。
    pip install pytest-rerunfailures pytest --reruns 3 --reruns-delay 2 # 失败后重试3次,每次间隔2秒
  3. 隔离测试环境:确保每个测试用例都是独立的,不依赖于前一个测试留下的数据或状态。善用fixture的setupteardown来清理环境。

6.4 报告与日志

清晰的报告和日志是快速定位问题的关键。

  1. 使用Pytest内置报告pytest -v输出详细结果,pytest --tb=short简化错误回溯信息。
  2. 集成Allure报告:Allure能生成非常美观且信息丰富的交互式测试报告。
    pip install allure-pytest pytest --alluredir=./allure-results allure serve ./allure-results # 生成并打开本地报告
  3. 自定义日志:在关键步骤(如开始测试、执行操作、断言前)打印日志,并记录到文件。
    import logging logging.basicConfig(level=logging.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 自动化Selenium+Pytest测试网站前端功能,用户交互流程。最高。应用最广,入门直观。
接口自动化Requests+Pytest测试后端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 持续学习资源

  1. 官方文档永远是第一选择:Selenium、Pytest、Requests的官方文档写得非常好,遇到问题先查文档。
  2. GitHub找开源项目:搜索“selenium pytest example”、“web automation framework”等关键词,看别人是怎么组织项目的。
  3. 动手做个人小项目:找一个你经常使用的网站(注意遵守robots.txt和服务条款),尝试为其核心流程(如搜索、加入购物车、下单)编写自动化测试。这是最好的练习。

自动化测试是一个实践性极强的领域,看十遍教程不如动手写一个脚本并让它稳定运行起来。过程中遇到的每一个报错,都是你深入理解一个知识点的机会。从环境搭建到第一个脚本,从单个用例到框架项目,每一步都踩实,你就能真正从零走到精通。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询