No single test type catches every security bug. Table and unit tests catch logic and access rules, property tests catch invariant breaks, fuzzing catches parser and memory bugs, integration tests catch enforcement gaps between components, and contract tests catch interface drift. Pick by bug class.
Match the bug class to the test
Broken access control
Best: unit tests on the decision function, plus integration tests with two users or two tenants hitting real routes. Unit tests show the rule is right. Integration tests show the routes use it.
Weak: fuzzing, which has no idea who should see what, and coverage numbers.
Injection and output encoding
Best: property tests that assert no raw delimiter appears in escaped output, plus a fixed list of known payloads in unit tests. Static analysis and dynamic scans add breadth.
Parser, format and memory bugs
Best: coverage guided fuzzing with sanitizers in the build. Go's documentation describes fuzz tests as a way to feed unexpected inputs to functions, and AddressSanitizer documents the memory errors it reports, such as out of bounds access and use after free.
Authentication and session logic
Best: negative tests for expired, tampered and replayed tokens, with an injected clock for expiry. See the posts on negative tests and deterministic tests.
Race conditions
Best: integration tests that fire concurrent requests against a real database, repeated many times. Single threaded unit tests rarely find them, and a flaky failure here deserves attention instead of a retry.
Misconfiguration and cross service assumptions
Best: integration tests in an environment that matches production, and contract tests where one service assumes another's behavior. Pact describes contracts between a consumer and a provider, generated from the consumer's automated tests.
Dependency vulnerabilities
Best: software composition analysis and reachability checks, not unit tests. Tests help after the fact to confirm that an upgrade did not change behavior.
Business logic abuse
Best: abuse case tests written from a threat model: discount stacking, refund loops, quota bypass. Automated scanners rarely know your rules.
How to use this table in planning
For each feature, list the bug classes that apply, then choose at least one test type per class. Record gaps in the pull request template. Revisit the list after incidents, since each one shows a class you under-tested.
Try it yourself
The SAST code scan demo shows what static analysis reports on source code. Check which bug classes it surfaces, and which from the list above would still need a test.
Click through it at your own pace, or open it full screen.
Quick check
If I have a SAST tool, do I still need tests?
Yes. Static analysis finds patterns, but it cannot know your business rules or prove that a permission check is enforced on every route.
Safeguard covers SBOM and dependency scanning, reachability analysis and policy gates, and you can try a free scan at https://gold.safeguard.sh/scan.
Sources
Last reviewed: 19 October 2026.