🚀 Next.js 全栈 E2E 测试:Playwright vs Cypress

写 Next.js 项目的人,最终都会走上这样一条路:
写前端 → 写 API → 写数据库 → 写测试 → 坐牢(调试半天测试不通过)。

为了不让自己凌晨三点还在盯着 npm test 发呆,我们需要掌握 E2E(End-to-End)测试

今天的主角是两位测试界的明星:

  • 🎭 Playwright ------ 来自微软,擅长潜入浏览器底层搞事情。
  • 🌲 Cypress ------ UI 界的老牌网红,界面友好,生态丰富。

接下来我们用 Next.js 做个全栈小例子,边写边比较。


🏗️ 1. 为什么要做 E2E 测试?

很多人觉得单元测试已经够了。

  • 单元测试:就像检查螺丝钉是不是拧紧。
  • E2E 测试:直接开上车,踩油门,看车会不会解体。

在全栈应用里,前端、后端、数据库之间任何一个环节崩了,用户体验就直接爆炸。E2E 测试帮我们模拟真实用户的操作,比如:

  1. 打开页面
  2. 填写表单
  3. 点击提交
  4. 检查后端是否真的保存成功

⚙️ 2. Next.js 项目准备

bash 复制代码
# 创建一个 Next.js 项目
npx create-next-app e2e-demo
cd e2e-demo

我们加一个简单的 Todo 功能:

pages/api/todos.js

ini 复制代码
let todos = [];

export default function handler(req, res) {
  if (req.method === "POST") {
    const todo = { id: Date.now(), text: req.body.text };
    todos.push(todo);
    return res.status(201).json(todo);
  }
  if (req.method === "GET") {
    return res.status(200).json(todos);
  }
}

pages/index.js

javascript 复制代码
import { useState } from "react";

export default function Home() {
  const [todos, setTodos] = useState([]);
  const [text, setText] = useState("");

  async function addTodo() {
    const res = await fetch("/api/todos", {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ text })
    });
    const newTodo = await res.json();
    setTodos([...todos, newTodo]);
    setText("");
  }

  return (
    <div>
      <h1>📝 Todo List</h1>
      <input
        value={text}
        onChange={(e) => setText(e.target.value)}
        placeholder="Write something..."
      />
      <button onClick={addTodo}>Add</button>
      <ul>
        {todos.map((t) => (
          <li key={t.id}>{t.text}</li>
        ))}
      </ul>
    </div>
  );
}

到这里,我们有了一个最小可测的全栈应用。


🎭 3. 用 Playwright 写 E2E 测试

安装:

bash 复制代码
npm install -D @playwright/test
npx playwright install

配置一个测试:

tests/todo.spec.js

erlang 复制代码
import { test, expect } from "@playwright/test";

test("用户可以添加一个 Todo", async ({ page }) => {
  await page.goto("http://localhost:3000");

  await page.fill("input", "买一杯咖啡");
  await page.click("button");

  const todo = await page.locator("li").last().innerText();
  expect(todo).toBe("买一杯咖啡");
});

运行:

bash 复制代码
npx playwright test

Playwright 的优势:

  • 多浏览器支持(Chromium、WebKit、Firefox)
  • 速度快,底层用浏览器协议直连
  • 内置截图、视频录制,调试时一目了然

🌲 4. 用 Cypress 写 E2E 测试

安装:

arduino 复制代码
npm install -D cypress
npx cypress open

配置一个测试:

cypress/e2e/todo.cy.js

erlang 复制代码
describe("Todo App", () => {
  it("用户可以添加一个 Todo", () => {
    cy.visit("http://localhost:3000");

    cy.get("input").type("写测试代码");
    cy.contains("Add").click();

    cy.get("li").last().should("have.text", "写测试代码");
  });
});

运行:

arduino 复制代码
npx cypress open

Cypress 的优势:

  • 界面化调试,像玩小游戏一样点点点
  • 社区插件丰富
  • 断言语法自然(cy.get().should(...) 看起来比 expect 更口语化)

🥊 5. Playwright vs Cypress 对比

特性 Playwright 🎭 Cypress 🌲
浏览器支持 Chromium / Firefox / WebKit Chromium 系
速度 ⚡ 更快 稍慢
调试体验 截图 & 视频 可视化界面强
API 风格 类似 Jest 链式操作,更口语化
CI/CD 适配 强大 成熟

一句话总结:

  • 如果你爱折腾底层,想要跨浏览器测试 → Playwright
  • 如果你想要上手快、调试方便 → Cypress

🌌 6. 收尾

测试不是"写完交差"的工作,它本质上是 给自己未来省头发

E2E 测试就像一台自动驾驶仪:

  • 让你放心上线
  • 让你半夜睡得更香
  • 让你的代码少点"玄学 Bug"

写代码的人和写测试的人,往往是同一个倒霉蛋。

但是相信我:测试写得好,未来的你会给现在的自己磕个头 🙇。


📌 作业

  • 用 Playwright 写一个"用户登录"E2E 测试。
  • 用 Cypress 写一个"数据持久化"测试(刷新后还能看到 Todo)。
相关推荐
我叫张小白。10 小时前
Vue3 基本生命周期:组件的一生之旅
前端·javascript·vue.js·前端框架·vue3
GISer_Jing10 小时前
SSE Conf大会分享——UTOO WASM:AI时代的浏览器原生极速研发套件
前端·人工智能·架构·wasm
Q***l68711 小时前
前端在移动端中的响应式设计
前端
QH_ShareHub11 小时前
R 包中的生命周期触发函数全解析
前端·javascript·数据库
小奶包他干奶奶11 小时前
Webpack学习——如何自定义钩子
前端·学习·webpack
AI3D_WebEngineer11 小时前
企业级业务平台项目设计、架构、业务全解之平台篇
前端·javascript·vue
该用户已不存在11 小时前
免费 SSL 证书缩短至 90 天,你的运维成本还能hold住吗
前端·后端·https
汤姆Tom11 小时前
前端转战后端:JavaScript 与 Java 对照学习指南 (第二篇 - 基本数据类型对比)
java·javascript·全栈
七月十二11 小时前
【Vite】离线打包@iconify/vue的图标
前端·vue.js
星空的资源小屋11 小时前
Explorer++:更强大的Windows文件管理器
javascript·人工智能·django·电脑