Do you find yourself saying things that are so absurd you’d not believe it if you hadn’t lived through it? I’ve had a few of those experiences.
I once worked at a software company that had a strong unit test culture. There were specifications for everything and tests for everything. Sounds great, right? Unfortunately, despite extensive review meetings, the specifications never survived the few first days of coding. The unit tests were detailed and thorough–fantastic! But no one ever ran the whole product in-house. QA didn’t. Developers didn’t. The company didn’t use its own product because “it is too complicated.” After I left the company, I had a problem that the company’s product was designed to solve. As a shareholder, I was interested in the company having customers, and happy to be one. I downloaded the product and installed it. When I fired it up, the product crashed about 3 lines into main(). No one had ever used the product. It’s great to prove that the pieces work individually, but your customers will be using them when they are all bolted together. You have to make sure the holes line up.
I also once worked at a company with the exact opposite approach. There were no unit tests of any kind. No libraries, no modules, nothing. The only way to test anything was to run the product. This meant there were very few crashes on the third line of main(), but it also made it impossible to know whether or not any of the pieces of the code work independently. If you can determine whether pieces work independently, you can track those results, tie them to check-ins, and suddenly understand a heck of a lot about what changes in your source control impacted what areas of the product. You can track down not only data corruption but also which modules hit performance issues, whether within a unit test context or within an integration context within a customer environment.
The first company had a hard time getting customers to be successful with the product. The second company had difficulty predicting when a release would be ready. The former is easier to fix–start using the product internally and also fix the QA organization to include system tests. The latter likely entails an expensive refactor and reflects deeper cultural issues of a hacking organization rather than an engineering organization. Neither extreme is healthy.