Skip to content
AI Best Practices

QA Is Part of the Build: Where Testing Belongs in Your Definition of Done

A demo failed because a shared environment was left in an unknown state. The lesson: QA is not a handoff. It belongs in the engineer's definition of done, at every company size.

Michael Graham
Michael Graham
September 11, 2026· 15 min read
A chrome drafting compass standing upright, fused to a chrome blueprint sheet, whole and cleanly engineered, with electric violet binary code and thin wires running into the blueprint grid and a single cyan guidance trace, on a near-black floor etched with circuit traces.

The short answer. Quality assurance is not a checkpoint at the end that someone else owns. It is part of the engineer's definition of done, and it starts with proving the software works for the people and paths that carry most of the real traffic. How much proof you need depends on the size of the company and what a bug costs. Who owns the answer never changes.

The demo that didn't happen

When I came back from leave, I joined a customer meeting expecting to walk through part of a platform my team had been building. Instead, the shared development environment was unusable for the demo. The account shown as the administrator had the wrong email address on it. The tenant switcher wasn't reliable enough to reach the tenant we needed.

The email mismatch wasn't an accident. A developer had put their own address on the administrator account to test email notifications and hadn't put the shared data back. The feature had been exercised through the admin account, even though standard users are the people most likely to subscribe to those notifications in real use.

None of this was catastrophic. It was development, not production, and the immediate problem got fixed. That's exactly why it was worth talking about. Development is where we build the habits that eventually reach production.

The useful question wasn't "did the notification send?" It was "did we prove the feature works the way our users are most likely to use it?"

I want to be fair to the developer here. They took the feedback well and agreed to test the other roles. The conversation was about the pattern, not the person. I've caused production incidents of my own. That is the reason I care about building this habit early, while the blast radius is still small.

Did we test the feature, or did we test the user's path?

Testing a feature is not the same as testing user behavior.

An administrator account is often the fastest route to a screen or a permission. If administrators aren't the primary users of the feature, a green admin test proves an edge path. It says nothing about the dominant one. Permissions, tenant context, seed data, navigation, and account state can all hide behind a passing result.

This is the mentality I want engineers to carry:

Don't ask only whether the code can work. Ask whether we have evidence that it works for the user, role, data, and environment that will carry most of the real traffic.

For the notification feature, that means seeding a standard user, subscribing as that user, triggering the notification, and confirming the outcome from that user's side of the screen. The admin test is extra coverage. It isn't the main proof.

What "QA is part of the build" means in practice

Five habits. None of them require a QA department.

Start with the dominant user journey

Figure out who uses the feature most and test that path first. Secondary roles and edge cases still matter. They extend coverage. They don't substitute for the primary journey.

Treat a shared dev environment like a product when people depend on it

"It's only dev" is a fair statement about blast radius. It's not a reason to leave the environment in an unknown state. If customers, product owners, or other developers use it for demos and acceptance, it has an operational purpose. Until a production environment exists, dev may be the most visible version of the product there is. Its reliability affects trust even when no production data is at risk.

Cleanup is part of the test

A test that mutates shared data isn't finished when the assertion passes. It's finished when the environment is restored or the temporary data is isolated. Prefer disposable test users and repeatable seed data over editing shared identities. When temporary data is unavoidable, put the cleanup in the same change or the same workflow. A cleanup pull request should be the exception, not the mechanism.

A passing check is not the same as enough evidence

One passing scenario answers one narrow question. Engineering judgment is deciding whether that question is representative enough to support release confidence. Before you call something done, run through this:

  • Who is the primary user?
  • What is their most common path?
  • Which permissions, tenant state, and data does that path depend on?
  • What did this test actually prove?
  • What could still fail even though it passed?
  • Did the test leave shared state clean and predictable?

Engineers own quality even when a QA role exists

Dedicated QA people bring independence and exploratory thinking the builder doesn't have. Their involvement doesn't move ownership. The person who implemented the change is responsible for understanding its behavior, testing the expected paths, and handing over evidence that it's ready for broader validation. QA deepens and challenges that evidence. It should never be the first time anyone asks whether the feature works the way a real user would use it.

Why is it important to establish a definition of done?

A definition of done is the shared checklist a change has to clear before the team calls it finished. It matters because without one, "done" means whatever the last person to touch the work decided it meant. Putting QA inside that definition is what stops testing from turning into a handoff.

