Why a fixed scope integration begins with the test, not the estimate

Most integration disputes are not technical. They are definitional. The supplier believes the work is complete because orders are flowing between two systems; the finance manager believes it is not, because the nominal codes on five per cent of orders are wrong and the VAT on Channel Islands shipments posts to the standard rate. Both positions are defensible, because nobody wrote down what correct meant before the build started. A fixed scope integration that is priced from a one-page brief is not fixed at all; it is a fixed price attached to a moving target, and the movement will be absorbed either by the supplier's margin or by the client's patience.

The remedy is unglamorous. Before any estimate is produced, the acceptance test is written out in full and agreed in writing. It states which records will be processed, what each field will contain on the receiving side, what the reconciliation figures must be, and who will sit at the keyboard and confirm it. The estimate is then produced against that document rather than against a conversation. If the test cannot be written, the scope is not yet understood, and producing a number at that point is guesswork dressed as commitment.

This inverts the common sequence, in which testing is treated as a phase that happens after the build and is specified by whoever happens to be available in the week before go-live. Written last, a test tends to confirm what the code already does. Written first, it describes what the business needs and becomes the specification. The build then has a target it can be measured against, and the discovery work that precedes it has an obvious purpose: to gather the facts the test will depend on.

There is a commercial argument as well as a quality one. A supplier who has agreed a precise test can price the risk accurately, because the boundary of the work is visible. A client who has agreed a precise test knows exactly what they are buying and can refuse to pay for something that does not meet it. Ambiguity benefits neither party. It merely defers the disagreement to the point where both sides have already spent money.

What an acceptance test document actually contains

An acceptance test for an integration is not a list of aspirations. It is a set of cases, each with a named input, a defined action and a verifiable output, written so that a competent person who was not involved in the build can run it and reach the same conclusion. The structure matters less than the discipline, but the following components appear in every version that has held up in production.

Each case should be expressed in terms a finance or operations reader can verify without opening a developer tool. "Order SO-10432 appears in Sage 200 as sales order 10432 with customer account WEB001, nominal 4000, VAT code T1, net 124.50, VAT 24.90" is testable. "Orders sync correctly" is not. Where a value is derived rather than copied, the derivation rule belongs in the test, not in the developer's head.

Non-functional criteria deserve the same treatment. If the business needs orders in the warehouse within fifteen minutes of payment, that interval belongs in the acceptance test with a stated measurement method. If the integration must survive the receiving system being unavailable for two hours, the test should include switching it off and confirming that nothing is lost and nothing is duplicated when it returns.

  • A named test data set — Specific records, identified by reference, drawn from real history rather than invented. Typically twenty to forty orders chosen to cover the variations that actually occur, plus any records the finance team knows have caused trouble before.
  • Expected output per record — Field by field, on the receiving system. Customer account, nominal code, tax code, net, tax, gross, dates, references and anything else finance will later rely on.
  • Reconciliation totals — An aggregate check that the sum of what left one system equals the sum of what arrived in the other, stated to the penny, with any permitted variance explicitly named and justified.
  • Failure behaviour — What happens when a record cannot be processed: where it is held, who is notified, how it is retried, and the evidence that it was not silently discarded.
  • Sign-off roles — The named individuals who run the test and the named individual who accepts it. Usually one from operations and one from finance, because they check different things.

Building the cases from real data rather than from API documentation

Platform documentation describes what a field can contain. It does not describe what your business puts in it. The gap between those two things is where most of the unbudgeted effort in an integration project lives. A Shopify export will tell you that discount allocations exist at line level and order level; it will not tell you that your merchandising team has been applying order-level discounts to mixed-VAT baskets for three years, and that the apportionment rule you need has never been written down. The only reliable way to find that out is to take a real month of orders and work through them.

In practice this means asking for a representative extract early in discovery and reading it properly. Sort by value, by channel, by country, by payment method, and look at the outliers at both ends. The single-penny order placed to test a promotion, the order with forty-two lines, the one paid half on account and half by card, the one shipped to a BFPO address: each of these either has a defined handling rule or it does not, and the acceptance test is where that rule gets recorded. A Sage 200 posting routine that handles the middle ninety per cent elegantly and the remaining ten per cent not at all is a routine that will generate manual work forever.

