Why bother: the trust problem
Vibe coding has a blind spot: you didn't type the code, so you can't scan it for mistakes the way you'd proofread your own writing. The AI wrote a hundred lines in four seconds and said it was done. It looks done. It ran once on your screen. But “it ran on my laptop” is a long way from “it works.”
Automated testing is a second pair of eyes that never gets tired. You write down, one time, what “working” means. From then on a computer re-checks the whole app against that definition every time anything changes, for free. Everything below is a variation on that.
You don't have to become a testing expert, and you barely have to write any of this yourself. Your AI sets most of it up and runs it. Your job is to know these safety nets exist, turn on the cheap ones, and refuse to accept “done” until they're green.
In one sentence
A test is you writing down, once, what “working” looks like, so a computer can re-check it forever and shout the moment it stops being true.
The ladder of checks
There isn't one kind of test. There's a ladder of them. Each rung catches a different class of problem, and they get slower and more thorough as you climb. You don't need all five on day one. Start at the bottom, where checks are nearly free and instant, and add rungs as your tool grows up and meets real people.
Read bottom to top: cheapest and fastest at the base, most thorough at the peak.
If you only do two things
Turn on rungs 1 and 2 (lint and TypeScript) today. They're nearly free and catch a big share of everyday mistakes before you even run the app. Add rung 4, a click-through test, the moment real users show up. The rest is polish.
Linting: spellcheck for code
A linter reads your code without running it and flags mistakes and messiness: a variable you named but never used, a bracket that doesn't close, a risky pattern, an inconsistent style. It works like the squiggly red underline in a word processor, but for code. This is the fastest, cheapest feedback there is, and it shows up right in your editor as you build.
ESLint · the standard
free“Reads your code and points at the mistakes, before you ever hit run.”
ESLint is the near-universal linter for JavaScript and TypeScript. Its partner Prettier handles pure formatting (spacing, quotes, line breaks) automatically, so you never argue about how the code looks. Together they keep AI-written code from quietly drifting into a mess.
Turn it on when: always. It's the bottom rung and it's basically free.
Watch for: don't drown in style nitpicks. Let Prettier auto-fix formatting so the only warnings left are the ones that matter.
Where it comes from: most modern builders and starter templates ship with it already wired in. If yours didn't, you never have to configure it by hand. Just tell your agent:
Set up ESLint and Prettier for this project, then fix every warning.
TypeScript: bugs caught before you run
TypeScript is regular JavaScript with labels on your data. You (or the AI) mark things: this is a number, this is a date, this is a student record with these exact fields. A type checker then makes sure you never mix them up, like handing a word to something that expected a number. It catches a big group of bugs before you ever click Run.
Picture labeled bins in a workshop. The bin marked “screws” refuses the paint. If you try to force it, something complains right away, instead of three weeks later when a student's screen goes blank and you have no idea why.
Lint vs. types, in one line
Lint judges how the code is written. Types judge whether the data fits together. Two different jobs. You want both, and they stack for almost no extra effort.
There's a tradeoff: TypeScript adds a little friction. You'll see red underlines that feel pedantic when you're moving fast. They're worth it, because that friction is the bug showing up early instead of in front of your class. Satisfying the type checker is also the kind of tidying AI agents are good at, so you rarely fix it yourself:
Turn it on when: any app that stores or moves real data around, which is nearly all of them. Builders like v0 and Bolt default to it. If you're in plain JavaScript, your agent can add it.
Tests that click through your app
Lint and types never open your app. They can't tell you the login button does nothing, or that the quiz submits blank. For that you need a test that behaves like a real student: open the page, type a name, click Submit, check what happened. That's an end-to-end test (E2E): the whole app, run the way a person would use it.
Playwright · Microsoft
free · start here“Drives a real browser automatically. The modern standard for click-through tests.”
You (or, realistically, the AI) write the steps in plain instructions: go to this page, fill the name box, click Submit, expect to see “Thanks.” Playwright runs all of that in a real browser in about a second and reports back pass or fail. Its cousins Cypress (friendly, popular) and Puppeteer (barebones original) do similar jobs. For a beginner in 2026, Playwright is the safe pick.
Turn it on when: the moment real people use your tool.
Watch for: E2E tests are slower and can be “flaky” (fail for timing reasons). Keep a few on the critical path, not hundreds.
Headless vs. a real browser window
This term sounds scarier than it is. It's the same browser doing the same thing. The only difference is whether there's a window for you to watch.
The rule of thumb
Run headed while you're building a test, so you can watch it. Run headless once it's on autopilot. Same test, same result. One just has a window and one doesn't.
You don't hand-write any of this. You describe the path, and the agent writes and runs the test for you.
Run it headed so I can watch, then fix anything that fails.
What to test first
The one path that would embarrass you most if it broke. For a quiz tool: can a student open it, answer, and submit? Test that “happy path” first. Everything else is bonus.
The robot reviewer on every commit
A commit is a save-point in your project's history (see the tools guide). Every time you push one up to GitHub, you can have robots check it automatically before it becomes part of the live app. There are two kinds, and they work well together.
Kind 1: your own checks, run automatically (CI)
“Continuous integration” is a plain idea behind a fancy name: GitHub Actions re-runs your lint, your type-check, and your Playwright tests on every push, on GitHub's servers, headless. If anything fails, the commit gets a red ✗ and you know before it ships. You set it up once (or ask your agent to), then forget it exists until it saves you.
Kind 2: an AI that reads the change like a colleague
These reviewers read your change the way a careful senior teammate would, and leave plain-English comments on the exact lines they're worried about: “this doesn't handle the empty case,” or “this could expose student emails.” A 2026 snapshot of the common ones:
GitHub Copilot review · GitHub
bundled · zero setupBuilt right into GitHub. If you already pay for Copilot, it costs nothing extra to switch on. Convenient and low-effort, but it mostly reads the changed lines rather than your whole project, so it's good for obvious bugs and light on the deep ones.
CodeRabbit · coderabbit.ai
free on public reposA one-click GitHub app and the most widely installed reviewer out there. Free on public repositories, a low per-seat cost on private ones. The easiest place for a solo builder to start.
Greptile · greptile.com
~$30/dev/moReads your entire codebase, not just the diff, so it catches cross-file bugs the lighter tools miss: the “you changed this over here and quietly broke that over there” kind of problem. Pricier, and worth it once your app is real. Anthropic also has its own Claude Code Review, though as of 2026 it's a research-preview product for Team and Enterprise plans.
The earliest catch: pre-commit hooks
A pre-commit hook (tools like Husky set these up) runs your lint and formatting the instant you try to commit, on your own machine, so broken code never even leaves your laptop. Optional, but your agent can add it in a minute. Better to catch a typo at your desk than after it's live on the internet.
The honest part
These robots reduce mistakes. They don't erase them. A green checkmark means “no obvious problems found,” not “certified perfect.” You still click through the real thing yourself before a class touches it. And for a solo vibe coder, you don't need all of this. One free AI reviewer plus GitHub Actions is plenty.
Claude Code & Codex, out of the box
Your coding agent is already a tester, if you ask it to be. Both Claude Code and Codex will, right out of the box, write tests, run them, read the failures, and fix the code, looping on their own until things pass. They'll run your lint and type-check and clean up what they broke. Claude Code even ships /review and /security-review commands, plus a code-review plugin that runs several review agents in parallel and surfaces only the high-confidence issues.
The catch out of the box
They only do this when you remember to ask. Left alone, an agent will cheerfully announce “done!” without ever running the checks. So you strengthen them by making the checks automatic and non-optional. Four ways, cheapest first:
1 · A memory file (CLAUDE.md / AGENTS.md)
A plain-text note that lives in your project and tells the agent your standing rules. Claude Code reads CLAUDE.md every session, and Codex reads AGENTS.md the same way (that file also works across many other tools). Put your build, lint, and test commands in it, plus one blunt instruction:
After any code change: run lint, run the type-check, run the tests.
Do not stop or say you're done until all three are green.
This is the most useful habit in the guide. It costs five minutes and turns a fast, sloppy agent into a careful one, every session.
2 · Hooks
Hooks are rules that fire automatically at set moments, with no human in the loop. For example: run the linter before every commit, and reject the commit if the tests fail. Claude Code has the deepest hook system, with a couple dozen points where you can step in, and Codex added its own hooks in 2026. This is how you enforce a rule the agent can't skip, even when it's in a hurry.
3 · The cross-check: one builds, the other reviews
Have one model write the code and a different model review it: the “Claude implements, Codex reviews” pattern. A second, independent model catches the things the author talked itself into. Ready-made plugins automate this loop. When Claude finishes a task, it fires off a Codex review and handles the feedback before you ever see it, so every change gets an independent second opinion.
4 · A Playwright MCP
An MCP is a small connector that gives an agent a new capability. A Playwright MCP lets Claude Code or Codex open a browser and click through your app to check its own work. Instead of guessing whether the button works, it presses the button.
The move that matters most
Put three lines in your CLAUDE.md or AGENTS.md: run lint, run types, run tests, and don't stop until they're green. If you do nothing else from this section, do that.
What a strengthened session feels like
“Add a file-upload field to the quiz and save it to the database.”
Writes the feature across a few files. Because your memory file said so, it doesn't stop there.
Runs lint and the type-check. Two red errors. Fixes both, runs them again, clean.
Runs the Playwright test for the quiz flow. It fails: the upload breaks Submit. Fixes it, re-runs, green.
See the green output before you accept the change, then click through it once yourself.
Watch for
An agent that says “done!” with nothing to show for it. Ask to see the checks pass: the green output, not the promise.
Where you're testing: local, preview, live
Before the habit in the next section clicks into place, it helps to know that your app doesn't run in just one place. There are three, and they're not equal. Knowing which one you're looking at is half of testing safely.
Local · localhost
only youWhen you run your project (usually a command like npm run dev), your builder starts a dev server on your own machine and hands you a private address like localhost:3000. “Localhost” just means “this computer.” Nobody else can reach it, it updates the instant you save, and it's completely safe to break. This is where you do most of your building and most of your clicking.
Preview · staging
a private linkA real URL on the internet that isn't the public one. Hosts like Vercel and Netlify connect to your GitHub repo and, every time you push a branch, build a preview deployment with its own throwaway address (something like your-app-git-quiz.vercel.app). It runs on the same setup as the real site, so you, or a colleague, can click through that exact change before anyone else sees it. Every branch gets its own preview link, which lets you try one idea without touching the live tool. This is the feature worth switching on.
Production · the live site
real usersThe app at your real address, the one students actually open. This is the one you protect. The oldest rule in the trade: don't test in production. By the time a change lands here, it should already have passed your checks and survived a click-through somewhere safer.
The loop this gives you
Push a branch, and that single push kicks off two things at once: your automated checks run (the commit robots from section 06), and a preview URL gets built. Click through the preview, fix anything wrong, then merge. Only merged, checked, clicked-through work reaches production, where the real students are.
Setting up a host like Vercel, wiring it to GitHub, and pointing a domain at it is the whole job of the hosting guide. This is just the testing-shaped view of it: three places your app can run, and the discipline of catching problems in the first two so they never reach the third.
Still test it yourself, often
Every check so far is worth having, and not one of them replaces you opening the app and using it. Automated tests only look for what someone thought to write down. They'll happily confirm the quiz submits and the score saves while staying silent about the questions appearing in the wrong order, the wording that confuses a ninth-grader, or the layout that falls apart on a phone. A green checkmark means “no problem I was told to look for,” not “good.” You're the one who catches the things nobody wrote a test for.
So keep clicking through it by hand, and do it often. The habit that pays off most is a quick human pass around every commit: make a small change, save it, then spend thirty seconds actually using the part you touched. When you check that frequently, a new bug can only have come from the handful of lines you just changed, so it's easy to trace and cheap to fix. Skip it for twenty commits and you're hunting through a week of changes with no idea which one broke things.
The habit
Commit small, commit often, and after each one spend thirty seconds being your own worst student: walk the real path, try a wrong answer, leave a box blank, open it on your phone. A bug caught the minute you make it almost fixes itself. A bug left to sit gets expensive and scary.
This isn't extra work bolted onto the automated checks. It's the other half of the same job: the robots watch the parts you can spell out in advance, and you watch the parts you only recognize once you see them.
A clean starter setup
You don't need the whole ladder on day one. This order leaves you covered without turning testing into a second job.
- Let your builder or template give you TypeScript, ESLint, and Prettier, and don't turn them off to make a warning go away.
- Add a
CLAUDE.md(orAGENTS.md) with your three rules: lint, types, and tests must pass before “done.” - When real users arrive, ask your agent for one Playwright test on the main path, the happy path first.
- Turn on one free AI reviewer on GitHub (Copilot review or CodeRabbit). One is plenty to start.
- Let GitHub Actions run your checks on every push. Green means safe to share.
- Let your host hand every branch a preview URL (Vercel and Netlify do this on their own), and click through that link before you merge to the live site.
- Still click through it yourself, around every commit, not just before a class sees it. Robots miss the human stuff.
Where this fits in the series
This is the safety net under the editors guide and the hosting guide: the gap between “it worked when I demoed it” and “it keeps working when thirty students hit it at once.” Prototype an idea, move into a real editor with an agent, put it online, and let these checks keep it online and correct.
You don't need to become a testing expert. You need to know these nets exist, switch on the cheap ones today, and tell your AI to stop pretending it's finished until everything's green.