1. 项目概述:为什么选择Python+Selenium+PyCharm这套组合拳?

如果你正在为Web应用的回归测试、兼容性测试或者数据抓取而头疼,手动点点点不仅效率低下,还容易出错,那么自动化测试就是你的解药。而在众多自动化方案里,Python + Selenium + PyCharm 这套组合,可以说是从新手到老手都绕不开的“黄金搭档”。我从业十多年,从早期的QTP到后来的各种测试框架都用过,最终在团队里大规模落地并稳定运行的,还是这套组合。它最大的魅力在于“平衡”——Python的简洁语法降低了学习门槛,Selenium提供了强大且标准的浏览器操控能力,而PyCharm作为专业的Python IDE,其调试和项目管理功能能让你的自动化脚本开发效率提升好几个档次。

简单来说,这个项目就是教你如何搭建一个高效、可维护的Web自动化测试环境,并写出健壮的测试脚本。它适合测试工程师、开发人员(尤其是后端或全栈,需要自测前端交互)、以及任何需要通过程序与网页进行重复交互的人。即使你之前没写过代码,跟着这篇教程一步步走,也能亲手实现一个自动登录网站、填写表单的“机器人”。接下来,我会拆解每一个环节,不仅告诉你怎么做,更会解释为什么这么做,以及我在实际项目中踩过的那些坑。

2. 环境搭建与核心工具选型解析

工欲善其事,必先利其器。环境搭建是第一步,也是最容易让新手卡住的地方。很多人在这里放弃,不是因为步骤多复杂,而是不理解每一步的作用,一旦出错就无从下手。我会带你捋清脉络,确保你的环境一次配好。

2.1 Python安装:版本选择与路径配置的学问

首先,你需要安装Python。去Python官网下载安装包,这里第一个关键选择就来了:选Python 3的哪个版本?我的建议是, 不要追求最新,选择当前被广泛支持且稳定的版本 ,比如Python 3.8到3.11之间的某个版本。Python 3.12+可能对一些第三方库的兼容性还不够完善,而Python 2.7早已停止维护,绝对不要用。

安装时,务必勾选 “Add Python to PATH” 这个选项。这是很多新手忽略的致命一步。它的作用是把Python和pip(Python的包管理工具)的路径添加到系统环境变量中。勾选后,你才能在命令行(CMD或PowerShell)的任何位置直接输入 python pip 命令。如果不小心忘了勾选,后续就需要手动配置环境变量,对新手来说比较麻烦。

安装完成后,验证一下。打开命令行,输入 python --version 。如果正确显示版本号,比如 Python 3.10.11 ,说明安装成功。同时输入 pip --version ,确认pip也已就绪。

注意 :有些电脑上可能同时存在多个Python版本(比如系统自带的Python 2.7和你刚装的Python 3.10)。这时,在命令行输入 python 可能默认启动的是旧版本。你可以尝试使用 python3 命令,或者通过修改环境变量顺序来调整。更稳妥的做法是后续在PyCharm中为项目指定解释器。

2.2 PyCharm的选择与初始化设置

接下来是集成开发环境(IDE)。为什么强烈推荐PyCharm而不是简单的文本编辑器(如VSCode)?因为自动化测试不仅仅是写代码,还涉及到项目管理、依赖库管理、强大的调试(断点、变量查看、步进执行)以及对Selenium脚本运行时的浏览器状态监控。PyCharm在这些方面做得非常出色。

PyCharm有 专业版(Professional) 社区版(Community) 。对于纯Python开发和Web自动化测试, 社区版完全够用 ,而且是免费的。专业版主要额外支持Web框架(如Django)、数据库工具等,如果你不做Web开发,没必要折腾激活码。直接去JetBrains官网下载社区版安装即可。

安装后首次运行,有几个设置建议你调整:

  1. 主题与字体 :选择一个你看着舒服的配色方案(如Darcula深色主题)并调整编辑器字体大小(我一般用Consolas, 14号),保护眼睛。
  2. 解释器配置 :这是核心。创建新项目时,PyCharm会让你选择“New Environment”还是“Existing interpreter”。建议选择“Existing interpreter”,然后指向你刚才安装的Python解释器路径(例如 C:\Users\你的用户名\AppData\Local\Programs\Python\Python310\python.exe )。这样能避免为每个项目创建独立的虚拟环境(虽然虚拟环境是更佳实践,但对纯新手来说,先用全局环境跑通流程更直观)。
  3. 安装Selenium库 :在PyCharm中,打开底部工具栏的“Terminal”(终端)。它会自动进入你的项目目录。在这里输入命令 pip install selenium 并回车。PyCharm的终端集成了系统命令行,并且环境变量已经配置好,在这里安装的包直接作用于当前项目。