The same applies to the warehouse side. If fulfilment runs through Mintsoft, the acceptance test should include a case where a despatch is partial, a case where a courier service is downgraded at the point of booking, and a case where an item is short-picked and the order is closed with less than was ordered. Each of those has a consequence in the finance system, and each needs an agreed answer before the build rather than an improvised one afterwards. Writing the cases forces the conversation with the people who know, which is usually a warehouse supervisor rather than a project sponsor.

Where the integration touches an accounting ledger, involve the person who closes the month. They will know which codes are reconciled by hand, which control accounts have historically drifted, and what the auditors asked about last year. A Xero integration that posts technically valid journals but makes the bank reconciliation harder has failed, even though every API call returned a success. That judgement belongs in the acceptance test, and it can only come from the person who does the work.

Exclusions, assumptions and the change control that follows

A test defines what is in scope by describing it. It should also define what is out of scope by naming it. An exclusions list is not defensive paperwork; it is the mechanism by which a fixed price remains honest. If historical data migration is not included, say so. If the integration handles orders but not returns, say so, and say what the business will do about returns in the meantime. If a second sales channel is anticipated but not commissioned, record it as a known future item with an indicative shape, so that nobody later assumes it was covered.

Assumptions deserve the same visibility. Typical ones include: the receiving system's API credentials will be provided within a stated period; customer records already exist and will not be created by the integration; the product catalogue is matched by SKU and the SKUs are unique; a sandbox or test company will be available for the duration of acceptance testing. Each assumption is a dependency on the client. Written down, it becomes a shared responsibility rather than a surprise that appears in week four as a reason for delay.

Change control then becomes straightforward. If something comes to light that falls outside the agreed test — a currency nobody mentioned, a second warehouse, a requirement to push tracking numbers back to DPD-labelled despatch notes — it is priced as a variation against the same standard: a new or amended test case, an estimate, written agreement, then build. This is not bureaucracy for its own sake. It is the only way a fixed price can accommodate genuine discovery without either party feeling that they have been taken advantage of.

It is worth being candid about the cost of this approach. Writing a thorough acceptance test takes time, often a day or two of combined effort across both parties, and it happens before any code is written and before the client has seen anything working. That can feel slow. The alternative is faster at the start and slower at the end, with the slowness concentrated in the weeks immediately after go-live, when the business is live on a system that does not quite do what it needs to.

Running the test, recording the evidence and handing over

Acceptance testing should be run by the client, on their data, in an environment that resembles production closely enough for the results to mean something. The supplier's role is to prepare the environment, supply the test script and be available to investigate failures. It is not to run the test and report that it passed. A test executed only by the people who wrote the code tests the code against their understanding, which is precisely the understanding that needs checking.

Record the output. For each case, capture the input record reference, the observed result, a screenshot or export from the receiving system, and the date and initials of the person who checked it. For reconciliation cases, keep the figures. This evidence pack serves three purposes: it establishes that acceptance was met, it provides a baseline for diagnosing anything that changes later, and it gives the finance team something to show an auditor who asks how the postings in the ledger came to be there.

Expect some cases to fail on the first pass. That is the system working as intended; a test that passes entirely on the first attempt usually means the cases were written too loosely. Failures should be triaged into three buckets: defects against the agreed test, which the supplier fixes within the fixed price; requirements that were missed, which go through change control; and misunderstandings about expected behaviour, which are resolved by amending the test document so that the record remains accurate. Keeping those categories distinct prevents the slow erosion of a fixed scope integration into an open-ended one.

On acceptance, the test document, the evidence pack, the field mapping, the code and the operational documentation are handed over together. The test then keeps earning its place: when the receiving system is upgraded, when a new channel is added, or when a different supplier takes over maintenance in two years, the acceptance test is the fastest available description of what the integration is supposed to do. Very few artefacts from an integration project retain their value that long. A well-written test is one of them, and the discipline of producing it first is what makes a fixed scope integration genuinely fixed rather than merely optimistic.

Key points

  • Write the acceptance test in full, with named records and expected field-level outputs, before producing an estimate; if the test cannot be written, the scope is not yet understood.
  • Build test cases from a real extract of your own order history rather than from API documentation, and involve the warehouse supervisor and the person who closes the month.
  • Name the exclusions and assumptions explicitly, route anything outside them through written change control, and hand over the evidence pack alongside the code and documentation.