BUILT IN CLASS, Swiss Academy for Digital Skills

Checking AI-generated code: tests and failure cases

One example that works proves very little. Here is how to use acceptance cases, tests and targeted failure cases to check whether your AI agent's code really does what it should.

A laptop showing a contact list, next to test output with passed and failed checks.

The most reliable way to check AI-generated code is to write down beforehand what the application should do in each situation, and then deliberately try out the cases where something can go wrong. A single example that works proves very little: it only shows that this one particular path succeeds.

For beginners this sounds like it needs programming knowledge. Mostly, it doesn't. You don't have to read the code line by line to check whether it does what it should. You need clear expectations, a few awkward test cases and the habit of verifying every result yourself.

Why one successful example is not enough

Imagine you ask an AI agent such as Claude Code or Codex to add a form for new contacts to your contact list. You type in a name and an email address, click Save, and the contact appears in the list. Looks finished.

But quite a lot is still open:

  • What happens if the name field is empty?
  • Is ‘max@’ accepted as an email address?
  • Is the contact still there after you reload the page?
  • Does a contact that already existed now appear twice?

The AI built the path you described. The side roads you didn't mention it may have thought about, or it may not. Because the code looks tidy and the answer sounds confident, a gap often only shows up once someone actually uses the app. The normal case is rarely the problem. Errors usually hide at the edges.

Decide in advance what counts as correct

Before you can check anything, you need a standard to check against. Acceptance cases work well for this: short sentences that describe a situation and the expected result. For a status change in a follow-up app, they could look like this:

  • If I change a contact from ‘new’ to ‘contacted’, the list shows the new status immediately.
  • If I filter by status, only contacts with that status appear.
  • If a follow-up date is in the past, the contact is marked as overdue.

Sentences like these help you twice. You can give them to the AI as the task, instead of writing ‘add a filter’. And afterwards you can tick off each sentence one by one. What you haven't written down, you can't check either. So it pays to think about the unpleasant cases while you are still writing the task.

What tests do and what they don't

An automated test is a small program that recreates an acceptance case and reports whether the expected result occurs. Instead of clicking through by hand every time, you run one command and see which checks pass and which fail.

Tests mainly do three things:

  1. They record what is correct, regardless of how convincing the AI's explanation sounds.
  2. They raise the alarm when a later change breaks something that used to work. This happens easily when you work with an AI agent, because reworking one part sometimes changes another part along with it.
  3. They make checking repeatable. You don't test by feel, you test the same way every time.

Tests still have limits. A test only checks what is written in it. If you ask the AI to write the code and the tests at the same time, both can contain the same mistake in reasoning. Then everything is green and still wrong. So at least read what a test is supposed to check, and compare it with your acceptance cases. And if a test fails, don't simply let the AI adjust the test until it passes. First work out whether the code or the test is wrong.

Try out failure cases on purpose

Failure cases are situations that depart from the ideal flow. If you trigger them deliberately, you will find most of the weaknesses. For a simple application, four groups already cover a lot.

Missing information

Leave required fields empty. Save a contact without a name, create a follow-up without a date. Watch whether the app shows an understandable message or whether an empty entry ends up in the list. Also check fields that contain only spaces: for many programs, a space is valid input.

Invalid input

Enter data that doesn't match the expected format: an email address without a domain, a date like 31 February, a very long text. Also try special characters and umlauts in the name. Good validation rejects nonsense and lets correct input such as ‘Müller-Zürcher’ through. Both need testing.

The interface fails or responds unexpectedly

As soon as your app fetches data from an interface, new sources of error appear. Check at least these cases:

  • The response is empty. Does the app show a sensible message, or a blank, confusing area?
  • The interface reports an error. Does the app crash, or does it stay usable?
  • The response takes a long time. Can you see that something is loading, or does the app look frozen? Can you click twice in the meantime and create duplicate entries?

With a real interface these cases are hard to trigger, because it usually works. A simulated interface that responds empty, with an error or slowly on request is much more practical for this.

Access and secrets

This area is often forgotten. Ask yourself who is allowed to see or change which data, and try out whether that is actually how it works. Also check that access keys or passwords are not written into the code itself. Generated code sometimes writes such values straight into a file if the task doesn't ask for something else.

Checklist for every change the AI makes

You can work through this short list after every larger step:

  • I wrote down beforehand, in one sentence, what the change should achieve.
  • I tried the normal case myself and didn't rely on the AI's summary.
  • I tested at least one case with missing information and one with invalid input.
  • If an interface is involved: empty response, error and waiting time checked.
  • All automated tests pass, including the ones that passed before.
  • I know which files the AI changed and can roughly explain why.
  • There are no passwords or keys in the code.

If a point is still open, give the AI a concrete note: which case, what result you expected, what happened instead. The more precise the description, the more targeted the fix.

Working traceably with an AI log

Checking also means still knowing later what happened. A simple log helps: what did you ask the AI, what did it contribute, what did you change or discard yourself? That sounds like extra work, but it pays off as soon as an error turns up. You can then narrow down which step introduced it. If you also save small intermediate states with Git, you can undo a failed change instead of covering it up with more requests.

The log also helps with explaining. If you can describe your solution and name its limits, you have checked it. If all you can say is ‘the AI did it that way’, you have trusted it.

How the Vibe Coding Foundation course fits in

In the Vibe Coding Foundation programme you use Claude Code or Codex to build a contact and follow-up app for a small company, with sample data. Checking runs through every mission. Each mission has a goal, criteria in the form of tests and hints at three levels. On your computer, a command checks whether your solution meets the criteria. The check that counts runs on the academy's server, in an isolated environment with no network. So you experience first-hand that ‘works on my machine’ and ‘meets the criteria’ are two different things.

The failure cases from this article come up directly:

  • In Mission 3 you validate input and add status changes and filters.
  • In Mission 4 you practise handling responses, errors and waiting times with a simulated interface.
  • In Mission 5 you narrow down prepared errors, fix them and check basic access cases.
  • In Mission 7 you extend the app with a CSV export of overdue follow-ups and test the new feature.

Throughout the course you keep an AI log. In the written project exam you explain your solution and its limits; the exam rubric (in German) shows how it is marked. All missions with planned times are listed in the course overview (in German), and Mission 0 on setting up the tools is free to read. The learning project stores data in the browser and is meant for practice data, not real company data. What the course costs and what is included is set out under price and what's included.

Frequently asked questions

Do I need to be able to program to check AI-generated code?

No. You don't need to understand every line. What matters is that you decide beforehand what should happen in each case, and then verify it with tests and your own tries.

Is it enough if the AI writes the tests as well?

Only to a degree. Code and tests can contain the same mistake in reasoning. Read what a test is supposed to check and compare it with your own acceptance cases.

Which failure cases should I try first?

Missing information, invalid input and, if there is one, an interface that responds empty, with an error or slowly. After that, access and stored secrets.

This article in other languages: DeutschFrançaisItalianoРусский