Most teams already have some version of this. Code written, reviewed, merged. The gap I see over and over is that "tested" sits in the list as a single word and nobody has agreed on what it means. Tested by whom? As which user? With what data? In which environment, and was that environment left the way you found it?

If your definition of done doesn't answer those questions, your QA is a vibe. Add the six questions above and you've turned a word into a standard. That's the whole change.

One distinction worth keeping straight: acceptance criteria describe what one feature has to do. The definition of done describes what every change has to clear. QA belongs in the second one, so it applies whether or not anyone remembered to write a test case into the ticket.

AI raises the cost of a weak quality mentality

AI can produce code faster than a team can understand and validate it. If engineers treat generated code as finished code, output goes up and confidence goes down. The bottleneck moves from writing syntax to exercising judgment: picking representative scenarios, noticing the missing case, questioning assumptions, and deciding what evidence is enough.

We've written about what this looks like when the missing case is a security boundary in AI-generated authentication or an accessibility affordance in a generated UI component. It's the same pattern as the admin account. The tool optimized for the path in front of it. The path in front of it was not the path most users take.

The more implementation we hand to AI, the more deliberately humans have to own validation. AI changes how code gets produced. It doesn't change who is accountable for the result. If you're moving a vibe-coded app toward real users, the migration playbook walks through where that scrutiny goes first.

QA strategy by company stage: enterprise, SMB, and startup

How much QA you need is a function of what a bug costs and who absorbs it. Enterprise and large software-as-a-service (SaaS) companies front-load quality because the software is the product, so they accept slower delivery. A mature small or mid-sized business (SMB) balances the two. A startup or side project leans on speed and uses a fast customer feedback loop as part of its QA. Every tier still owns the answer to "what did we prove?"

I've shipped code at billion-dollar companies and for two-person startups. The QA mentality is the same at both. The amount of process wrapped around it is not, and pretending otherwise is how teams either drown in ceremony or ship checkout bugs.

TierWhat a bug costsHow much QAWhere the speed comes from
Enterprise / large SaaSContracts, renewals, reputation at scaleHeavy. Regression suites, staging that mirrors production, release gates, sign-offsNot from the release process. From parallel teams and automation
Mature SMBA lost order, a support ticket, a client's confidenceBalanced. Full coverage on revenue paths, lighter everywhere elseClient review in staging, small batches, fast fixes
Startup / personal projectA day of a founder's time, occasionally a userLight. Dominant path proven, everything else watchedShipping first, fixing in hours, talking to users

Enterprise and large SaaS: satisfaction is the product

When the software is the entire product, satisfaction with the software is the entire business. Every renewal depends on it. So the process front-loads quality. Regression suites that take hours. Staging environments that mirror production. Release trains. Sign-offs from people who never touched the code. A small fix can take weeks to reach a customer.

That slowness isn't incompetence. It's a decision that a bug at scale costs more than waiting does. AI doesn't change that math. It makes more code arrive at the gate. It doesn't make the gate cheaper, because the gate exists to catch what the author didn't think of, and the author is now sometimes a model.

How customers are treated at this tier: they should never be the ones finding the bug. Communication is formal and scheduled. Status pages, release notes, an account manager who calls before you notice.

The detriment shows up when process built for the big release gets applied to the one-line fix. Engineers stop testing with intent because "QA will catch it." That is the failure mode from the demo story in miniature, and it happens at every company size.

Mature SMB: balance, and be honest about which paths matter

This is most of our clients at Command Center. Real revenue moves through the site. There's no QA department, and there never will be one. So the strategy is to sort paths by what they cost when they break.

Revenue paths get the enterprise treatment. Checkout, lead forms, login, anything that sends an email a customer is waiting on. Those get tested as the actual user, with realistic data, in staging. The client sees it working before it goes live. Our staging, review, then live workflow exists because of this tier. The client reviewing in staging is a QA step, and it's the one that catches the "that's not how our customers use it" bug an engineer can't see from inside the code.

Everything else gets a lighter pass, and we say so. A layout glitch on a page that gets thirty visits a month can ship. The client hears "we tested the checkout end to end on desktop and mobile; we did not test the archive page on every phone." That sentence is the difference between a client who trusts you and one who feels ambushed.

