Gooze vs other Go mutation testing tools

How Gooze compares with Gremlins, go-mutesting, and go-mutants, including what Gooze does not do yet.

Last verified October 2026 against Gooze v1.1.0 and each tool's own documentation (gremlins.dev, zimmski/go-mutesting, avito-tech/go-mutesting, P4suta/go-mutants). “Not documented” means we found no mention of it, not that it's impossible. Spotted a mistake? Open an issue.

In short

  • Gooze keeps the same three commands (run, report view, report merge) from a weekend project to a large monorepo. Its per-file cache re-tests only what you changed, so local TDD loops stay fast, and every run still reports a score for the whole codebase, not just the diff. Sharding, a shared OCI baseline, a TUI viewer, and editor integration come built in.
  • Gremlins has a built-in score threshold and a git-based diff mode, but describes itself as best for “smallish” modules and is still 0.x.
  • go-mutesting is a minimal framework: write your own mutators and plug in your own test runner with --exec, at the cost of building caching, parallelism, and reporting yourself. The avito-tech fork adds a config file, JSON/HTML reports, and ignore directives.
  • go-mutants is feature-rich (threshold, git-based diff mode, sharding, outcome cache, JSON/HTML) but pre-release at the time of writing.

Feature matrix

FeatureGoozeGremlinsgo-mutestinggo-mutesting (avito-tech)go-mutants
Config file in the repo
Yes
gooze.yaml + GOOZE_* env vars
Yes
.gremlins.yaml
No
flags only
Yes
YAML via --config
Yes
.go-mutants.toml
Fail the build below a score
Partly
no flag yet; 3-line script gate
Yes
--threshold-efficacy, --threshold-mcover
Not documented
Not documented
Yes
policy.minimum_score + --strict
Test only changed code
Yes
detected by incremental execution (content hashes); no git or base ref
Yes
git diff against a ref (--diff)
Not documented
Not documented
Yes
git diff against a ref (--changed)
Incremental cache between runs
Yes
per-file, reused on any machine
Not documented
Partly
manual MD5 blacklist
Partly
manual MD5 blacklist
Yes
per-mutant outcome cache
Whole-codebase score without re-running everything
Yes
cached results + re-tested changed files
Partly
--diff tests only changed code; otherwise a full run
No
full run every time
No
full run every time
Yes
cached outcomes; --changed narrows to the diff
Split one run across CI jobs
Yes
-s INDEX/TOTAL + report merge
Not documented
Not documented
Not documented
Yes
--shard K/N + report merge
Shared baseline for CI and teammates
Yes
report push/pull to any OCI registry
Not documented
Not documented
Not documented
Not documented
Parallel workers
Yes
-p/--parallel
Yes
--workers
Partly
via a custom --exec script
Not documented
Not documented
Skip code tests never execute
Yes
--coverage-profile
Yes
NOT COVERED status
Not documented
Not documented
Yes
uncovered status
Ignore code with comments
Yes
//gooze:ignore, per file/func/line/mutator
Partly
file regex only (--exclude-files)
Partly
checksum blacklist
Yes
mutator-disable-* directives
Not documented
Write your own mutators
Partly
one small function in the gooze source; no plugin API
Partly
toggle built-ins only
Yes
Mutator interface + Register
Not documented
Not documented
Custom test runner command
No
on the roadmap
Partly
--integration runs the full suite
Yes
--exec
Yes
--exec
Yes
test.command
Machine-readable results
Yes
YAML report dir + _index.yaml
Yes
JSON (-o)
Partly
stdout
Yes
JSON and HTML
Yes
JSON (Stryker-style) and HTML
Interactive results viewer
Yes
TUI with diffs (report view)
Not documented
Not documented
Partly
static HTML report
Partly
live dashboard during the run
Results in your editor
Yes
goozels language server
Not documented
Not documented
Not documented
Not documented
Stable (1.x) CLI and config
Yes
v1.x
No
v0.x; config may change between minors
Not documented
Not documented
No
pre-release

Which one to pick

  • Pick Gooze if you want one tool that stays simple as the codebase grows: fast feedback while you write tests (only changed files re-run), a whole-codebase score on every PR, and CI that scales by adding shards. Start with the Quick start.
  • Pick Gremlins if you need a built-in threshold flag today, or want mutations limited to the exact lines a PR changed, and the module is small.
  • Pick go-mutesting if you need a fully custom test runner or want to ship mutators outside the tool's source.

Incremental execution vs git diff

Both approaches test only what changed. They differ in how they find it and what the score means afterwards.

  • Git diff (Gremlins --diff, go-mutants --changed): compare against a base branch or commit and mutate only the changed lines. Needs git history and the right base ref, and the score describes the change, not the codebase.
  • Incremental execution (Gooze): hash every file and its test file, re-test only what changed since the stored reports, and reuse the rest. No git, base ref, or fetch depth needed, uncommitted edits count, and the score after a one-file change is still the score for the whole project.

The trade-off is granularity: Gooze re-tests a whole changed file, a diff mode only the changed lines.

A file is re-tested when it, its _test.go, or the mutators change. Changes elsewhere (a helper in another file, a dependency) don't invalidate it, so run with --no-cache on a schedule, for example nightly. Details: Incremental runs.

What Gooze doesn't do (yet)

A threshold flag, custom mutator plugins, and a custom test runner are not supported in v1.1.0. Workarounds and status are on the Roadmap.

FAQ

Does gooze have a config file?

Yes. gooze.yaml in the project root holds output dir, excludes, parallelism, timeouts, and the coverage profile; gooze config init generates one. Every key can also be set with a GOOZE_* environment variable or a CLI flag.

Is gooze only for large projects?

No. The workflow is the same three commands for a small project and a large monorepo: gooze run, gooze report view, and, when you shard in CI, gooze report merge. Sharding and OCI baselines are opt-in for when a codebase outgrows a single job.

Is gooze good for TDD?

Yes. Results are cached per file, so after you edit a file or its test only that file is re-tested and the rest of the report is reused. The feedback loop stays short without losing the whole-codebase score.

Can gooze fail CI when the mutation score drops below a threshold?

Not with a built-in flag yet (as of v1.1.0). gooze prints Mutation score: NN.NN% in non-interactive output, and a three-line shell step compares it to a minimum and fails the job. The GitHub Actions and GitLab CI guides include it.

Does gooze only test changed code?

Yes, by design without git. gooze detects changes through incremental execution: it hashes each file and its test file and re-tests only what changed since the stored reports, reusing results for the rest, so the score always covers the whole codebase. No base branch, commit, or git history is needed, and uncommitted edits count. Granularity is per file, not per changed line. Changes in other files don't invalidate cached results, so run --no-cache periodically.

Can I write custom mutators for gooze?

Not as plugins. gooze ships six default operators (arithmetic, comparison, logical, boolean, numbers, unary). Adding an operator means one small function in the gooze source; caching, sharding, and reporting don't change. go-mutesting supports mutators outside the tool via its Mutator interface.

How is the gooze mutation score calculated?

killed / (all mutations - error). Mutants that do not compile (error) are left out; survived, not_covered, and timeout all lower the score.

Can gooze run across several CI machines?

Yes. gooze run -s INDEX/TOTAL runs one shard per job, and gooze report merge combines them. Ready-made GitHub Actions and GitLab CI pipelines are in the docs.