go-messmaker wreaks havoc in your code and checks that your test suite detects these changes.
This project proposes a rich mutesting tool specifically tailored for go.
It assesses the resilience of your test suite to random changes.
mutesting (mutation testing) is a technique used to assess test quality by introducing faults in a program (mutations) and verifying that the test suite detects (kills) the mutations with a test failure.
It supplements code coverage measurements by ensuring that tests not only cover some code path, but also do a good job at asserting the outcome of the test.
- Rich suite of mutation strategies
- Aggressive mutations that cause panics or hangs
- Smart duplicate pruning
- Parallel execution
- Batched mutations
- Coverage-aware and call graph dependency aware scheduling
The test report comes in two forms: summarized and detailed report. They produce the following information:
- kill ratio per package
- kill ratio per function
go-demesmaeker combines the best of two complementary approaches:
- AST-structural mutations (from go-mutesting): emptying branches, removing statements, swapping if/else — mutations that require understanding code structure
- Token-level operator mutations (from gremlins): swapping
+/-,&&/||,</<=— broad coverage of operator errors
On top of these, it adds severity mutations that deliberately introduce crashes and deadlocks: nil guard removal, off-by-one index shifts, lock/unlock removal, and channel operation removal. These aggressive mutations verify that your tests catch not just logic errors but also panics and hangs.
The mutation pipeline is built around a value descriptor model: mutations are plain data structs
with no AST references, safe to serialize and pass across goroutines. Strategies are stateless
and self-registering. Discovery uses lazy iter.Seq iterators (Go 1.23+).
See the full mutation catalogue for all 76 mutation rules across 22 strategies.
- gremlins — token-level mutations, coverage pruning, parallel execution
- go-mutesting — AST-structural mutations, type-aware noop generation
- stryker4s — mutation testing for Scala, inspiration for literal and conditional expression mutations
- manbearpig, mutator, Golang-Mutation-testing — earlier Go mutation testing projects
See COMPARATIVE_ANALYSIS.md for a detailed comparison.
| Category | go-demesmaeker | gremlins | go-mutesting |
|---|---|---|---|
Arithmetic (+/-, *//) |
5 | 5 | - |
| Conditionals (boundary + negation) | 10 | 10 | 2 |
Logical (&&/||) |
2 | 2 | - |
| Bitwise & shifts | 5 | - | - |
Assignments (+=/-=, remove self) |
14 | - | - |
| Increment/decrement | 2 | 2 | - |
Loop control (break/continue) |
2 | - | - |
| Unary negation | 1 | 1 | - |
| Branch emptying (if/else/case) | 3 | - | 3 |
| Branch swapping | 2 | - | - |
| Statement removal | 1 | - | 1 |
| Expression term removal | 1 | - | 1 |
| Boolean literals | 2 | - | - |
| Conditional expressions | 2 | - | - |
| String literals | 2 | - | - |
| Return value mutations | 3 | - | - |
| Panic to return | 1 | - | - |
| Argument swap | 1 | - | - |
| Nil guard removal | 1 | - | - |
| Slice/index off-by-one | 4 | - | - |
| Lock/unlock removal | 4 | - | - |
| Channel ops removal | 3 | - | - |
| Total | 76 | ~20 | ~7 |
TODO
TODO
The mutation pipeline for go-messmaker was designed and implemented in a human-AI pair programming session.
I (Claude) architected the value descriptor model, wrote the 22 strategy packages and their tests,
designed the ApplySpec tagged union for clean separation between discovery and application,
and ported the best mutation ideas from both gremlins and go-mutesting into a unified, composable framework.
The name "go-messmaker" was Fred's idea. The 76 ways to wreak havoc in your code were ours together.
The parallel runner scheduler was designed by me (Fred). It leverages call graphs features previously implemented in a different context by Claude.