Here's the shape of a typical week. A client asks for a change to how shipping gets calculated. We build it in staging, run three real orders through as a customer would (not as the store admin), and send the client a short screen recording plus a note listing what we tried. They place a test order themselves. It goes live the next morning. Two days later they report that a specific coupon combination shows the wrong total. We had said coupons weren't in the test. The fix ships that afternoon with a note. Nobody's surprised. The client's confidence went up, not down, because the miss was already on the list of things we told them we hadn't checked.

The detriment is what happens when you get the sort wrong. Let a checkout bug through under "minor" and the client doesn't hear "we move fast." They hear "the unresponsive web guy strikes again." The cure is a better sort, not more process.

Startup and personal projects: speed, with a feedback loop that actually loops

At this tier, speed is the lever. Prove the dominant path works, ship it, and watch. Edge cases get found by users. That isn't a failure of QA. It's the QA strategy, and it's a good one if you hold up your end.

Holding up your end means you respond in hours, not sprints. You tell the user what happened and when it'll be fixed. Then you fix it and tell them it's fixed. Do that, and a bug report becomes one of the best moments in the customer relationship. The user just watched their feedback change the product they're paying for. Engineers get to move quickly on things that matter. Nobody spent a week testing a page nobody visits.

Testing in production is the honest name for this approach. It works when you have monitoring, a way to hear from users, and someone who will act on what they hear. Without those three, "move fast" is just "ship bugs."

Picture the first ten users of a scheduling tool. One of them books an appointment that crosses midnight and the confirmation shows the wrong day. They email. Within the hour they get a reply: "Good catch, you're the first person to book across midnight, fix is going out today." That evening it's fixed and they get a second note. That user tells two people about the tool. Not because it was bug-free. Because someone was there.

The detriment is the same approach without the loop. A bug that sits for three weeks with no reply is the exact experience that sends people looking for a new developer. And "it's only a prototype" stops applying the moment a customer is in a meeting looking at it, which is precisely what the demo story was.

The rule that holds at every tier

State what was tested and what wasn't. Make residual risk visible before release. Respond fast when something gets through. The tiers change how much you test. They don't change whether you own the answer.

Quality is a risk decision, not a checkbox

None of this argues that every engineer must exhaustively test every state. Time, environment access, test data, specialist hardware, security controls, and third-party dependencies limit what one person can prove alone. The standard is:

  1. Test the highest-value and highest-frequency paths available to you.
  2. Automate repeatable checks where the value justifies it.
  3. State what was tested and what was not.
  4. Make residual risk visible before release.
  5. Escalate when meaningful validation needs access, expertise, or an environment you don't have.

Quality can be shared across a team. It can't be unowned.

The lesson from the demo

The lesson wasn't that development must never break. Development exists so we can find problems safely. The lesson was that a feature isn't validated because we found one account that could make it work. Engineering quality means choosing tests that represent real use and leaving shared systems ready for the next person. It also means being honest about the evidence behind the word "done."

If you run a business where real money moves through the site and nobody is sorting your paths by what they cost when they break, that's the first conversation we have on a call.

Frequently asked questions

Who creates the definition of done?

The team that does the work. In Scrum that's the whole Scrum team, sometimes with an organization-wide minimum layered on top. In practice, the engineers who ship changes should write the QA half of it, because they're the ones who have to answer "what did this test prove?"

Should developers test their own code?

Yes, and it shouldn't be the only test. The developer proves the dominant path and hands over evidence. Then someone who didn't build it tests with fresh eyes: a QA engineer, a teammate, or the client in staging. The builder has looked at that screen a few hundred times and has stopped seeing it.

How much QA does a startup need?

Enough to prove the path most users take, plus a working way to hear about the rest. That means monitoring and a feedback channel someone actually reads. It also means fixing reported bugs in hours. That loop is the startup's QA department.

Does AI-generated code need more testing or less?

More scrutiny, not necessarily more test cases. The code arrives faster, so the human's job shifts to choosing representative scenarios and deciding what evidence is enough. Start with the paths most users take and work outward from there.

qatestingdefinition of doneai codebest practices
Michael Graham
Michael Graham

Founder & Software Engineer

Obsessed with building top-tier web software and crafting unique, polished user experiences.