1. 项目概述:一个自动化测试与部署的实战起点
最近在折腾一个很有意思的项目,叫“tools.simonwillison.net测试与部署”。这名字听起来可能有点具体,但它本质上是一个绝佳的实战案例,完美诠释了如何将现代前端项目的自动化测试与持续部署流程串联起来。简单来说,这个项目就是要把一个网站(tools.simonwillison.net)的代码变更、自动化测试和最终上线发布,全部交给机器自动完成,实现“提交即测试,通过即部署”的 DevOps 理想状态。
这个项目的核心价值在于,它不是一个空泛的理论教程,而是一个真实的、可复现的工程实践。无论你是前端开发者、测试工程师,还是对 DevOps 感兴趣的运维同学,都能从中窥见一套高效、可靠的自动化工作流是如何搭建起来的。它解决了开发中最常见的痛点:手动测试耗时费力、部署过程容易出错、不同环境结果不一致。通过自动化,我们能把宝贵的时间从重复劳动中解放出来,专注于更有创造性的工作,同时极大地提升代码质量和发布信心。
整个流程的基石是两大工具:Playwright 和 GitHub Actions。Playwright 是一个强大的浏览器自动化测试框架,由微软开源,它支持 Chromium、Firefox 和 WebKit 三大浏览器引擎,能模拟真实用户操作进行端到端(E2E)测试。而 GitHub Actions 是 GitHub 平台内置的 CI/CD(持续集成/持续部署)服务,它允许你直接在代码仓库中定义自动化工作流,响应诸如代码推送(push)、拉取请求(PR)等事件。将两者结合,就意味着每次你向代码库提交更改时,GitHub Actions 会自动启动一个虚拟环境,运行 Playwright 测试套件来验证你的改动没有破坏现有功能,只有所有测试通过,才会触发后续的部署步骤,将更新安全地推送到生产环境。
2. 核心工具链深度解析:为什么是 Playwright + GitHub Actions?
在开始动手之前,我们必须先理解为什么选择这套组合拳。市面上测试框架和 CI/CD 工具众多,比如 Selenium、Cypress、Jenkins、GitLab CI 等。但 Playwright 和 GitHub Actions 的组合,在当前的前端和开源项目场景下,展现出了独特的优势。
2.1 Playwright:超越 Selenium 的现代浏览器自动化利器
Playwright 并非横空出世,它可看作是 Puppeteer 项目的进化与扩展。Puppeteer 主要专注于 Chrome/Chromium,而 Playwright 则一举提供了对三大浏览器引擎的一流支持。这意味着你写一套测试脚本,就可以在 Chrome、Firefox 和 Safari(通过 WebKit)上运行,轻松实现跨浏览器兼容性测试,这对于保证网站在不同用户环境下的表现一致性至关重要。
它的优势非常明显:
-
自动等待机制
:这是 Playwright 最省心的特性之一。在定位元素或执行操作前,它会自动等待元素变得可交互(如可见、可点击),无需在测试代码中手动添加大量的
sleep或显式等待,大大减少了因页面加载或渲染延迟导致的测试失败(Flaky Tests)。 -
强大的选择器引擎
:除了常规的 CSS 和 XPath,Playwright 提供了诸如
text=、role=等语义化选择器,让你可以编写更稳定、更贴近用户视角的测试。例如,page.click(‘text=Submit’)比page.click(‘#submit-btn’)更能抵抗前端 DOM 结构的变化。 - 网络拦截与模拟 :你可以轻松地拦截和修改网络请求,这对于测试错误处理、模拟慢速网络或 mock 后端 API 响应极其有用,无需依赖真实的后端服务。
-
录制与代码生成
:Playwright 提供了一个强大的命令行工具
playwright codegen,可以录制你在浏览器中的操作并自动生成测试代码,是快速创建测试用例原型的利器。
注意 :虽然 Playwright 功能强大,但它主要针对的是 E2E 测试和集成测试。对于单元测试(测试单个函数或组件),你仍然需要搭配 Jest、Vitest、Mocha 等框架。在这个项目中,我们聚焦于用 Playwright 来模拟用户访问
tools.simonwillison.net这个完整网站的行为。
2.2 GitHub Actions:无缝集成于代码仓库的自动化引擎
GitHub Actions 的最大优势在于它与 GitHub 生态的深度集成。你的工作流配置文件(.yml 文件)就存放在代码仓库的
.github/workflows/
目录下,版本管理与代码同步,协作和审计都非常方便。
它的核心概念是:
- 工作流(Workflow) :一个可配置的自动化过程,由仓库中的 YAML 文件定义。
-
事件(Event)
:触发工作流运行的具体活动,如
push、pull_request、schedule(定时任务)等。 - 作业(Job) :工作流中的一组步骤,在同一个运行器(Runner)上执行。一个工作流可以包含多个作业,默认并行运行,也可以设置依赖关系串行执行。
- 步骤(Step) :作业中可执行的任务单元,可以是运行一个命令、执行一个脚本或调用一个 Action。
-
Action
:可重用的独立单元,用于执行复杂或重复的任务。社区有海量的 Action 可供使用,例如
actions/checkout(检出代码)、actions/setup-node(设置 Node.js 环境)。
对于我们的项目,我们将创建一个工作流,监听
push
到主分支(如
main
)和针对主分支的
pull_request
事件。当这些事件发生时,工作流会自动启动,执行“安装依赖 -> 运行 Playwright 测试 -> 部署”等一系列步骤。
3. 项目环境搭建与初始化配置
理论清晰了,现在我们来搭建实战环境。假设你已经将
tools.simonwillison.net
的代码克隆到本地,并且它是一个基于 Node.js 的项目(这是 Playwright 的典型运行环境)。
3.1 本地开发环境准备
首先,在项目根目录下初始化 Playwright。
# 进入项目目录
cd tools.simonwillison.net
# 使用 npm 初始化 Playwright(如果你使用 npm)
npm init playwright@latest
# 或者使用 yarn
yarn create playwright
# 或者使用 pnpm
pnpm create playwright
执行命令后,CLI 会引导你进行一系列选择:
- 选择测试语言 :TypeScript 或 JavaScript。对于新项目,强烈推荐 TypeScript,它能提供更好的类型安全和编辑器支持。
-
选择测试文件夹位置
:默认是
tests或e2e,你可以按需修改。 - 是否添加 GitHub Actions 工作流 : 这里先选“No” 。因为我们将手动创建一个更定制化的工作流文件,以便更好地理解其原理。
- 是否安装 Playwright 浏览器 :选“Yes”。这会在本地下载 Chromium、Firefox 和 WebKit 的二进制文件,以便你本地运行测试。
初始化完成后,你的项目结构会新增以下关键文件和目录:
-
playwright.config.ts:Playwright 的主配置文件,可以设置浏览器、视口、基础URL、超时时间、截图/视频录制等。 -
tests/:存放测试用例的目录。 -
tests-examples/:一些示例测试文件。 -
package.json中会新增@playwright/test依赖以及相关的 npm scripts。
3.2 编写第一个针对项目的测试用例
现在,让我们为
tools.simonwillison.net
编写一个简单的冒烟测试(Smoke Test),确保核心页面可访问且关键功能正常。在
tests/
目录下创建一个文件,例如
homepage.spec.ts
。
import { test, expect } from ‘@playwright/test’;
// 使用 test.describe 对相关测试进行分组
test.describe(‘工具站首页测试’, () => {
// 在每个测试运行前,导航到基础URL。baseURL 在 playwright.config.ts 中配置。
test.beforeEach(async ({ page }) => {
// 假设我们在配置文件中将 baseURL 设置为 ‘https://tools.simonwillison.net’
await page.goto(‘/’);
});
test(‘页面标题正确’, async ({ page }) => {
// 断言页面标题包含特定文本
await expect(page).toHaveTitle(/Simon Willison’s Tools/);
});
test(‘主页存在核心功能区域或链接’, async ({ page }) => {
// 使用 getByRole 或 getByText 等语义化选择器定位元素
const header = page.getByRole(‘heading’, { name: ‘Tools’ });
await expect(header).toBeVisible();
// 假设网站上有一个著名的 “Datasette” 工具链接
const datasetteLink = page.getByRole(‘link’, { name: ‘Datasette’ });
await expect(datasetteLink).toBeVisible();
await expect(datasetteLink).toHaveAttribute(‘href’, /datasette/);
});
test(‘搜索功能可用’, async ({ page }) => {
// 定位搜索输入框并输入内容
const searchInput = page.getByPlaceholder(‘Search tools…’); // 根据实际placeholder调整
await searchInput.fill(‘sql’);
await searchInput.press(‘Enter’);
// 断言页面URL变化或出现搜索结果
await expect(page).toHaveURL(/.*search.*/); // 检查URL包含search
// 或者检查搜索结果元素出现
const results = page.getByTestId(‘search-results’); // 假设元素有 data-testid
await expect(results).toBeVisible({ timeout: 10000 }); // 给搜索一些时间
});
});
3.3 配置 playwright.config.ts 以适应项目
打开
playwright.config.ts
,根据你的项目进行关键配置:
import { defineConfig, devices } from ‘@playwright/test’;
export default defineConfig({
// 测试用例所在的目录
testDir: ‘./tests’,
// 并行运行测试时,每个工作进程的最大失败数。设置为1有助于在CI中快速失败。
maxFailures: process.env.CI ? 1 : undefined,
// 是否在遇到第一个失败时停止整个测试套件。CI环境中建议开启。
forbidOnly: !!process.env.CI,
// 重试失败的测试次数。本地开发可以设置,CI环境通常设为0或1,以避免隐藏间歇性错误。
retries: process.env.CI ? 1 : 2,
// 工作进程数,用于并行运行测试。CI中可以根据runner配置调整。
workers: process.env.CI ? 2 : undefined,
// 全局的测试超时时间(毫秒)
timeout: 30 * 1000,
// 所有测试的全局配置
use: {
// 所有测试的基础URL,这样在测试中可以使用相对路径,如 page.goto(‘/about’)
baseURL: ‘https://tools.simonwillison.net’,
// 在CI中捕获每次测试的追踪信息、截图和视频,便于调试。本地可关闭以节省资源。
trace: process.env.CI ? ‘on-first-retry’ : ‘off’,
screenshot: process.env.CI ? ‘only-on-failure’ : ‘off’,
video: process.env.CI ? ‘retain-on-failure’ : ‘off’,
},
// 项目配置:可以定义不同的浏览器或设备环境
projects: [
{
name: ‘chromium’,
use: { …devices[‘Desktop Chrome’] },
},
{
name: ‘firefox’,
use: { …devices[‘Desktop Firefox’] },
},
// 在CI中,WebKit测试可能较慢,可根据需要开启
// {
// name: ‘webkit’,
// use: { …devices[‘Desktop Safari’] },
// },
],
});
实操心得 :在配置
baseURL时,一个最佳实践是使其可通过环境变量覆盖。例如,在本地你可能想测试http://localhost:3000,而在 CI 中测试预发布环境,在生产部署前测试真实域名。可以这样配置:baseURL: process.env.PLAYWRIGHT_TEST_BASE_URL || ‘https://tools.simonwillison.net’。然后在本地.env文件或 GitHub Actions 的 secrets 中设置该变量。
4. 构建 GitHub Actions 自动化工作流
这是整个项目的自动化核心。我们将在
.github/workflows/
目录下创建一个 YAML 文件,例如
test-and-deploy.yml
。
4.1 工作流基础结构与触发条件
name: Test and Deploy # 工作流的名称,会在 GitHub Actions 页面显示
on: # 定义触发事件
push:
branches: [ main ] # 当代码推送到 main 分支时触发
pull_request:
branches: [ main ] # 当针对 main 分支创建或更新 Pull Request 时触发
# 权限设置,特别是部署步骤可能需要写入仓库内容(如生成报告)或访问 secrets
permissions:
contents: write # 允许工作流写入内容(例如上传测试报告产物)
pages: write # 如果使用 GitHub Pages 部署,需要此权限
id-token: write # 如果使用 OIDC 进行云服务认证(如 AWS、Azure),可能需要
jobs:
test: # 第一个 job:运行测试
runs-on: ubuntu-latest # 指定运行器环境,最新 Ubuntu
# 后续步骤将在这里定义
deploy: # 第二个 job:部署
runs-on: ubuntu-latest
needs: test # 指定依赖关系:只有 test job 成功后才运行 deploy job
if: github.event_name == ‘push’ && github.ref == ‘refs/heads/main’ # 仅在推送到 main 分支时执行部署
# 后续步骤将在这里定义
4.2 测试 Job 的详细步骤拆解
现在,我们来填充
test
作业的步骤。目标是搭建一个稳定的测试环境,高效运行 Playwright 测试,并收集和展示测试结果。
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
# 矩阵策略:可以同时在多个浏览器或 Node.js 版本下运行测试
# 这里我们选择在 Chromium 和 Firefox 上运行测试
browser: [chromium, firefox]
# node-version: [18, 20] # 如果需要测试多 Node.js 版本,可以取消注释
steps:
- name: Checkout repository code
uses: actions/checkout@v4 # 官方 Action,用于检出你的代码到运行器
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: ‘20’ # 指定 Node.js 版本,应与你的项目兼容
cache: ‘npm’ # 启用 npm 缓存,加速后续安装
- name: Install dependencies
run: npm ci # 使用 ci 而非 install,它严格依赖 package-lock.json,能确保依赖一致性,更适合 CI 环境
- name: Install Playwright Browsers
run: npx playwright install –with-deps ${{ matrix.browser }} # 仅安装矩阵中指定的浏览器,节省时间和空间
# –with-deps 会同时安装浏览器所需的系统依赖(如字体库)
- name: Run Playwright tests
run: npx playwright test –project=${{ matrix.browser }} –reporter=html
# –project 指定运行哪个配置文件中的项目(对应我们之前配置的 chromium/firefox)
# –reporter=html 生成一个漂亮的 HTML 格式测试报告
env:
# 如果测试需要环境变量,在这里设置
PLAYWRIGHT_TEST_BASE_URL: ${{ secrets.TEST_BASE_URL || ‘https://tools.simonwillison.net’ }} # 使用 secret 或默认值
- name: Upload Playwright test report
if: always() # 无论测试成功还是失败,都上传报告,便于排查失败原因
uses: actions/upload-artifact@v4
with:
name: playwright-report-${{ matrix.browser }} # 产物名称,按浏览器区分
path: playwright-report/ # playwright test 默认生成的 HTML 报告目录
retention-days: 7 # 产物保留天数
- name: Upload test results (JUnit format)
if: always()
uses: actions/upload-artifact@v4
with:
name: test-results-${{ matrix.browser }}
path: test-results/ # JUnit 格式报告,便于其他 CI 工具集成
4.3 部署 Job 的策略与实现
部署的方式千差万别,取决于你的网站托管在哪里。这里我以几种常见场景为例,展示如何集成到 GitHub Actions 中。
场景一:部署到 GitHub Pages(适用于静态站点)
如果你的
tools.simonwillison.net
是一个构建后的静态网站(例如由 Vite、Next.js 静态导出等生成),那么 GitHub Pages 是一个简单免费的选择。
deploy:
runs-on: ubuntu-latest
needs: test
if: github.event_name == ‘push’ && github.ref == ‘refs/heads/main’
environment: # 可选,定义一个部署环境,便于在 GitHub 界面查看和管理
name: github-pages
url: ${{ steps.deployment.outputs.page_url }} # 从部署步骤获取 URL
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: ‘20’
cache: ‘npm’
- name: Install dependencies and build
run: |
npm ci
npm run build # 假设你的 package.json 中 build 脚本用于构建静态文件
- name: Setup Pages
uses: actions/configure-pages@v4 # 配置 Pages
- name: Upload artifact
uses: actions/upload-pages-artifact@v3
with:
path: ‘./dist’ # 将构建产物目录(如 dist, build, out)上传
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4 # 执行部署
场景二:通过 SSH 部署到自有服务器(VPS)
这是更通用的方式,使用
ssh-agent
和
rsync
将文件同步到远程服务器。
deploy:
runs-on: ubuntu-latest
needs: test
if: github.event_name == ‘push’ && github.ref == ‘refs/heads/main’
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Node.js and Build
uses: actions/setup-node@v4
with:
node-version: ‘20’
cache: ‘npm’
run: |
npm ci
npm run build
- name: Install SSH key
uses: shimataro/ssh-key-action@v2
with:
key: ${{ secrets.SSH_PRIVATE_KEY }} # 将服务器的 SSH 私钥存入 GitHub Secrets
known_hosts: ${{ secrets.KNOWN_HOSTS }} # 可选,服务器指纹,避免首次连接确认
- name: Deploy to Server via Rsync
run: |
rsync -avz –delete ./dist/ ${{ secrets.DEPLOY_USER }}@${{ secrets.DEPLOY_HOST }}:${{ secrets.DEPLOY_PATH }}
# -avz: 归档模式、显示进度、压缩传输
# –delete: 删除目标端源端没有的文件,保持同步
# 将 DEPLOY_USER, DEPLOY_HOST, DEPLOY_PATH 存入 Secrets
场景三:触发外部部署服务(如 Vercel, Netlify) 许多现代托管平台提供了 GitHub 集成,可以通过简单的 Action 触发部署。
deploy:
runs-on: ubuntu-latest
needs: test
if: github.event_name == ‘push’ && github.ref == ‘refs/heads/main’
steps:
- name: Deploy to Vercel
uses: amondnet/vercel-action@v25
with:
vercel-token: ${{ secrets.VERCEL_TOKEN }} # Vercel 账户 Token
vercel-org-id: ${{ secrets.ORG_ID }}
vercel-project-id: ${{ secrets.PROJECT_ID }}
vercel-args: ‘–prod’ # 部署到生产环境
重要提示 :所有敏感信息,如
SSH_PRIVATE_KEY、VERCEL_TOKEN、服务器地址、密码等,都必须存储在 GitHub 仓库的 Settings > Secrets and variables > Actions 中,绝对不要直接写在 YAML 文件里。在工作流中通过${{ secrets.NAME }}的方式引用。
5. 高级优化与实战技巧
一个基础的工作流已经能跑起来了,但要让它健壮、高效,还需要一些优化技巧。
5.1 提升测试执行效率
-
并行化与分片 :我们已经在
testjob 中使用了matrix在浏览器维度并行。对于大量测试用例,还可以使用分片(Sharding)在单个浏览器内进一步并行。- name: Run Playwright tests with sharding run: npx playwright test –shard=${{ matrix.shard }}/${{ matrix.shards }}你需要定义一个
matrix.shard和总片数matrix.shards。这能极大缩短测试总时间。 -
依赖缓存 :除了 npm 缓存,Playwright 浏览器二进制文件也可以缓存,避免每次下载。
- name: Cache Playwright browsers uses: actions/cache@v4 id: playwright-cache with: path: ~/.cache/ms-playwright # Playwright 默认缓存路径 key: ${{ runner.os }}-playwright-${{ hashFiles(‘package-lock.json’) }} # 锁文件变化时缓存失效 restore-keys: | ${{ runner.os }}-playwright-然后在安装浏览器步骤前判断缓存是否命中。
-
选择性运行测试 :不是每次提交都需要全量测试。可以利用 Playwright 的
–grep过滤标签,或者通过分析代码变更来智能运行受影响的测试(这需要更复杂的脚本)。
5.2 测试报告与结果可视化
上传的 HTML 报告是压缩包,查看不便。我们可以使用第三方 Action 将其发布为一个临时网站。
- name: Publish Playwright Report
if: always()
uses: peaceiris/actions-gh-pages@v3
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./playwright-report
destination_dir: playwright-report/${{ github.run_id }} # 按运行ID区分每次报告
这样,每次测试运行后,你都会得到一个唯一的 URL 来查看详细的 HTML 报告。
此外,可以将测试结果以状态徽章(Badge)的形式添加到 README 中。GitHub Actions 提供了原生支持,格式为:
https://github.com/<username>/<repository>/workflows/<workflow_name>/badge.svg
。
5.3 安全与密钥管理最佳实践
-
最小权限原则
:在
permissions块中,只授予工作流所需的最小权限。例如,如果不需要写入仓库,就不要给contents: write。 -
使用环境特定 Secrets
:如果有多环境(如 staging, production),可以为每个环境配置不同的 Secrets,并在 job 中通过
environment关键字关联。 - 审计日志 :定期查看 GitHub 的审计日志,监控 Actions 的使用情况。
5.4 监控与告警
自动化流程一旦建立,就需要确保其可靠性。你可以在工作流中添加失败通知。
- name: Notify on Failure (Slack)
if: failure()
uses: 8398a7/action-slack@v3
with:
status: failure
channel: ‘#ci-alerts’
username: ‘GitHub Actions Bot’
env:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
类似的,可以集成邮件、钉钉、企业微信等通知方式。
6. 常见问题排查与调试实录
即使配置再完善,在实际运行中也可能遇到各种问题。这里记录几个我踩过的坑和解决方案。
6.1 测试在 CI 中通过,但在本地失败(或反之)
这通常是因为环境差异。
-
浏览器版本
:CI 环境中安装的 Playwright 浏览器版本可能与本地不同。确保
package.json中@playwright/test的版本固定,并定期更新。在 CI 安装步骤中使用npx playwright install确保安装指定版本。 -
系统依赖
:Linux CI 环境可能缺少某些库。
–with-deps参数能解决大部分问题,但某些特定字体或库仍需手动安装。如果遇到glibc或图形库错误,可能需要在工作流中增加安装系统包的步骤:- name: Install system dependencies (Ubuntu) run: | sudo apt-get update sudo apt-get install -y libgbm-dev libnss3 libatk-bridge2.0-0 libdrm-dev libxkbcommon-dev libasound2 libxshmfence-dev -
时区与语言环境
:测试可能依赖于特定的日期格式或语言。在 CI 环境中设置统一的环境变量:
env: LANG: ‘en_US.UTF-8’ TZ: ‘UTC’
6.2 测试执行超时
-
单个测试超时
:检查
playwright.config.ts中的timeout全局设置以及单个测试的test.setTimeout()。在 CI 中,由于资源限制,可能需要适当延长超时时间。 -
全局安装/构建超时
:GitHub Actions 免费套餐的 runner 资源有限。如果
npm ci或构建步骤耗时过长,可以考虑使用更快的包管理器(如 pnpm),或者利用缓存机制。如果项目很大,可能需要升级到付费的更大规格 runner。
6.3 部署步骤权限错误
-
SSH 连接失败
:确保私钥格式正确(通常是 PEM 格式),且对应的公钥已添加到服务器的
~/.ssh/authorized_keys中。known_hosts可以避免首次连接交互,通过ssh-keyscan your-server.com命令获取并存入 Secret。 -
GitHub Pages 部署 404
:检查构建产物的输出目录是否正确,以及 GitHub Pages 源设置是否指向了
gh-pages分支或root目录下的/docs文件夹。 - Vercel/Netlify 部署失败 :检查 Token 是否有足够权限,项目 ID 是否正确。查看对应平台提供的部署日志,通常非常详细。
6.4 Flaky Tests(不稳定的测试)
这是自动化测试的顽疾。应对策略包括:
-
增加重试
:在配置中设置
retries: 1(CI环境),给测试一次自我修复的机会。 -
使用更稳定的选择器
:优先使用
getByRole、getByText等语义化选择器,避免使用易变的 CSS 类名或复杂 XPath。 -
明确等待而非隐式等待
:虽然 Playwright 自动等待很好,但在某些复杂异步场景下,可能需要使用
page.waitForSelector或page.waitForFunction进行更精确的等待。 -
隔离测试状态
:确保每个测试是独立的,不依赖前一个测试留下的状态。使用
test.beforeEach进行重置。 -
启用追踪(Trace)
:在配置中设置
trace: ‘on-first-retry’,当测试失败时,会生成一个追踪文件,你可以用npx playwright show-trace命令在本地打开,可视化地回放测试的每一步,包括网络请求、DOM 快照等,是调试的神器。
7. 将流程扩展至更复杂的项目场景
tools.simonwillison.net
可能是一个相对简单的静态工具集。但对于更复杂的应用,这套流程可以进一步扩展。
7.1 多阶段测试金字塔
完整的测试策略应遵循测试金字塔。在 Playwright E2E 测试之前,可以加入更底层的测试 Job。
- Lint & Format Job :在测试之前,运行 ESLint、Prettier 或类似工具,确保代码风格一致。
- Unit Test Job :运行 Jest/Vitest 单元测试,速度更快,反馈更及时。
- Integration Test Job :可能使用像 MSW(Mock Service Worker)来 mock API,进行集成测试。
-
E2E Test Job
:就是我们上面配置的 Playwright 测试。
你可以通过
needs关键字定义这些 Job 的执行顺序,形成管道。只有 lint 和单元测试通过,才进行更耗时的 E2E 测试。
7.2 多环境部署
你可以定义多个部署 Job,对应不同的环境。
deploy-staging:
runs-on: ubuntu-latest
needs: test
if: github.event_name == ‘push’ && github.ref == ‘refs/heads/main’
environment: staging
steps: … # 部署到预发布环境
deploy-production:
runs-on: ubuntu-latest
needs: deploy-staging # 可能需要手动批准或额外条件
if: github.event_name == ‘push’ && github.ref == ‘refs/heads/main’
environment: production
steps: … # 部署到生产环境
在 GitHub 仓库的 Environments 设置中,可以配置
staging
和
production
环境,并设置保护规则和审批者,实现更安全的部署流程。
7.3 与数据库和外部服务的集成测试
如果应用依赖数据库或第三方 API,在 CI 中测试会更复杂。策略包括:
- 使用 Docker Compose :在工作流中启动一个包含数据库的 Docker 容器栈。
- 使用云服务提供的测试实例 :许多数据库服务(如 Supabase, PlanetScale)提供免费的开发/测试分支。
-
彻底 Mock 外部服务
:在 E2E 测试中,使用 Playwright 的
page.route()方法拦截所有对外部 API 的请求,返回固定的模拟数据。这能让测试完全可控且快速。
整个流程搭建下来,最初的手动测试和部署工作被转化为了一个清晰、自动化的管道。每次代码推送,你都能立刻得到质量反馈,并且可以自信地将通过所有检查的代码部署上线。这套基于 Playwright 和 GitHub Actions 的方案,不仅适用于这个具体的工具站,其模式和思想可以迁移到几乎任何 Web 项目中,是提升个人或团队研发效能不可或缺的一环。
962

被折叠的 条评论
为什么被折叠?



