Go Tests Are Permission to Change the System
The most valuable Go tests do more than raise coverage. They expose business assumptions, protect critical workflows, and make refactoring and AI-assisted changes safer.
I do not get excited when a dashboard says a service has 95% test coverage.
I get interested when an engineer can change the service on Friday without being terrified.
That is what useful tests buy. They catch regressions, support refactoring, and put some boundaries around AI-assisted code changes. A percentage by itself buys very little.
Coverage is not confidence
An application can report 80%, 95%, or even 100% coverage and still fail in production.
Coverage tells you which lines executed during tests. It does not tell you whether the important business behavior was challenged.
On one project I worked on at Tesla, we did not use unit-test coverage as the central quality metric. We did not even have unit tests for large parts of the project. I would not copy that blindly, but it made one weakness of coverage targets obvious.
Which failures would damage users, operations, or the business, and how do we detect them before release?
I would rather see one serious integration test around a factory-critical workflow than fifty synthetic unit tests written because a quality gate demanded another ten percent.
Tests reveal hidden business rules
Every time I write a serious test, I find either an improvement to the code or an assumption I had not examined.
Billing systems are good at humiliating reasonable assumptions. A receipt total obviously cannot be negative, until a promotion makes it negative. A free order sounds suspicious, until the business runs exactly that campaign.
I encountered zero totals, negative totals, and negative tax or adjustment values. None looked sensible when considered in isolation. All were possible in the real business.
At large scale, “this probably never happens” is not a useful engineering argument.
Writing the test forces the engineer to ask the business question before production asks it more loudly.
Difficult testing is architecture feedback
Badly structured code fights back when you test it.
Hidden dependencies, business logic inside HTTP handlers, and side effects scattered through the code make every setup painful. I do not immediately reach for a mocking framework when this happens. First I ask whether the code is telling me it needs a cleaner boundary.
It may indicate that the code needs:
- explicit dependencies
- smaller responsibilities
- clearer boundaries
- isolated side effects
- a more direct representation of business rules
Almost every time I write a proper test, I find either a bug or a design decision worth improving. That is why I still recommend writing tests by hand to junior, middle, and senior engineers. The thinking is part of the exercise.
Test behavior that earns confidence
For a Go service, I usually want some combination of:
- unit tests for dense business rules
- integration tests for databases and external boundaries
- end-to-end tests for a small number of critical workflows
- example tests when executable documentation helps users
There is no universal ratio. Look at what can hurt the business, what has failed before, and which parts engineers are afraid to touch. Start there.
For related guidance, see code review mentoring and software engineer mentoring.
About the author
Aleksandr Perederei is a Principal Engineer, former Staff Software Engineer, Engineering Manager, and CTO. He has mentored 120+ engineers on system design, technical leadership, promotion evidence, career direction, and stronger engineering judgment.
Related articles
Go Architecture: Start With Boundaries, Not a Framework
Go does not give you one official application framework. Start with clear package boundaries, a simple layered design, and only add architecture when it improves delivery.
GoUse Go for LLM Orchestration, Not Model Research
Go is a strong choice for production LLM orchestration, typed tool boundaries, and agent services. Python remains the practical choice for model research and evaluation.
GoEverybody Talks About AI -- Let's Talk About Code Generators in Go
Explore Go's powerful code generation ecosystem: sqlc for type-safe SQL, OpenAPI generators for API clients and servers, and go generate as the glue. Practical examples with OpenAI, Stripe, and more.
Get engineering articles in your inbox
Practical advice on system design, technical leadership, and career growth. No spam.