2.3 浏览器驱动的下载与配置:最常出错的环节

Selenium本身是一个控制浏览器的“遥控器”,但它需要对应的“驱动程序(Driver)”才能与具体的浏览器(如Chrome、Firefox)对话。这是新手遇到问题最多的环节。

以最常用的Chrome浏览器为例:

  1. 查看你的Chrome版本 :打开Chrome,点击右上角三个点 -> 帮助 -> 关于Google Chrome。记下版本号,例如 114.0.5735.199
  2. 下载对应版本的ChromeDriver :访问ChromeDriver官方下载站。这里的关键是 版本匹配 。你的ChromeDriver主版本号必须与Chrome浏览器的主版本号完全一致。例如,Chrome是114版,你就必须下载114.x.x.x版本的ChromeDriver。下载对应你操作系统的文件(Windows一般是 chromedriver_win32.zip )。
  3. 放置驱动文件 :将下载的ZIP包解压,得到一个 chromedriver.exe 文件。你有三种放置方式,我推荐第一种:
    • (推荐)放在Python安装目录的Scripts文件夹下 :例如 C:\Users\你的用户名\AppData\Local\Programs\Python\Python310\Scripts\ 。因为这个路径通常已经在系统的PATH环境变量里,Selenium可以自动找到。
    • 放在项目根目录下 :这样需要在代码中指定驱动路径。
    • 放在任意位置,并在代码中指定绝对路径 :最灵活,但代码可移植性差。

验证驱动是否可用:在PyCharm的Terminal中,先进入驱动所在目录,然后输入 chromedriver 。如果出现类似 Starting ChromeDriver... 的信息,没有报错,说明驱动没问题,按Ctrl+C退出即可。

实操心得 :浏览器会自动更新,但ChromeDriver不会。经常发生某天你的脚本突然报错,提示“Chrome版本与驱动不匹配”。这就是因为Chrome自动升级了。解决办法是定期检查并更新ChromeDriver。你可以写一个简单的检查脚本,或者更简单地,使用 webdriver-manager 这个第三方库,它能自动下载和管理匹配的浏览器驱动,强烈推荐在后续进阶中使用。

3. 第一个自动化脚本:从登录案例理解核心API

环境准备好了,我们来写第一个真正的自动化脚本。我选择一个经典的“登录”场景作为例子,因为它涵盖了打开浏览器、访问URL、定位元素、交互操作、断言验证等核心步骤。

3.1 脚本骨架与基础流程

在PyCharm中新建一个Python文件,比如叫 first_test.py 。我们将一步步构建代码。

# 1. 导入必要的模块
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
import time

# 2. 创建WebDriver实例,启动浏览器
driver = webdriver.Chrome()  # 如果驱动不在PATH,需指定路径:webdriver.Chrome(executable_path=r‘你的路径\chromedriver.exe’)

# 3. 控制浏览器窗口(可选)
driver.maximize_window()  # 最大化窗口,确保元素可见

# 4. 打开目标网页
driver.get("https://www.example.com/login")  # 替换成你要测试的登录页地址

# 5. 定位页面元素并操作
# 假设登录页有两个输入框,id分别为‘username’和‘password’,一个登录按钮id为‘submit’
username_input = driver.find_element(By.ID, "username")
password_input = driver.find_element(By.ID, "password")
login_button = driver.find_element(By.ID, "submit")

# 在输入框中输入内容
username_input.send_keys("your_username")
password_input.send_keys("your_password")

# 点击登录按钮
login_button.click()

# 6. 添加等待,并验证结果
time.sleep(3)  # 强制等待3秒,等待页面跳转(这是一种简单但不推荐的方式,后面会讲更好的)
# 验证是否登录成功,例如检查页面是否出现用户昵称元素
try:
    welcome_text = driver.find_element(By.CLASS_NAME, "welcome-message").text
    if "your_username" in welcome_text:
        print("登录成功!")
    else:
        print("登录状态异常。")
