My catalog parser passed every test locally for months. Then imported rows started landing with prices that were technically valid numbers and completely wrong.
The fixtures were the problem.
I had generated them with my own serializer, so the same code path that wrote them also read them back. Every field arrived already in the shape the parser expected. Encoding and decimal separators lined up, optional fields too: self-consistent all the way down. My test data got laundered through my own assumptions before the parser ever saw it.
Real input came from retail sources, piled up over years, in formats that changed without anyone telling me. Old rows with no currency on the price. A field that sometimes held a range instead of a value, and whitespace that wasn't whitespace.
The cost wasn't a crash. There wasn't one. It was quiet bad data moving downstream, and then me tracing backwards through import runs to find where it got in.
What I changed: fixtures never come from my own writer anymore. I keep a corpus of captured real payloads, anonymized, the ugly historical ones included, and a new parser has to survive that corpus before it earns a green check. Every new malformed shape production hands me goes in permanently, so the input I develop against only ever gets harsher.
A passing suite built on self-generated fixtures proves one thing: the code is consistent with itself. That is a much smaller claim than it feels like at 11pm.
I write up more of these parser and payment-pipeline failures on my blog, if that's your kind of reading: https://polycratia.com/c/bbc15722
If you run importers or integrations, your test data comes from somewhere. Probably worth knowing where...