{"post":{"slug":"how-to-write-good-tests-2026","title":"How to write good tests in 2026: testing pyramid revisited, AAA, real smells","excerpt":"The testing pyramid still works in 2026 — most teams just apply it wrong. Here is the practical guide to writing tests that actually pay back.","category":"code","date":"February 11, 2026","author":"ByteLedger Team","content":"<span class=\"dropcap\">G</span>ood tests are a leverage multiplier — they let you change code with confidence, ship faster, and catch regressions before users do. Bad tests are a tax — slow, flaky, brittle, expensive to maintain. The difference is mostly process and discipline, not tool choice. This guide is the practical playbook for writing tests that actually pay back.\n\n## What changed in 2026\n\n- **AI-generated tests became normal.** Cursor, Claude, and Copilot can scaffold tests in seconds — but the auto-generated tests are often the wrong tests, testing implementation details rather than behavior.\n- **Snapshot testing fell out of favor** for non-trivial cases. Inline assertions are clearer and harder to \"just regenerate\" thoughtlessly.\n- **Vitest overtook Jest in new projects** by speed and ESM support — see [Vitest vs Jest in 2026](/blog/vitest-vs-jest-2026).\n\n## The pyramid still works\n\nThe testing pyramid (lots of unit tests, fewer integration tests, even fewer end-to-end) is still right in 2026 because it reflects test cost: unit tests are 10-100× faster and more deterministic than E2E. A typical good test suite for a web application:\n\n- **Unit tests (~70%)**: pure functions, business logic, individual components in isolation\n- **Integration tests (~25%)**: database interactions, API routes, multi-component workflows\n- **E2E tests (~5%)**: critical user paths only — sign up, checkout, the 3-5 paths your product cannot ship broken\n\nInverting this pyramid (lots of E2E, few unit tests) is how you end up with 30-minute test suites that nobody trusts.\n\n## The AAA pattern\n\nArrange, Act, Assert. Three blocks per test, separated visually:\n\n```ts\ntest('subtotal includes tax', () => {\n  // Arrange\n  const cart = newCart([{ price: 100, qty: 2 }]);\n\n  // Act\n  const total = cart.totalWithTax(0.08);\n\n  // Assert\n  expect(total).toBe(216);\n});\n```\n\nOne concept per test. If the assert section has more than 1-3 expectations, the test is doing too much. Split it.\n\n## Common test smells\n\n**Testing implementation, not behavior.** A test that breaks every time you refactor is testing the wrong thing. Test what the code does, not how.\n\n**Excessive mocking.** If you mock 8 dependencies to test one function, the function has too many dependencies. Listen to the test.\n\n**Shared mutable state between tests.** Tests run in parallel. Globals, singletons, and shared fixtures cause flake. Each test owns its setup.\n\n**Snapshot tests that nobody reads.** Auto-generated snapshots get regenerated mindlessly. They prove the output didn't change, not that it's correct. Use sparingly.\n\n**Slow unit tests.** A unit test that takes >50ms isn't a unit test. It's an integration test pretending. Speed up or move it.\n\n**Tests that pass when broken.** If you don't have a \"make this fail first\" step in your TDD or test-writing flow, you'll write tests that pass for the wrong reason.\n\n## Coverage is necessary but not sufficient\n\n| Coverage % | What it means in practice |\n| --- | --- |\n| <50% | Most paths untested; refactoring is dangerous |\n| 50-70% | Critical paths covered; many edge cases missed |\n| 70-85% | Sweet spot for most apps; diminishing returns above |\n| 85-95% | Good for libraries and shared code |\n| 95-100% | Often theater — covering trivial code, missing real behavior |\n\nCoverage is necessary but not sufficient. 100% coverage with bad assertions is worse than 70% coverage with good ones. Ask: if I delete the code, do tests fail? If I introduce a bug, do tests catch it?\n\n## What to test first when adding tests to a legacy codebase\n\n1. **Critical revenue paths.** Checkout, signup, billing.\n2. **Bug-prone areas.** Look at git blame for recent fixes — those modules need regression tests.\n3. **Public API surface.** What other code depends on this? Test the contract.\n4. **Pure functions.** Easiest to test, biggest immediate ROI.\n\nWhat to skip first: UI styling, glue code, simple getters/setters, anything that changes weekly for product reasons.\n\n## AI-generated tests in 2026\n\nLLMs can scaffold tests in seconds. The good: covers the easy paths, generates the boilerplate, suggests edge cases you might miss. The bad: tends to test implementation rather than behavior, generates plausibly-named tests that don't actually assert what they claim, hallucinates API methods.\n\nThe pattern that works: **you write the test name and the AAA structure; AI fills in the test body.** That keeps you in the design seat and lets the model do the typing.\n\n## FAQ\n\n**Should I do TDD?**\nSometimes. Pure TDD shines for well-understood domains (parsers, calculators, business rules). For exploratory UI work, writing tests after the design settles is fine.\n\n**E2E tests with Playwright vs Cypress in 2026?**\nPlaywright now leads — faster, multi-browser by default, better debugging. Cypress is still solid but Playwright became the default for new projects in 2025-2026.\n\n**How long should tests take to run?**\nUnit tests: under 30 seconds for the suite. Integration: under 2 minutes. E2E: under 10 minutes for the critical-path subset. Anything longer is a productivity killer.\n\n**Should AI write tests for me?**\nUse it for boilerplate and scaffolding. Review every assertion. Never accept \"tests pass\" as evidence the code works without reading the tests.\n\n## Where to go next\n\nFor related coverage see [Vitest vs Jest in 2026](/blog/vitest-vs-jest-2026), [TypeScript strict mode guide in 2026](/blog/typescript-strict-mode-guide-2026), and [AI coding agents workflows in 2026](/blog/ai-coding-agents-workflows-2026).","hue":148,"metaTitle":"How to Write Good Tests in 2026: Pyramid, AAA, Smells","metaDescription":"Practical 2026 guide to writing good tests — testing pyramid revisited, AAA pattern, common test smells, and what coverage actually matters.","keywords":["how to write good tests","testing pyramid 2026","aaa pattern testing","unit test best practices","integration tests vs e2e","test smells","test coverage 2026","testing software 2026","how to test code","tdd in 2026"],"tldr":["**Most \"untestable code\" is design feedback.** Hard to test usually means hard to change. Listen to the test.","**The pyramid still applies:** lots of fast unit tests, fewer integration, fewest E2E.","**AAA is the structure that scales:** Arrange, Act, Assert. One concept per test.","**Skip:** chasing 100% coverage. 70-80% on the right code beats 100% on everything."],"readTime":"4 min read","wordCount":869},"related":[{"slug":"how-to-write-unit-tests-2026","title":"How to write unit tests in 2026: patterns, coverage, and what to actually test","excerpt":"Unit tests are fast, focused, and the foundation of a reliable test suite. This 2026 guide covers what to test, how to structure tests, and the patterns that make tests useful rather than just green.","category":"code","date":"March 2, 2026","author":"ByteLedger Team","readTime":"5 min read","hue":319},{"slug":"unit-vs-integration-testing-2026","title":"Unit vs Integration Testing Explained 2026: Where Each Pays Off","excerpt":"Unit tests check one piece in isolation; integration tests check pieces working together. Here is the 2026 guide to the difference, the right balance, and how to avoid slow, brittle test suites.","category":"code","date":"July 1, 2026","author":"ByteLedger Team","readTime":"4 min read","hue":150},{"slug":"unit-testing-explained-2026","title":"Unit testing explained in 2026: write tests that actually help","excerpt":"Most developers know they should write unit tests but struggle with what to test, how to structure them, and why their tests keep breaking. Here is the 2026 guide.","category":"code","date":"March 19, 2026","author":"ByteLedger Team","readTime":"4 min read","hue":322}],"sameCategory":[{"slug":"bazel-build-explained-2026","title":"Bazel Explained: What Hermetic Builds Actually Cost","excerpt":"Bazel delivers reproducible, precisely cached builds and demands that you describe everything. Here is what you get, what it costs, and who should say no.","category":"code","date":"August 19, 2026","author":"ByteLedger Team","readTime":"3 min read","hue":145},{"slug":"graphql-federation-2026","title":"GraphQL Federation: One Graph, Many Teams","excerpt":"Federation composes independently-owned subgraphs into a single API. Here is what it solves, the operational cost it adds, and when a simpler gateway is enough.","category":"code","date":"August 19, 2026","author":"ByteLedger Team","readTime":"3 min read","hue":300},{"slug":"hermetic-builds-explained-2026","title":"Hermetic Builds Explained: Same Inputs, Same Output","excerpt":"A hermetic build depends only on declared inputs. Here is what that property gives you, the common leaks that break it, and how to move toward it incrementally.","category":"code","date":"August 19, 2026","author":"ByteLedger Team","readTime":"3 min read","hue":130},{"slug":"monorepo-tooling-compared-2026","title":"Monorepo Tooling Compared: What You Actually Need","excerpt":"Monorepo tools solve task orchestration and caching, not repository layout. Here is what each tier provides and how to tell when you have outgrown the simple option.","category":"code","date":"August 19, 2026","author":"ByteLedger Team","readTime":"3 min read","hue":150}],"newer":{"slug":"how-to-stop-procrastinating-2026","title":"How to stop procrastinating in 2026: 7 evidence-based methods that work","excerpt":"Procrastination is not a willpower problem — it is an emotion-regulation problem. Here are seven evidence-based methods that work, ranked by what the research actually supports.","category":"guides","date":"February 11, 2026","author":"ByteLedger Team","readTime":"4 min read","hue":60},"older":{"slug":"hsa-account-guide-2026","title":"HSA account guide for 2026: the triple tax advantage and how to actually use it","excerpt":"Health Savings Accounts are the most tax-advantaged account in the US tax code — triple tax-free, investable, portable. Here is the honest 2026 guide to limits, providers, and how to actually use one.","category":"finance","date":"February 11, 2026","author":"ByteLedger Team","readTime":"4 min read","hue":295}}