🚀 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)。
相关推荐
原生高钙2 小时前
JS设计模式指南
前端·javascript
拳打南山敬老院2 小时前
漫谈 MCP 构建之Resources篇
前端·后端·ai编程
golang学习记2 小时前
从0死磕全栈第九天:Trae AI IDE一把梭,使用react-query快速打通前后端接口调试
前端
超人9212 小时前
我用纯前端技术打造了一个开发者工具箱,10+实用工具助力提效!
前端
bug_kada2 小时前
详解 React useCallback & useMemo
前端·react.js
Mintopia2 小时前
⚡ WebAssembly 如何加速 AIGC 模型在浏览器中的运行效率?
前端·javascript·aigc
AAA_Tj2 小时前
前端动画技术全景指南:四大动画技术介绍
前端
断竿散人2 小时前
乾坤微前端框架的沙箱技术实现原理深度解析
前端·javascript·前端框架
进阶的鱼2 小时前
(4种场景)单行、多行文本超出省略号隐藏
前端·css·面试