PyCharm集成Selenium:构建高效Web自动化测试工作流全攻略
1. 项目概述:为什么选择 PyCharm + Selenium?
如果你是一名 Python 开发者,或者正在向自动化测试领域转型,那么“PyCharm 集成 Selenium”这个组合,几乎是你构建高效、可靠 Web 自动化测试工作流的黄金起点。我见过太多团队和个人,在自动化测试的起步阶段,要么被繁琐的环境配置劝退,要么在脚本编写和调试中耗费大量时间,最终项目不了了之。而 PyCharm 作为一款强大的 Python IDE,与 Selenium 这个业界标准的 Web 自动化框架结合,能极大地平滑这条学习曲线,让你把精力真正集中在测试逻辑和业务验证上,而不是在环境、路径和依赖的泥潭里挣扎。
简单来说,这个工作流的核心价值在于:将专业的开发工具与成熟的自动化框架无缝衔接,实现从环境搭建、脚本编写、元素定位、调试运行到结果分析的全流程闭环。PyCharm 提供了智能代码补全、强大的调试器、便捷的项目管理和虚拟环境支持,而 Selenium 则提供了操控浏览器的标准化接口。两者结合,你得到的不是一个简单的脚本运行环境,而是一个生产力倍增的“自动化测试工作站”。
这个工作流适合谁?无论是刚接触自动化测试的新手,希望有一个清晰、无痛的入门路径;还是有一定经验的测试工程师,寻求提升脚本开发效率和可维护性;甚至是开发人员,需要为自己的 Web 应用编写端到端(E2E)的验收测试,这套组合都能提供强有力的支持。接下来,我将带你从零开始,一步步搭建并优化这个工作流,分享我在实际项目中积累的配置技巧和避坑经验。
2. 环境准备与核心工具链解析
在动手写第一行代码之前,一个稳定、隔离的 Python 环境是成功的基石。很多初学者失败的第一步,就是直接在本地的全局 Python 环境中安装各种包,导致版本冲突、依赖混乱。我们将采用虚拟环境来规避这个问题。
2.1 Python 环境与 PyCharm 版本选择
首先,确保你已安装 Python。我推荐使用 Python 3.8 或更高版本,因为它们在稳定性和对新库的支持上表现更好。你可以通过命令行输入python --version或python3 --version来检查。
关于 PyCharm,JetBrains 提供了两个版本:专业版(Professional)和社区版(Community)。对于 Selenium 自动化测试,社区版的功能已经足够强大,它完全支持 Python 项目、虚拟环境、代码调试和运行。专业版额外提供了对 Web 开发框架(如 Django, Flask)的深度集成、数据库工具以及科学计算模式,如果你后续有这些需求,可以考虑。对于纯粹的自动化测试项目,社区版是免费且完全胜任的。
注意:无论选择哪个版本,请务必从 JetBrains 官网下载安装,避免使用来路不明的版本,以确保稳定性和安全性。
2.2 创建虚拟环境与项目结构
虚拟环境(Virtual Environment)是 Python 项目的“隔离沙箱”。它允许你为每个项目维护独立的依赖包集合,互不干扰。PyCharm 对此提供了原生支持。
步骤一:创建新项目
- 打开 PyCharm,点击
File->New Project。 - 在
Location字段,为你项目选择一个干净的目录,例如D:\Projects\selenium_auto_test。 - 最关键的一步在
Python Interpreter部分。展开New environment using下拉框,你会看到几个选项:- Virtualenv:最常用、最轻量的选择。PyCharm 会在项目目录下创建一个
venv文件夹来存放隔离环境。 - Conda:如果你使用 Anaconda 或 Miniconda 进行 Python 和科学计算包管理,可以选择此项。
- Pipenv / Poetry:更现代的依赖管理工具,集成了虚拟环境和依赖锁定。
- Virtualenv:最常用、最轻量的选择。PyCharm 会在项目目录下创建一个
对于新手和大多数自动化测试场景,我强烈推荐Virtualenv。它简单直接,与 PyCharm 集成度最高。
步骤二:配置虚拟环境选择Virtualenv后,确保Location路径指向项目目录下的一个子文件夹(如venv)。Base interpreter会自动检测到你系统安装的 Python。下方有两个重要复选框:
- Inherit global site-packages:勾选后,虚拟环境可以访问你全局安装的包。不建议勾选,这破坏了隔离的初衷,可能导致依赖污染。
- Make available to all projects:让所有项目都能使用这个解释器。也不建议勾选,我们追求的是项目级别的环境隔离。
点击Create,PyCharm 会自动创建项目并初始化虚拟环境。
步骤三:规划项目结构一个清晰的项目结构能极大提升代码的可维护性。在项目创建后,我建议手动建立如下目录(在 PyCharm 的项目视图中右键点击项目根目录 ->New->Directory):
your_project_name/ ├── tests/ # 存放所有测试用例 │ ├── __init__.py # 使 tests 成为一个 Python 包 │ ├── test_login.py # 示例:登录功能测试 │ └── test_search.py # 示例:搜索功能测试 ├── pages/ # 页面对象模型(Page Object)目录 │ ├── __init__.py │ ├── base_page.py # 所有页面类的基类 │ ├── login_page.py # 登录页面 │ └── home_page.py # 主页 ├── utils/ # 工具函数 │ ├── __init__.py │ └── config_reader.py # 读取配置文件 ├── reports/ # 测试报告输出目录(.gitignore 中忽略) ├── logs/ # 日志文件目录(.gitignore 中忽略) ├── conftest.py # Pytest 的全局配置和夹具(fixture) ├── requirements.txt # 项目依赖清单 └── README.md # 项目说明这个结构遵循了“页面对象模型(Page Object Model, POM)”设计模式,将页面定位和操作与测试逻辑分离,是编写可维护、可复用自动化脚本的最佳实践。我们会在后续章节详细展开。
2.3 安装 Selenium 与 WebDriver 管理
环境就绪,现在安装核心库。
安装 Selenium 库:在 PyCharm 中,你有两种方式安装:
- 终端(Terminal):点击 PyCharm 下方的
Terminal选项卡,确保激活的是你的虚拟环境(命令行前缀会有(venv)字样)。输入命令:pip install selenium - 图形界面:点击
File->Settings(Windows/Linux) 或PyCharm->Preferences(macOS),进入Project: your_project_name->Python Interpreter。点击右上角的+号,搜索selenium并安装。
管理浏览器驱动(WebDriver):这是 Selenium 工作的关键。WebDriver 是一个独立的可执行文件,充当 Selenium 代码和真实浏览器之间的桥梁。你需要为你要测试的浏览器下载对应的驱动。
- Chrome:ChromeDriver (需与 Chrome 浏览器版本匹配)
- Firefox:geckodriver
- Edge:Microsoft Edge WebDriver
最佳实践:使用webdriver-manager手动下载、匹配版本、设置系统路径是新手常见的痛点。我强烈推荐使用webdriver-manager这个 Python 包来自动化管理。它会自动检测你本地安装的浏览器版本,并下载匹配的驱动。 安装它:
pip install webdriver-manager后续在代码中,你可以这样使用(以 Chrome 为例):
from selenium import webdriver from selenium.webdriver.chrome.service import Service from webdriver_manager.chrome import ChromeDriverManager # 自动下载并使用匹配的 ChromeDriver service = Service(ChromeDriverManager().install()) driver = webdriver.Chrome(service=service)这行代码会检查本地是否有合适的 ChromeDriver,没有则自动下载,省去了大量手动配置的麻烦。对于 Firefox 和 Edge,也有对应的GeckoDriverManager和EdgeChromiumDriverManager。
实操心得:在团队协作或 CI/CD(持续集成)环境中,虽然
webdriver-manager很方便,但有时为了环境稳定性和构建速度,我们更倾向于将特定版本的 WebDriver 直接放在项目目录或通过其他方式预置。但对于本地开发和快速启动,webdriver-manager是无敌的。
3. 编写你的第一个 Selenium 测试脚本
现在,让我们告别“纸上谈兵”,动手编写一个实实在在的测试脚本。我们将以访问百度首页并搜索关键词为例。
3.1 基础脚本编写与元素定位
在项目根目录下,创建一个新的 Python 文件,比如first_test.py。
from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.common.keys import Keys from selenium.webdriver.chrome.service import Service from webdriver_manager.chrome import ChromeDriverManager import time # 1. 自动设置 ChromeDriver 服务 service = Service(ChromeDriverManager().install()) # 2. 创建 WebDriver 实例,启动浏览器 driver = webdriver.Chrome(service=service) try: # 3. 打开目标网页 driver.get("https://www.baidu.com") # 等待页面加载(初级做法,后续会优化) time.sleep(2) # 4. 定位搜索框并输入关键词 # 通过元素的 'id' 属性定位,这是最快最稳定的方式之一 search_box = driver.find_element(By.ID, "kw") search_box.send_keys("PyCharm Selenium 自动化测试") # 5. 定位搜索按钮并点击 # 通过元素的 'id' 属性定位按钮 search_button = driver.find_element(By.ID, "su") search_button.click() # 6. 等待搜索结果加载 time.sleep(3) # 7. 简单的断言:检查页面标题或特定结果 # 这里检查标题是否包含关键词(实际测试中应有更严谨的断言) assert "PyCharm" in driver.title print("测试通过!页面标题包含‘PyCharm’。") # 可以进一步定位搜索结果中的第一条,验证其内容 # first_result = driver.find_element(By.CSS_SELECTOR, '#content_left .result h3 a') # print(f"第一条结果标题是:{first_result.text}") except Exception as e: print(f"测试执行出错:{e}") # 这里可以加入截图功能,便于排查问题 driver.save_screenshot('error_screenshot.png') finally: # 8. 等待几秒便于观察,然后关闭浏览器 time.sleep(5) driver.quit()代码解析与定位策略:
- 导入与驱动初始化:使用
webdriver-manager简化了驱动管理。 driver.get(url):这是导航到指定 URL 的标准方法。- 元素定位:这是 Selenium 的核心。我们使用了
By.ID定位器,通过 HTML 元素的id属性(kw和su)来找到搜索框和按钮。id在理想情况下应该是唯一的,定位速度最快。 - 元素操作:
send_keys()用于输入文本,click()用于点击。 - 等待:这里使用了
time.sleep(),这是一种强制等待(硬等待)。它会让脚本无条件暂停指定秒数。在实际项目中,这被视作不良实践,因为它效率低下且不稳定(网络或机器快慢会影响所需时间)。我们马上会优化它。 - 断言:使用 Python 内置的
assert语句进行简单验证。在正式的测试框架(如pytest)中,我们会使用更强大的断言方法。 - 退出:
driver.quit()会关闭浏览器并释放 WebDriver 进程资源。务必在finally块中执行,确保即使测试失败,浏览器也能被关闭,避免残留进程。
3.2 优化等待策略:告别 time.sleep
硬等待是自动化脚本不稳定的主要元凶之一。Selenium 提供了两种智能等待方式:
1. 隐式等待 (Implicit Wait)在创建driver后设置一次,对整个driver的生命周期有效。它告诉 WebDriver 在查找元素时,如果元素没有立即出现,可以轮询 DOM 一段时间(比如10秒),直到找到或超时。
driver.implicitly_wait(10) # 单位:秒注意:隐式等待只对find_element和find_elements这类查找操作有效。对于页面加载、JavaScript 执行完毕等情况无效。
2. 显式等待 (Explicit Wait)这是更强大、更推荐的方式。它允许你为某个特定条件设置等待,条件满足则立即继续,超时则抛出异常。需要配合WebDriverWait和expected_conditions(EC) 使用。
from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC # 等待直到搜索框可见并可交互 wait = WebDriverWait(driver, 10) # 最长等待10秒 search_box = wait.until(EC.element_to_be_clickable((By.ID, "kw"))) search_box.send_keys("优化后的搜索")常用预期条件 (EC):
presence_of_element_located: 元素出现在 DOM 中(不一定可见)。visibility_of_element_located: 元素可见(宽高大于0)。element_to_be_clickable: 元素可见且可点击。title_contains: 页面标题包含特定文本。
最佳实践组合:我个人的习惯是:设置一个较短的全局隐式等待(如5秒)作为兜底,然后在关键交互步骤(如点击按钮后等待新页面/元素)使用显式等待。完全避免使用time.sleep。将上面的脚本优化后,关键部分如下:
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 selenium.webdriver.chrome.service import Service from webdriver_manager.chrome import ChromeDriverManager service = Service(ChromeDriverManager().install()) driver = webdriver.Chrome(service=service) driver.implicitly_wait(5) # 设置全局隐式等待 try: driver.get("https://www.baidu.com") # 显式等待搜索框出现并可交互 wait = WebDriverWait(driver, 10) search_box = wait.until(EC.element_to_be_clickable((By.ID, "kw"))) search_box.send_keys("PyCharm Selenium") search_button = driver.find_element(By.ID, "su") # 隐式等待已生效 search_button.click() # 显式等待搜索结果页的特定元素(例如第一个结果链接)出现 first_result_link = wait.until( EC.presence_of_element_located((By.CSS_SELECTOR, '#content_left .result h3 a')) ) print(f"搜索完成,第一条结果标题是:{first_result_link.text}") assert "PyCharm" in driver.title finally: driver.quit()这样的脚本健壮性大大提升,执行速度也更快。
4. 构建可维护的测试框架:POM 设计与 Pytest 集成
当测试用例越来越多,直接在一个脚本里写所有定位和操作会变得难以维护。我们需要引入设计模式和测试框架。
4.1 页面对象模型 (Page Object Model, POM) 实战
POM 的核心思想是将每个网页封装成一个类(Page Class),页面的元素定位和基本操作作为这个类的方法。测试脚本只调用这些方法,不直接包含定位器。这样,当页面 UI 变化时,你只需要修改对应的 Page Class,而不需要修改大量测试脚本。
让我们用 POM 重构百度搜索的例子。
1. 创建基础页面类 (base_page.py)
# pages/base_page.py from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC class BasePage: """所有页面类的基类,封装通用操作""" def __init__(self, driver): self.driver = driver self.wait = WebDriverWait(driver, 10) def find_element(self, by, locator): """查找单个元素,加入显式等待""" return self.wait.until(EC.presence_of_element_located((by, locator))) def find_elements(self, by, locator): """查找多个元素""" return self.driver.find_elements(by, locator) def click(self, by, locator): """点击元素""" element = self.wait.until(EC.element_to_be_clickable((by, locator))) element.click() def input_text(self, by, locator, text): """向元素输入文本""" element = self.find_element(by, locator) element.clear() element.send_keys(text) def get_title(self): """获取页面标题""" return self.driver.title2. 创建百度首页页面类 (baidu_home_page.py)
# pages/baidu_home_page.py from selenium.webdriver.common.by import By from .base_page import BasePage class BaiduHomePage(BasePage): """百度首页的页面对象""" # 页面元素定位器 (Locators) SEARCH_INPUT = (By.ID, 'kw') SEARCH_BUTTON = (By.ID, 'su') def __init__(self, driver): super().__init__(driver) self.driver.get("https://www.baidu.com") def search(self, keyword): """执行搜索操作""" self.input_text(*self.SEARCH_INPUT, keyword) # 解包元组 self.click(*self.SEARCH_BUTTON) # 返回搜索结果页的页面对象,实现页面跳转的链式调用 from .baidu_result_page import BaiduResultPage return BaiduResultPage(self.driver)3. 创建百度结果页页面类 (baidu_result_page.py)
# pages/baidu_result_page.py from selenium.webdriver.common.by import By from .base_page import BasePage class BaiduResultPage(BasePage): """百度搜索结果页的页面对象""" FIRST_RESULT_LINK = (By.CSS_SELECTOR, '#content_left .result h3 a') def get_first_result_text(self): """获取第一条搜索结果的文本""" element = self.find_element(*self.FIRST_RESULT_LINK) return element.text4. 使用 POM 的测试脚本 (test_baidu_search.py)
# tests/test_baidu_search.py import pytest from selenium import webdriver from selenium.webdriver.chrome.service import Service from webdriver_manager.chrome import ChromeDriverManager from pages.baidu_home_page import BaiduHomePage class TestBaiduSearch: """测试百度搜索功能""" @pytest.fixture(scope="class") def driver(self): """Fixture: 为整个测试类提供共享的 driver""" service = Service(ChromeDriverManager().install()) driver = webdriver.Chrome(service=service) driver.implicitly_wait(5) yield driver # 测试执行时使用这个 driver driver.quit() # 所有测试结束后退出 def test_search_functionality(self, driver): """测试基本搜索功能""" home_page = BaiduHomePage(driver) result_page = home_page.search("PyCharm Selenium") first_result_text = result_page.get_first_result_text() print(f"实际结果: {first_result_text}") # 使用 pytest 的断言 assert "PyCharm" in first_result_text or "Selenium" in first_result_text assert "PyCharm" in driver.title def test_empty_search(self, driver): """测试空搜索(应停留在首页)""" home_page = BaiduHomePage(driver) # 不输入关键词直接点击搜索 home_page.click(*home_page.SEARCH_BUTTON) # 验证是否仍为百度首页(通过URL或标题判断) assert "baidu.com" in driver.current_url现在,测试脚本变得非常清晰,只关注“做什么”(测试逻辑),而“怎么做”(页面交互)被封装在 Page 类中。UI 变更时,只需修改对应的 Page 类文件。
4.2 集成 Pytest 测试框架
pytest是 Python 最流行的测试框架之一,它比unittest更简洁、功能更强大。我们已经在上面的例子中使用了它(@pytest.fixture)。
安装与配置:
pip install pytest pytest-htmlpytest-html用于生成漂亮的 HTML 测试报告。
运行测试:在 PyCharm 的 Terminal 中,进入项目根目录,运行:
pytest tests/ -v --html=reports/report.html --self-contained-html-v: 显示详细输出。--html=reports/report.html: 生成 HTML 报告到reports目录。--self-contained-html: 将 CSS 等资源内嵌到 HTML 中,生成单个文件报告。
使用 PyCharm 运行/调试:PyCharm 完美支持pytest。右键点击测试文件或测试类/方法,选择Run 'pytest in test_...'或Debug 'pytest in test_...'。你可以在代码中设置断点,使用强大的调试器逐步执行,查看变量状态,这对于排查复杂的定位或逻辑问题至关重要。
conftest.py全局配置:在项目根目录创建conftest.py,可以定义全局的fixture,供所有测试文件使用。例如,将driver的初始化放到这里:
# conftest.py import pytest from selenium import webdriver from selenium.webdriver.chrome.service import Service from webdriver_manager.chrome import ChromeDriverManager @pytest.fixture(scope="function") # 改为每个测试函数一个 driver def driver(): """为每个测试提供一个全新的浏览器实例""" service = Service(ChromeDriverManager().install()) driver = webdriver.Chrome(service=service) driver.implicitly_wait(5) driver.maximize_window() # 默认最大化窗口 yield driver driver.quit()然后,测试文件就可以直接使用driver这个 fixture 了,无需自己定义。
5. PyCharm 高效工作流与高级技巧
掌握了基础框架后,让我们利用 PyCharm 的特性来进一步提升效率。
5.1 利用 PyCharm 的 Selenium 插件与 Live Templates
PyCharm 专业版内置了强大的Test Automation插件(社区版可通过安装插件获得部分功能),它可以直接在 IDE 内录制和回放 Web 操作,并生成 Selenium 代码。虽然我不推荐完全依赖录制(生成的代码通常不够健壮和优雅),但它是一个绝佳的学习和元素定位辅助工具。
更实用的是 Live Templates(代码模板):你可以创建自定义的代码片段。例如,创建一个名为sel_find的模板,用于快速生成带显式等待的元素定位代码:
File->Settings->Editor->Live Templates。- 点击
+,选择Live Template。 - Abbreviation(缩写)填
sel_find,Description 填Selenium find element with wait。 - 在 Template text 区域输入:
(element = self.wait.until(EC.element_to_be_clickable((By.$LOCATOR$, "$VALUE$")))$LOCATOR$和$VALUE$是变量) - 点击
Define,选择Python。 - 点击
Edit variables,可以为LOCATOR设置一个预定义列表(如ID,NAME,CSS_SELECTOR,XPATH)。
这样,在代码中输入sel_find然后按 Tab 键,就能快速生成代码片段并跳转到变量处编辑。
5.2 运行配置与参数化测试
创建专用的运行配置:你可以为pytest创建固定的运行配置,避免每次在终端输入长命令。
- 点击 PyCharm 右上角运行配置下拉菜单 ->
Edit Configurations。 - 点击
+->Python tests->pytest。 - 在
Target选择Custom,并填写tests/(或特定文件)。 - 在
Additional arguments中添加-v --html=reports/report.html --self-contained-html。 - 可以设置环境变量、工作目录等。
参数化测试:pytest的@pytest.mark.parametrize装饰器可以让你用不同的数据运行同一个测试逻辑,非常适用于数据驱动测试。
import pytest class TestSearchWithData: @pytest.mark.parametrize("keyword, expected_in_title", [ ("Python", "Python"), ("自动化测试", "百度一下"), ("PyCharm", "PyCharm"), ]) def test_search_with_multiple_keywords(self, driver, keyword, expected_in_title): home_page = BaiduHomePage(driver) result_page = home_page.search(keyword) assert expected_in_title in driver.title运行这个测试,pytest会自动执行三次,每次使用一组参数。
5.3 调试与问题排查实战
自动化测试脚本失败是家常便饭。PyCharm 的调试器是你的最佳伙伴。
常见问题与排查步骤:
NoSuchElementException(找不到元素)- 原因:定位器写错了;元素在 iframe 内;元素尚未加载出来。
- 排查:
- 使用浏览器开发者工具复核:在页面右键“检查”,使用
Ctrl+F在 Elements 面板搜索你的定位器(如#kw)。 - 检查 iframe:如果元素在
iframe里,需要先用driver.switch_to.frame(frame_element)切换进去。 - 增加/调整等待:将
presence_of_element_located改为visibility_of_element_located或element_to_be_clickable,并适当增加等待时间。 - 调试时截图:在出错代码前加入
driver.save_screenshot('debug.png'),查看截图确认页面状态。
- 使用浏览器开发者工具复核:在页面右键“检查”,使用
ElementNotInteractableException(元素不可交互)- 原因:元素被遮挡、禁用、或者不可见。
- 排查:
- 等待元素可点击:使用
EC.element_to_be_clickable。 - 滚动到元素:使用
driver.execute_script("arguments[0].scrollIntoView(true);", element)将元素滚动到视口中。 - 检查覆盖层:是否有模态框(Modal)、弹窗遮挡了目标元素。
- 等待元素可点击:使用
测试在 IDE 中能跑,在命令行或 CI 中失败
- 原因:环境差异,如浏览器窗口大小、屏幕分辨率、加载速度。
- 排查:
- 统一浏览器选项:在创建
driver时添加固定选项。
from selenium.webdriver.chrome.options import Options options = Options() options.add_argument('--headless') # 无头模式,不显示GUI,常用于CI options.add_argument('--disable-gpu') options.add_argument('--window-size=1920,1080') # 固定窗口大小 options.add_argument('--no-sandbox') # Linux CI 环境常用 options.add_argument('--disable-dev-shm-usage') # 解决 Docker 内存不足问题 driver = webdriver.Chrome(service=service, options=options)- 检查依赖版本:确保 CI 环境中的
selenium,webdriver-manager, 浏览器版本与本地一致。使用requirements.txt固定版本:pip freeze > requirements.txt。
- 统一浏览器选项:在创建
使用 PyCharm 调试器:
- 在可能出错的代码行左侧点击设置断点(红点)。
- 右键测试方法,选择
Debug。 - 当执行到断点时,程序暂停。你可以在
Variables窗口查看所有变量值,在Watches窗口添加表达式进行求值,使用Step Over (F8),Step Into (F7)逐行执行。 - 特别有用的是,你可以在调试控制台(Debugger Console)中直接执行 Selenium 命令,实时探索页面,比如尝试不同的定位器,而无需修改代码重新运行。
6. 进阶:融入持续集成与日志报告
一个成熟的工作流离不开自动化执行和结果反馈。
6.1 生成丰富的测试报告
除了pytest-html,pytest还有强大的pytest-html插件可以定制报告,或者使用allure-pytest生成更美观的 Allure 报告。
pip install allure-pytest运行测试并生成 Allure 结果数据:
pytest tests/ -v --alluredir=./allure-results然后使用 Allure 命令行工具生成 HTML 报告(需要额外安装 Allure Commandline)。
6.2 集成日志系统
使用 Python 标准库的logging模块记录测试执行过程,便于排查问题。
# utils/logger.py import logging import os from datetime import datetime def setup_logger(name, log_level=logging.INFO): """设置并返回一个logger""" # 创建 logs 目录 log_dir = "logs" if not os.path.exists(log_dir): os.makedirs(log_dir) # 创建 logger logger = logging.getLogger(name) logger.setLevel(log_level) # 避免重复添加 handler if not logger.handlers: # 创建文件 handler,按日期命名 log_file = os.path.join(log_dir, f"test_{datetime.now().strftime('%Y%m%d')}.log") file_handler = logging.FileHandler(log_file, encoding='utf-8') file_handler.setLevel(log_level) # 创建控制台 handler console_handler = logging.StreamHandler() console_handler.setLevel(log_level) # 设置格式 formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') file_handler.setFormatter(formatter) console_handler.setFormatter(formatter) # 添加 handler logger.addHandler(file_handler) logger.addHandler(console_handler) return logger # 在 conftest.py 或测试中引入 # logger = setup_logger(__name__) # logger.info("开始执行测试...")6.3 融入 CI/CD 流水线
你可以将这套测试框架集成到 Jenkins、GitLab CI、GitHub Actions 等持续集成工具中。核心步骤通常包括:
- 检出代码。
- 设置 Python 环境(如
actions/setup-python@v4)。 - 安装依赖:
pip install -r requirements.txt。 - 安装浏览器:在 CI 环境中安装 Chrome 或 Firefox(通常使用无头模式)。
- 运行测试:
pytest tests/ --html=report.html ...。 - 收集产物:将测试报告、日志、截图作为构建产物保存或发布。
一个简单的 GitHub Actions 工作流示例 (.github/workflows/test.yml):
name: Python Selenium Tests 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: | 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 # 使用 webdriver-manager,无需单独安装 ChromeDriver - name: Run tests with pytest run: | pytest tests/ -v --html=reports/report.html --self-contained-html - name: Upload test report uses: actions/upload-artifact@v3 if: always() # 即使测试失败也上传报告 with: name: html-report path: reports/从在 PyCharm 中点击运行第一个脚本,到构建出这样一个能在云端自动执行、反馈结果的完整工作流,你已经跨越了从“写脚本”到“做工程”的关键一步。这个过程里,最深的体会是,工具和框架是为你服务的,核心永远是清晰的测试设计、稳定的元素定位和良好的代码结构。PyCharm 和 Selenium 的组合,提供了一个从探索、开发到调试、集成的完美环境,让你能更专注于测试逻辑本身,而不是环境问题。最后一个小建议,定期回顾和重构你的 Page Object 和测试用例,就像维护产品代码一样维护你的自动化代码,它的价值才会随着时间增长,而不是变成一堆难以维护的“遗产脚本”。
