All case studies

Case study

Fifteen months to write the first test. It found a defect nobody was looking for.

The integration between the shop floor and the ERP worked. Nobody was complaining. The first test to run showed that one blocked item was enough to stop every write from the floor until the session was renewed.

15 months
The integration ran with no test verifying any of it
3 days
From the tests arriving to the defect they found being fixed
1 blocked item
Was enough to stop every write from the shop floor until the session was renewed

The system

A forge, whose shop floor runs on an MES declaring production into Business Central Online through standard APIs rather than by writing to tables. Live, in production, with not one automated test on it.

First, the part that was done right

An MES is the software that runs the shop floor. It knows which station is working on what, what comes off a press, what goes to heat treatment, what gets scrapped. The ERP knows none of it: it waits to be told. Every one of those facts has a stock consequence and an accounting consequence, so the MES has to write into the ERP, continuously, while the floor is running.

The fast way to wire the two together is to let the MES write straight into Business Central’s tables, or to build it a bespoke endpoint that mirrors those tables. It works on go-live day. It breaks at the first version upgrade, and it breaks quietly.

On this project the very first thing committed to the repository, before any feature at all, was a set of standard API pages: production orders, routing lines, item, output and consumption journals, with a permission set scoped to that one use. No exposed tables, no homemade endpoint.

The difference is not cosmetic. The MES no longer talks to a database, it talks to a contract. When a line is invalid the contract refuses it. When Business Central upgrades, twice a year, on its own schedule, the contract holds. That is the subject of the Business Central API developer guide, and it is also what makes an AL extension upgrade possible without negotiating with the MES vendor first.

The same holds upstream of the floor, in quoting and costing a forging job: the same routings, the same work centres, the same material. What the MES declares in production is what the quotation promised.

Then, fifteen months of “it works”

The integration went to production and stayed there. It did its job. Nobody reported a problem. There was not one automated test on it.

That is the default state of most ERP integrations running today, and it is perfectly comfortable, because an integration with no tests tells you nothing. It does not tell you it is fine. It does not tell you it is broken either. It says nothing, and the absence of complaints gets read as proof.

A test app eventually landed in the repository. Two days later a separate commit carries a title worth reading twice: actually run the AL tests in CI. The tests had existed for two days and were not executing. Written is not run, and a test that does not run is a comment.

What the first test found was not what we were looking for

The defect we suspected was mild: we thought a refused posting still answered “fine” to the caller. A wrong answer, annoying, fixable.

The test showed something else. The refusal did reach the caller. But the code that prepares the posting binds an event subscription, and only unbinds it at the end. When the posting fails, that end is never reached. The subscription stays attached to the session.

From that point on, every later call fails. Not just the bad ones: the good ones too. One item mistakenly blocked in the master data, and all three APIs — item journal, output, consumption — refuse everything until the session is renewed. On the shop floor that means an MES that stops declaring anything, with no readable business error, in the middle of a production run.

That defect had been living there for fifteen months. It had never shown itself because it takes a refusal to wake it, and refusals are rare. It would have shown itself the day an item was blocked at the wrong moment, and nobody would have made the connection.

What that says about the rest

Two things, and the second is the uncomfortable one.

First: the contract did its job. The invalid line was refused. An integration wired straight into the tables would have written it, and the problem would be in your stock today instead of in an error message. The defect found here is a defect in the refusal handling, not in the refusal.

Second: fifteen months is too long, and the repository still shows it because we did not rewrite the history. A test is not a quality guarantee, it is a measuring instrument. Until there is one, you do not know what state your integration is in, and the absence of an outage is not information. Three days after plugging the instrument in, we had the answer.

If you have an integration nobody has tested

The question to ask is not “does it work”. It works, or you would know.

The question is what happens when it refuses something. Does the refusal reach the caller. Is the system in the same state it was before. Does the next call still work. None of those three answers comes from watching the integration run on a normal day, and all three decide what happens to your shop floor on the abnormal one.

That is exactly what a Business Central clarity review goes looking for.

Is your Business Central the problem, or the symptom?

We audit what you actually run, name what is worth keeping, and kill the rest. One conversation is usually enough to tell which one you are dealing with.

Start with clarity