except Exception as e:
    print(f"未找到欢迎信息,登录可能失败: {e}")

# 7. 关闭浏览器
driver.quit()

逐行解析:

  • from selenium import webdriver :导入Selenium的核心类。
  • webdriver.Chrome() :这个语句会启动一个全新的、干净的Chrome浏览器实例。你会在桌面上看到它弹出来。
  • driver.get(url) :命令浏览器导航到指定网址。
  • find_element(By.ID, "id_value") :这是 元素定位 ,是Selenium自动化最核心的技能。这里用的是通过HTML元素的 id 属性来定位, id 通常是唯一的,定位最准确。
  • send_keys(“text”) :向输入框(或任何可输入的元素)模拟键盘输入。
  • click() :模拟鼠标点击。
  • time.sleep(3) :让程序暂停(阻塞)3秒。这是一个 糟糕的实践 ,但在第一个脚本里为了简单演示,我们先这么用。在实际项目中,必须用更智能的“显式等待”。
  • driver.quit() :关闭浏览器窗口并结束WebDriver进程。务必用 quit() 而不是 close() close() 只关闭当前标签页。

3.2 元素定位的八种武器与选择策略

上面我们用到了 By.ID ,这是最理想的定位方式。但现实中的网页元素往往没有 id ,或者 id 是动态生成的。Selenium提供了多达8种定位策略,你需要根据实际情况选择最稳定的一种。

