A confession
The first UAT script I ever wrote was 187 cases long. Every case passed. Two weeks after go-live, the procurement team told me they were running parallel spreadsheets because the system couldn't handle a partial GRN against a multi-currency PO with a freight charge tied to a different vendor. I had tested partial GRN. I had tested multi-currency. I had tested freight. I had not tested the messy combination an actual buyer faces on a Tuesday afternoon.
That sentence is the entire essay. The rest is just craft.
Happy paths pass UAT. Tuesday afternoons fail it.
Why happy paths lie
UAT is the last line of defense against an ERP that is technically correct and operationally useless. But most scripts are written by the people closest to the configuration — the consultant, the integrator, the BA — which means they are written from inside the system. They walk forward through screens. They check that buttons do what the spec said.
Operations doesn't walk forward through screens. Operations walks forward through days. A script that doesn't account for that will catch typos and miss the things that actually break a business.
The shape of a useful script
Here's the structure I land on now, after enough painful Mondays:
- Anchor each case to a person, a moment, and a constraint. Not "user creates SO with multiple lines," but "Rina, on the last working day of the month, reopens an SO that was already partially shipped to add an urgent line item."
- Force one variable off the happy path. A late vendor. A wrong currency. A missing approval. A barcode that doesn't scan. The system has to fail gracefully or the user will work around it.
- Define the failure mode out loud. If the case fails, what does Rina actually do at her desk? If the answer is "call IT," you haven't designed for production.
- Tie the case to a measurable result, not a screen state. "Stock value reconciles to the source POs to the rupee" is a UAT case. "Inventory page loads" is a smoke test.
Two cases, side by side
Same intent, two scripts. The left is what I used to write. The right is what I write now.
Before · happy path
Create a Purchase Order with 3 lines, validate, receive in full, post the bill, register payment.
Pass criteria: all four documents reach "Done."
After · operational
Rina raises a PO in USD for a vendor who delivers in two split shipments — one short, one over. The short one arrives on the last day of the month; the over arrives next quarter. Freight is invoiced separately by a forwarder.
Pass criteria: stock value, COGS and FX gain/loss reconcile to the source documents at month-end close.
The first version takes twelve minutes to run. It will pass. The second version takes forty minutes and exposes three configuration gaps before lunch — none of which would have surfaced before live operations.
If you can run a UAT case without ever asking an end user a question, the case is probably testing the software, not the business.
What goes in the script header
Every case I write now starts with the same six fields. They look bureaucratic. They aren't — they're the difference between a tester who knows what they're doing and a tester who's politely clicking through.
What I do differently now
Three things, none of them complicated.
I write the script with operations, not for them. The procurement lead writes their own cases for two hours, in their own words, before I touch them. I add the technical scaffolding afterward. The cases are messier. They're also right.
I budget for the second-week bug. The bugs that surface in UAT week one are configuration. The bugs that surface in week two are workflow — and you only find them by running a full operational cycle, not a screen tour. I build a 5-day "shadow week" into the plan where users do their real job inside the system, in parallel with the old one. It costs time. It saves a quarter.
I ban the word "works." A case doesn't work. It produces a number, a document, a state — and that number, document or state either reconciles with the business or it doesn't. "Works" is how you ship 187 green checkmarks and a procurement team running spreadsheets in the corner.
The script is not the test. The test is whether your operations team will, unprompted, reach for the system instead of the spreadsheet on Tuesday afternoon.
If they do, you didn't pass UAT — you passed change management. The script just got you in the door.
FAQ
What should be included in an Odoo UAT test script?
An effective Odoo UAT script should cover: test case ID, the module being tested, prerequisite setup steps, step-by-step instructions for the tester, expected result, an actual-result field, pass/fail status, and a defect reference. Organise test cases by business process — not by Odoo menu — so non-technical users can follow along without ERP knowledge.
How many test cases do you need for Odoo UAT?
A typical Odoo UAT for a Bangladesh manufacturer with 4–6 modules needs 80–150 test cases — core happy paths plus 20–30% edge cases. Each module should have at least one end-to-end scenario (e.g. purchase order to vendor payment). A coverage matrix ensures no critical business process is missed.
Who should perform UAT testing in an Odoo project?
UAT must be performed by actual end users — the people who will use the system daily — not by the implementation consultant or IT team. The consultant's role during UAT is to observe, answer questions, and log defects, not to execute the test cases.
The companion utilities for this piece are the migration checklist and the BPMN discovery templates — same philosophy, different artifacts.