Your test suite is green. Every check passes, CI is happy, and you still can't say the one thing that actually matters: that the rule is right.
Here's how that happens. You have an eligibility rule—an account holder must be 18 or older and in a supported region. It lives in the signup form, where a validator checks the birthdate. It lives in the mobile client, which runs its own check so it can grey out the button. It lives in an internal admin tool that can override the odd edge case. And last month it started living in an AI-generated endpoint someone shipped to unblock a partner integration. Four copies of one rule, each with its own tests, and every one of those tests passing.
Then a 17-year-old opens an account from the mobile app. Not because anyone skipped testing—because the age check was tightened in three of the four places and missed in the fourth, and nothing in your suite was ever pointed at the rule. Your tests prove that each screen renders and each endpoint returns a 200. They don't prove the rule is correct, because the rule doesn't live anywhere a test can reach it.
This is the part of centralizing logic that the reuse-and-maintenance arguments skip. One home for a rule isn't only easier to change—it's the precondition for testing the rule at all. You can only verify logic that lives in one place you can see.
You're testing the symptom, not the rule
There are two kinds of test hiding under the same green checkmark, and only one of them tells you what you think it does.
A symptom test asks a question about a surface: does this endpoint return a 200 for a valid signup? Does the form show an error for a bad one? These are worth having. But look at what they actually assert—that a particular site behaves a particular way for a given input. They say nothing about whether that behavior matches the rule, and they can stay green while the rule is broken. The endpoint returns its 200 exactly as before; it just returns it for a 17-year-old now.
A rule test asks a different question: given this birthdate and this country, is the eligibility decision correct? That's the question you actually care about—the one your compliance team, your auditors, and your 3 a.m. self all care about. And here's the catch the scattered version hides: a rule test can only exist if the rule has a single address to send that question to. When the logic is smeared across four surfaces, there is no rule to test—only four shadows of it on four different walls, each with its own passing checks, none of them the rule itself.
A rule you can't point at is a rule you can't test
Step back and look at what a test needs in order to exist at all. A test is something you run against a subject: hand it inputs, assert something about the output. The subject has to be a thing you can name and call. When your eligibility rule is a form validator plus a client-side check plus an admin override plus a generated endpoint, there is no single thing to call. You can test each fragment, but the rule as a concept has no handle.
Worse is the assumption you never wrote a test for. The moment there are four copies, your system depends on all four agreeing—and agreement across copies is the one property none of your tests check. Each suite verifies its own copy in isolation. Nothing verifies that the mobile check and the endpoint check and the admin override still decide the same case the same way. So the failure isn't loud. It's a slow drift where the copies quietly diverge, and the first time you find out is when a customer or an auditor does.
The gap here isn't test effort. Teams in this situation often have plenty of tests. The gap is test surface—there is nowhere to aim a test at the rule itself.
AI code generation multiplies the places a rule can hide
This problem isn't new, but it's getting worse quickly, and it's worth being precise about why.
When you generate code surface by surface—an endpoint here, a handler there, each from its own prompt—the locally easiest thing to produce is a self-contained fragment that does its whole job inline. Ask a model to build an endpoint that opens an account, and a reasonable, working answer bakes the eligibility check right into the stack. It runs. It passes review. It's also a fifth copy of a rule you were already struggling to keep consistent across four.
This isn't a knock on AI code generation—the same instinct shows up on any team moving fast, and inline-and-working is a rational default when you're building one surface at a time. But the effect compounds. Every generated surface is a plausible new home for a rule, and the number of homes grows faster than anyone can track by reading diffs. The more you generate, the more addresses your rules acquire, and the less any single test proves about the rule as a whole. Speed multiplies the copies, and the copies are exactly what make the rule untestable.
Give the rule one address
The fix is unglamorous, and you've probably heard it argued for other reasons—reuse, maintenance, not hand-syncing four copies every time the rule moves. Testability is the payoff that's been sitting underneath those arguments the whole time.
Pull the rule into one place that every surface calls. Eligibility stops being a behavior four surfaces each reimplement and becomes a single function: inputs go in—a birthdate, a country—and a decision comes out. The form calls it. The mobile client calls it. The admin tool and the generated endpoint call it. There is now exactly one thing named "is this account eligible," and it has an address.
The moment it does, a rule test has a subject. You write it once—given this input, assert this decision—and you're testing the behavior that actually runs in production, not a copy of it. Consistency across surfaces stops being something you hope for and audit toward; it's structural, because there's only one thing for every surface to be consistent with. And coverage starts to mean what you always wanted it to mean: not how many screens you clicked through, but which of the rules your business depends on you've actually proven.
In Xano, the rule's home is also its test surface
This is the shape of a Xano backend, and the platform's testing story follows directly from that shape. A shared rule lives in a function stack—business logic you build visually, save as a custom function, and call from every endpoint, background task, and trigger that needs it. Change it in that one place and the change is in effect everywhere it's used. That's the reusable, addressable home the argument above asks for, with one addition: you can see it. The whole rule is laid out as steps you can read, not logic buried in four repositories.
Because the rule has one visible home, you can point a test straight at it. Xano lets you create a unit test from the same Run & Debug view where you watch the function stack execute; the test is defined by its inputs and its expects—the decisions you assert are correct. And the Test & Deploy view shows coverage of the rules rather than the screens: where the logic that runs in production is verified, and where it isn't. What you see is what runs—and now what you see is also what you test.
The rule you can see is the rule you can prove
You can't test your way to confidence in logic you can't see. All the coverage in the world, aimed at surfaces, still leaves the actual rule unproven—and scattered rules are the ones that fail quietly, in production, one drifted copy at a time. Give the rule a single home you can look at, and "we think it works" becomes "here's the test that proves it."
If you're evaluating how to reduce duplicated business rules, improve testing, and build AI-assisted applications with a single source of truth, we'd be happy to walk you through how teams implement this workflow in Xano.
Book a demo to see how reusable function stacks, built-in testing, and centralized backend logic work together in a real application.