定位方式 示例代码 适用场景与优缺点
ID find_element(By.ID, “loginBtn”) 首选 。ID唯一,定位最快最准。
Name find_element(By.NAME, “username”) 次选。Name属性也常用于表单元素,但可能不唯一。
Class Name find_element(By.CLASS_NAME, “btn-primary”) 用于通过CSS类定位。但一个元素常有多个类,且类名常被复用,稳定性一般。
Tag Name find_element(By.TAG_NAME, “input”) 通过标签名定位,如 <input> , <a> 。通常用于找一组同类元素。
Link Text find_element(By.LINK_TEXT, “忘记密码?”) 专用于超链接 ,通过链接的完整文本定位。
Partial Link Text find_element(By.PARTIAL_LINK_TEXT, “密码”) 通过链接的部分文本定位,比Link Text更灵活。
XPath find_element(By.XPATH, “//input[@name=‘email’]”) 万能但复杂 。可以定位页面任何元素,路径可绝对可相对。功能强大,但表达式易读性差,且对页面结构变化敏感。
CSS Selector find_element(By.CSS_SELECTOR, “#container .btn”) 推荐 。语法简洁,定位速度通常比XPath快,且是现代前端开发熟悉的方式。功能同样强大。

定位策略选择的心得

  1. 优先级 :ID > Name > CSS Selector > XPath > 其他。能不用XPath尽量不用,除非CSS Selector无法实现(如用文本内容定位)。
  2. 绝对避免 :使用包含索引位置的XPath(如 /html/body/div[3]/div[2]/form/input[1] ),页面结构稍改脚本就崩溃。
  3. 相对路径与属性结合 :使用相对XPath或CSS Selector,并结合元素的稳定属性(如 name , data-testid )。例如: //form[@id=‘loginForm’]//input[@type=‘submit’] #loginForm input[type=‘submit’]
  4. 利用浏览器开发者工具 :在Chrome中右键点击页面元素,选择“检查”,在Elements面板中,右键该元素,可以选择“Copy” -> “Copy selector” 或 “Copy XPath”。这是一个很好的起点,但 不要直接使用 ,要检查其是否简洁稳定。

3.3 等待机制:告别 time.sleep ,拥抱智能等待

time.sleep(seconds) 是“强制等待”,它不管页面是否加载完成、元素是否出现,都死等指定的时间。这会造成两种问题:如果时间设短了,元素还没出来就去操作,会报错;如果设长了,大量浪费执行时间,降低测试效率。

Selenium提供了两种更优的等待方式:

  • 隐式等待(Implicit Wait) :设置一个全局的超时时间。在查找任何元素时,如果元素没有立即出现,WebDriver会轮询查找直到超时。只需设置一次。
    driver.implicitly_wait(10)  # 单位是秒
    
  • 显式等待(Explicit Wait) :针对某个特定条件进行等待,条件满足则立即继续,超时则抛出异常。更精确、更灵活,是 推荐的最佳实践
    from selenium.webdriver.support.ui import WebDriverWait
    from selenium.webdriver.support import expected_conditions as EC
    
    # 等待直到“登录成功”的元素出现,最多等10秒
    try:
        element = WebDriverWait(driver, 10).until(
            EC.presence_of_element_located((By.ID, “welcomeMessage”))
        )
        print(“登录成功元素已加载!”)
    except TimeoutException:
        print(“等待超时,登录可能失败或元素未找到。”)
    

最佳实践 :通常,我会在脚本开头设置一个较短的隐式等待(如5秒)作为兜底,然后在关键步骤(如点击按钮后的页面跳转、异步加载的内容)使用显式等待。完全避免使用 time.sleep

4. 构建可维护的自动化测试框架

当你的测试脚本超过10个,你就会发现到处是重复代码(如启动/关闭浏览器、登录操作)、硬编码的测试数据、以及散落各处的定位器。这时,就需要引入一些设计模式和框架思想来提升代码的可维护性和可读性。

4.1 Page Object Model (POM):页面对象设计模式

POM是UI自动化测试的 基石性设计模式 。其核心思想是将 页面 抽象成一个 类(Class) ,将页面上的 元素定位器 操作这些元素的方法 封装在这个类里。测试脚本(用例)则通过调用页面对象的方法来与页面交互。

好处

  • 代码复用 :相同的页面操作(如登录)写一次,所有测试用例都能调用。
  • 易于维护 :当页面UI变化(如某个按钮的id改了),你只需要去对应的Page类里修改一次定位器,所有用到这个按钮的测试用例都自动生效。
  • 可读性强 :测试用例读起来像自然语言,例如 login_page.enter_username(“admin”)

一个简单的登录页面对象示例

# login_page.py
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

class LoginPage:
    # 1. 定义页面元素定位器(Locators)
    USERNAME_INPUT = (By.ID, “username”)
    PASSWORD_INPUT = (By.ID, “password”)
    LOGIN_BUTTON = (By.ID, “submit”)
    ERROR_MESSAGE = (By.CLASS_NAME, “alert-error”)

    def __init__(self, driver):
        self.driver = driver
        self.wait = WebDriverWait(driver, 10)

    # 2. 封装页面操作行为(Actions)
    def enter_username(self, username):
        # 使用显式等待确保元素可交互
        username_field = self.wait.until(EC.element_to_be_clickable(self.USERNAME_INPUT))
        username_field.clear()
        username_field.send_keys(username)
        return self  # 支持链式调用

    def enter_password(self, password):
        password_field = self.wait.until(EC.element_to_be_clickable(self.PASSWORD_INPUT))
        password_field.clear()
        password_field.send_keys(password)
        return self

    def click_login(self):
        login_btn = self.wait.until(EC.element_to_be_clickable(self.LOGIN_BUTTON))
        login_btn.click()

    def get_error_message(self):
        try:
            return self.driver.find_element(*self.ERROR_MESSAGE).text
        except:
            return None

    # 3. 封装一个完整的业务场景
    def login(self, username, password):
        self.enter_username(username)
        self.enter_password(password)
        self.click_login()

在测试用例中使用页面对象

# test_login.py
import pytest
from login_page import LoginPage

def test_valid_login(driver):  # 假设driver通过fixture提供
    login_page = LoginPage(driver)
    login_page.login(“correct_user”, “correct_pass”)
    # 断言:验证登录后跳转到了主页或出现欢迎信息
    assert “Dashboard” in driver.title

def test_invalid_login(driver):
    login_page = LoginPage(driver)
    login_page.login(“wrong_user”, “wrong_pass”)
    error_msg = login_page.get_error_message()
    assert error_msg is not None
    assert “用户名或密码错误” in error_msg

4.2 数据驱动测试:分离测试数据与脚本逻辑

测试数据(如用户名、密码、搜索关键词)不应该硬编码在测试脚本里。数据驱动测试(DDT)将测试数据外部化(如存放在CSV、JSON、Excel或YAML文件中),测试脚本读取这些数据来执行测试。

使用 pytest 和参数化实现数据驱动 pytest 是Python最流行的测试框架之一,它内置了强大的参数化功能。

# test_data_driven.py
import pytest
from login_page import LoginPage

# 将测试数据定义在装饰器里
@pytest.mark.parametrize(“username, password, expected_result”, [
    (“admin”, “admin123”, “success”),
    (“”, “admin123”, “empty_username”),
    (“admin”, “”, “empty_password”),
    (“wrong”, “wrong”, “failure”),
])
def test_login_with_data(driver, username, password, expected_result):
    login_page = LoginPage(driver)
    login_page.login(username, password)

    if expected_result == “success”:
        assert “Dashboard” in driver.title
    elif expected_result in [“empty_username”, “empty_password”, “failure”]:
        error_msg = login_page.get_error_message()
        assert error_msg is not None
        # 可以根据expected_result进一步断言具体的错误信息

更进阶的做法 :从外部文件(如 login_data.json )读取测试数据,使管理和维护大量测试用例数据变得更加方便。

4.3 测试报告与日志:让结果一目了然

脚本跑完了,是成是败需要清晰的记录。除了PyCharm自带的测试运行器输出,我们通常需要更美观、更详细的HTML报告,方便归档和分享。

使用 pytest-html 插件生成报告

  1. 安装: pip install pytest-html
  2. 运行测试时生成报告: pytest test_login.py --html=report.html --self-contained-html 这会生成一个独立的 report.html 文件,用浏览器打开,可以看到清晰的测试结果汇总、通过/失败详情、甚至每个步骤的截图(需配合其他插件)。

集成 Allure 框架生成更强大的报告 Allure 能生成非常专业、交互性强的测试报告,展示测试套件、用例层级、步骤详情、附件(截图、日志)等。

  1. 安装: pip install allure-pytest
  2. 运行测试: pytest test_login.py --alluredir=./allure-results
  3. 生成报告: allure serve ./allure-results (需要先安装Allure命令行工具)

添加日志记录 : 使用Python内置的 logging 模块,在关键步骤记录信息、警告和错误,有助于调试失败的测试。

import logging
logging.basicConfig(level=logging.INFO, format=‘%(asctime)s - %(levelname)s - %(message)s’)
logger = logging.getLogger(__name__)

def click_element(self, locator):
    try:
        element = self.wait.until(EC.element_to_be_clickable(locator))
        element.click()
        logger.info(f“成功点击元素: {locator}”)
    except TimeoutException:
        logger.error(f“等待元素可点击超时: {locator}”)
        raise

5. 高级技巧与实战避坑指南

掌握了基础框架后,一些高级技巧和“坑”的应对能让你脚本的稳定性和专业性再上一个台阶。

5.1 处理弹窗、iframe与多窗口

  • JavaScript弹窗(Alert/Confirm/Prompt)

    from selenium.webdriver.common.alert import Alert
    alert = Alert(driver)
    print(alert.text)  # 获取弹窗文本
    alert.accept()      # 点击“确定”
    # alert.dismiss()   # 点击“取消”
    # alert.send_keys(“text”) # 向Prompt弹窗输入文本
    
  • iframe(内嵌框架) :操作iframe内的元素前,必须先切换到对应的iframe。

    # 通过id或name切换
    driver.switch_to.frame(“iframe_id”)
    # 操作iframe内的元素...
    # 操作完成后切回主文档
    driver.switch_to.default_content()
    
  • 多窗口/多标签页

    main_window = driver.current_window_handle  # 获取当前窗口句柄
    # 点击某个打开新窗口的链接...
    all_windows = driver.window_handles  # 获取所有窗口句柄
    new_window = [window for window in all_windows if window != main_window][0]
    driver.switch_to.window(new_window)  # 切换到新窗口
    # 在新窗口操作...
    driver.close()  # 关闭新窗口
    driver.switch_to.window(main_window)  # 切回原窗口
    

5.2 执行JavaScript与处理复杂交互

有些操作通过Selenium标准API很难或无法实现,比如滚动到页面底部、修改元素属性、执行复杂的拖拽。这时可以直接注入并执行JavaScript。

# 滚动到页面底部
driver.execute_script(“window.scrollTo(0, document.body.scrollHeight);”)

# 滚动到某个元素可见
element = driver.find_element(By.ID, “some-element”)
driver.execute_script(“arguments[0].scrollIntoView(true);”, element)

# 修改元素属性(例如,让一个隐藏的元素显示出来)
driver.execute_script(“document.getElementById(‘hiddenElem’).style.display = ‘block’;”)

# 处理富文本编辑器(如CKEditor, TinyMCE)
# 通常需要先切换到编辑器的iframe,然后通过JS直接设置内容
iframe = driver.find_element(By.TAG_NAME, “iframe”)
driver.switch_to.frame(iframe)
editor_body = driver.find_element(By.TAG_NAME, “body”)
driver.execute_script(“arguments[0].innerHTML = arguments[1];”, editor_body, “<p>这是新内容</p>”)
driver.switch_to.default_content()

5.3 常见问题排查与调试技巧

  1. 元素找不到(NoSuchElementException)

    • 检查定位器 :用浏览器开发者工具确认定位器是否正确,是否唯一。
    • 检查等待 :元素是否还没加载出来?增加隐式/显式等待时间。
    • 检查iframe :目标元素是否在iframe里?需要先切换。
    • 检查页面是否刷新/跳转 :在 find_element 之前页面是否发生了跳转,导致之前的元素引用失效?
  2. 元素不可交互(ElementNotInteractableException)

    • 元素被遮挡 :可能有弹窗、悬浮层盖住了目标元素。尝试关闭遮挡物或滚动页面。
    • 元素未可见/未启用 :使用 EC.element_to_be_clickable 条件等待,它综合了“可见”和“可点击”状态。
    • 需要滚动到视图 :元素在页面可视区域外,先滚动到元素位置再操作。
  3. 脚本在IDE里运行正常,但在命令行或CI服务器上失败

    • 浏览器驱动版本不匹配 :CI服务器上的浏览器版本可能和本地不同。使用 webdriver-manager 自动匹配。
    • 无头(Headless)模式差异 :CI服务器通常以无头模式运行(不显示UI)。有些网页在无头模式下行为可能不同。在本地先用无头模式测试一遍。
    • 路径问题 :确保CI服务器上驱动文件的路径正确,或者驱动已加入PATH。
    • 资源加载超时 :CI服务器网络或资源可能较慢,适当增加页面加载和元素等待的超时时间。
  4. 使用PyCharm进行调试

    • 设置断点 :在代码行号左侧点击,出现红点。
    • 调试运行 :右键脚本文件或测试函数,选择“Debug”,而不是“Run”。
    • 查看变量 :在调试面板可以查看所有变量的当前值。
    • 步进执行 :使用步进(Step Over/Into)按钮,一行行执行代码,观察浏览器状态和变量变化,这是定位复杂问题最有效的手段。

5.4 持续集成(CI)集成初步

将自动化测试集成到CI/CD流水线(如Jenkins, GitLab CI, GitHub Actions)中,可以实现每次代码提交后自动运行测试,及时反馈问题。

一个简单的GitHub Actions配置示例( .github/workflows/run_tests.yml ):

name: Python Web UI Tests
on: [push, pull_request]
jobs:
  test:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v2
    - name: Set up Python
      uses: actions/setup-python@v2
      with:
        python-version: ‘3.10’
    - name: Install dependencies
      run: |
        pip install -r requirements.txt
        pip install pytest pytest-html
    - 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
        CHROME_VERSION=$(google-chrome --version | cut -d ‘ ‘ -f3 | cut -d ‘.’ -f1)
        wget -q “https://chromedriver.storage.googleapis.com/LATEST_RELEASE_$CHROME_VERSION”
        LATEST_VERSION=$(cat LATEST_RELEASE_$CHROME_VERSION)
        wget “https://chromedriver.storage.googleapis.com/$LATEST_VERSION/chromedriver_linux64.zip”
        unzip chromedriver_linux64.zip
        sudo mv chromedriver /usr/local/bin/
    - name: Run tests with headless Chrome
      run: |
        # 设置一个环境变量,让Chrome在无头模式下运行
        export PYTEST_ADDOPTS=“--html=report.html --self-contained-html”
        python -m pytest tests/ --headless
    - name: Upload test report
      uses: actions/upload-artifact@v2
      with:
        name: test-report
        path: report.html

这个工作流会在每次推送代码时,在一个干净的Ubuntu环境中安装Python、Chrome、ChromeDriver、依赖包,然后以无头模式运行你的测试,并生成HTML报告供下载查看。

更多推荐