Skip to content

Mutation Operators — Cross-Framework Reference

A comprehensive catalog of mutation operators across the mutation testing ecosystem. Compiled as a reference for irradiate's operator coverage and future development.

irradiate (current)

27 operator categories, ~160+ distinct mutations. Python-specific, operates on tree-sitter CST.

Operators implemented

Category Operator Details
Binary ops binop_swap 11 pairs: +-, */, ///, %/, ***, <<>>, &\|, ^&
Boolean ops boolop_swap andor
Comparison ops compop_swap 10 pairs: <=<, >=>, <<=, >>=, ==!=, isis not, innot in
Augmented assign augop_swap 11 pairs: +=-=, *=/=, //=/=, %=/=, **=*=, <<=>>=, &=\|=, ^=&=
Unary ops unary_removal not xx, ~xx
Unary sign unary_swap +x-x
String methods method_swap 15 pairs: lowerupper, lstriprstrip, findrfind, ljustrjust, indexrindex, removeprefixremovesuffix, partitionrpartition
Constants name_swap TrueFalse, deepcopycopy
Numbers number_mutation nn+1 (int and float)
Strings string_mutation "foo""XXfooXX" (skip docstrings, delimiter-containing)
String emptying string_emptying "foo""" (catches empty-string handling bugs)
Lambdas lambda_mutation body→None (or None0)
Assignments assignment_mutation value→None (or None"")
Aug-to-plain augassign_to_assign x += 5x = 5
Arg removal arg_removal Remove each arg individually (skip len(), isinstance(), generators)
Dict kwargs dict_kwarg dict(foo=1)dict(fooXX=1)
Default args default_arg Mutate default parameter values (None"", TrueFalse, nn+1, etc.)
Return values return_value return xreturn None (or None"")
Exception types exception_type except ValueError:except Exception: (broaden handler)
Match cases match_case_removal Remove each case branch (when >1 case)
Condition negation condition_negation if cond:if not (cond):, while cond:while not (cond):, assert condassert not (cond), ternary conditions
Condition replacement condition_replacement if cond:if True: / if False:, while cond:while True: / while False:, elif (skip if already literal)
Statement deletion statement_deletion x = exprpass, return xreturn None, foo()pass, raise Epass
Keyword swap keyword_swap breakcontinue
Loop mutation loop_mutation for x in items:for x in []:, while cond:while False:
Ternary swap ternary_swap a if cond else bb if cond else a (skip identical branches)
Slice index removal slice_index_removal Remove start/stop/step: x[1:3]x[:3]/x[1:], x[1:5:2]x[:5:2]/x[1::2]/x[1:5:]

Skip rules

  • Decorated functions (any decorator) — skipped entirely (trampoline incompatibility)
  • Enum subclass methods (Enum, IntEnum, StrEnum, Flag, IntFlag) — EnumMeta metaclass conflicts
  • Functions containing nonlocal — trampoline extraction breaks scope chains
  • __getattribute__, __setattr__, __new__
  • len(), isinstance() calls (arg_removal skipped — trivially killed, noisy)
  • Generator expression / comprehension arguments (arg_removal skipped — invalid syntax)
  • Triple-quoted strings (docstrings) — string_mutation and string_emptying skipped
  • Strings containing their own delimiter character
  • # pragma: no mutate lines

Python Ecosystem

mutmut

The reference implementation irradiate descends from. Uses LibCST for parsing.

Operators largely overlap with irradiate. Notable additions beyond irradiate's current set: - String literal case mutations: "FooBar""foobar", "foobar""FOOBAR" - Dict keyword argument mutation: dict(a=1)dict(aXX=1) - breakreturn, continuebreak keyword swaps - splitrsplit (conditional on maxsplit arg)

cosmic-ray

Parso-based. Takes a combinatorial approach — generates all pairwise permutations.

Category Approach
Binary ops All 132 pairwise permutations of 12 operators
Comparison ops All 56 pairwise permutations of 8 operators (context-aware: filters by RHS type)
Unary ops 5 states (+, -, ~, not, deletion) — all valid permutations
Booleans TrueFalse, andor, condition negation (if condif not cond, applies to if/while/assert/ternary)
Numbers n+1 and n-1 (both directions)
Break/continue breakcontinue
Exceptions Replace exception type with CosmicRayTestingException
Decorators Remove each decorator individually
Loops for x in itemsfor x in [] (zero iteration)
Experimental Variable replacement (inject random int), variable insertion (inject variable into expression)

mutpy

Python ast-based. Follows classical academic mutation operator naming (AOR, ROR, etc.). Has the richest OOP-specific operators.

Category Operators
Arithmetic AOD (unary deletion), AOR (full pairwise replacement)
Assignment ASR (augmented assignment replacement)
Logical COD (remove not), COI (insert not), LCR (andor), LOD (remove ~), LOR (bitwise swap)
Relational ROR (pairwise including <> cross-swaps)
Constants CRP: 56, "hello""mutpy", "mutpy""python"
Break/continue BCR: breakcontinue
Decorators DDL: remove all decorators
Exceptions EHD (handler→raise), EXS (handler→pass)
Inheritance IHD (remove shadowing assignment), IOD (delete overriding method body), IOP (move super() call position), SCD (delete super() call), SCI (insert super() call)
Slicing SIR: remove lower/upper/step from slices
Statements SDL: delete assignment/return/expression→pass
Self SVD: self.xx (remove self prefix)
Loops OIL (one iteration: add break), RIL (reverse: wrap in reversed()), ZIL (zero iteration: body→break)
Experimental CDI (insert @classmethod), SDI (insert @staticmethod)

JVM Ecosystem

PIT (pitest) — Java

The most widely-used Java mutation tester. Operates on bytecode. Operators grouped into tiers: OLD_DEFAULTS, DEFAULTS, STRONGER, ALL. Commercial extension Arcmutate adds EXTENDED/EXTREME.

DEFAULTS group (recommended production set):

Operator Description
CONDITIONALS_BOUNDARY <<=, <=<, >>=, >=>
INCREMENTS i++i-- and vice versa
INVERT_NEGS -xx
MATH +-, */, %*, &\|, ^&, <<>>, >>><<
NEGATE_CONDITIONALS ==!=, <=>, >=<, <>=, ><=
VOID_METHOD_CALLS Remove void method calls
EMPTY_RETURNS return "foo"return "", return Optional.of(x)return Optional.empty(), etc.
FALSE/TRUE_RETURNS return truereturn false and vice versa
NULL_RETURNS return objreturn null
PRIMITIVE_RETURNS return 42return 0 (or 01)

ALL/Experimental (additional):

Operator Description
CONSTRUCTOR_CALLS new Foo()null
INLINE_CONSTS Mutate constants: booleans flip, numbers ±1
NON_VOID_METHOD_CALLS Remove non-void calls, replace return with default
REMOVE_CONDITIONALS Replace condition with true or false (4 variants)
EXPERIMENTAL_AOR Full pairwise arithmetic: +-,*,/,% (4 sub-mutators)
EXPERIMENTAL_AOD Replace a + b with a or b (operand deletion)
EXPERIMENTAL_ROR Full pairwise relational (5 sub-mutators per operator)
EXPERIMENTAL_CRCR 6 constant replacement strategies: →1, →0, →-1, negate, ±1
EXPERIMENTAL_OBBN Bitwise swap + operand deletion
EXPERIMENTAL_UOI Insert ++/-- around variable uses
EXPERIMENTAL_SWITCH Swap default switch label with first non-default
EXPERIMENTAL_ARGUMENT_PROPAGATION Replace method call with one of its arguments
EXPERIMENTAL_NAKED_RECEIVER Replace foo.bar() with foo
EXPERIMENTAL_MEMBER_VARIABLE Replace field initializer with default

Arcmutate EXTENDED (commercial):

Stream/builder-specific: REMOVE_DISTINCT, REMOVE_FILTER, REMOVE_LIMIT, REMOVE_SKIP, REMOVE_SORTED, REMOVE_PREDICATE_NEGATION/AND/OR, CHAINED_CALLS removal, SWAP_PARAMS, SWAP_ALL_MATCH, varargs removal, reactive map swaps (concatMapflatMapswitchMap).

Major — Java

Compiler plugin (source-level). 9 operator categories following classical naming.

Operator Key feature
AOR All 4 alternative replacements per arithmetic op
COR &&a/b/false/==; \|\|a/b/true/!=; conditions→true/false
LOR Bitwise swap + operand deletion (a & ba, b)
ROR 3-5 replacements per relational op including true/false
SOR Shift operator pairwise swap + LHS operand
ORU Unary: -aa/~a, ~aa/-a, +a-a
LVR Literals: 01,-1; c0,c±1,-c; ""↔sentinel; truefalse
EVR Replace expressions with type defaults (0/null/true/false)
STD Statement deletion — remove calls, assignments, increments, returns, break, continue

Stryker4s — Scala

AST-level, Scala-specific.

Unique features: - 18 Scala method expression swaps: filterfilterNot, existsforall, takedrop, takeRightdropRight, takeWhiledropWhile, isEmptynonEmpty, indexOflastIndexOf, maxmin, maxByminBy - Regex mutation via weapon-regex library (20+ patterns: anchor removal, class negation, quantifier removal, lookaround inversion, Unicode property swap) - Conditional replacement: if(cond)if(true)/if(false), while(cond)while(false)


JavaScript/TypeScript Ecosystem

Stryker Mutator — JS/TS

The most comprehensive JS/TS mutation tester.

Category Operators
Arithmetic +-, */, %*
Assignment 14 pairs including ??=&&=
Equality 12 operators: boundary (<<=) + negation (<>=) + strict (===!==)
Logical &&\|\|, ??&&
Boolean truefalse, !xx
Unary +x-x
Update ++-- (pre and post)
Block statement Empty function body
Conditional Replace loop/if condition with true/false
String "foo""", """Stryker was here!", template literal→empty
Array [1,2,3][], new Array(1,2,3)new Array()
Object {foo: 'bar'}{}
Optional chaining foo?.barfoo.bar, foo?.()foo()
Method expression 20 swaps: endsWithstartsWith, toUpperCasetoLowerCase, someevery, Math.minMath.max, trimtrimEnd, plus removals (sort, filter, reverse, slice)
Regex 26 operators: anchor removal, class negation, \d\D, \s\S, \w\W, quantifier removal, lookaround inversion, Unicode property swap

C#/.NET Ecosystem

Stryker.NET

Shares the Stryker operator taxonomy with JS/TS-specific additions.

Notable unique operators: - LINQ method swaps (35 pairs): AllAny, FirstLast, SkipTake, OrderByOrderByDescending, UnionIntersect, ConcatExcept, MinMax, CountSum, etc. - Math method swaps (23): trig function cross-swaps (SinCosTan and hyperbolic variants), FloorCeiling, ExpLog - String methods (16): StartsWithEndsWith, ToLowerToUpper, TrimStartTrimEnd, PadLeftPadRight, IndexOfLastIndexOf, Trim"", Substring"" - Initialization emptying: arrays, lists, dictionaries, objects→empty - Removal mutators: method call removal, return removal, break/continue/goto/throw removal, yield removal - Checked statement removal: checked(expr)expr - Null-coalescing: a ?? bb ?? a, a, b - Regex: 37 operators (most comprehensive regex mutation of any tool)


Rust Ecosystem

cargo-mutants

Operates on Rust source. Unique approach: function body replacement is the primary strategy.

Category Approach
Function body replacement Replace entire body with type-appropriate default: ()/0/1/-1/true/false/String::new()/"xyzzy"/None/Ok(default)/vec![]/Default::default() etc.
Binary ops Multi-replacement: +-,*; -+,/; *+,/; etc.
Assignment ops Multi-replacement: +=-=,*=; etc.
Comparison ==!=, <==,>; etc.
Logical &&\|\|,==,!=; \|\|&&,==,!=
Unary -xx, !xx (deletion only)
Match arms Delete non-wildcard arm (when wildcard exists), guard→true/false
Struct fields Delete field (only when ..Default::default() base exists)

C/C++ Ecosystem

Mull (LLVM-based)

Operates on LLVM IR. 44 operators.

Standard set: arithmetic (6), arithmetic assignment (5), comparison (6), boundary (4), bitwise (6), bitwise assignment (5), increment/decrement (4), logical (2), constant assignment (2), function call removal/replacement (2).


PHP Ecosystem

Infection

The most operator-rich framework overall. 200+ distinct mutation operators.

Unique operators not found elsewhere: - Function unwrapping (49): strip a function call, return its first argument (array_filter($a, $f)$a, strtolower($s)$s, etc.) - Return value mutations (11): return $thisreturn null, return func()func(); return null, return $arrreturn array_slice($arr, 0, 1, true) - Type cast removal (6): (int)$v$v, (string)$v$v, etc. - Loop mutations (6): foreach($x as ...)foreach([] as ...), while($c)while(false), do{} while($c)do{} while(false) - Exception mutations (3): remove throw, remove finally, unwrap try/finally - Visibility reduction: publicprotected, protectedprivate - Catch block dissection: remove individual exception types from catch (A|B $e) - Ternary branch swap: $x ? $a : $b$x ? $b : $a - Null-safe removal: $obj?->method()$obj->method() - Spread mutations: [...$arr]$arr, [...$arr, 2][[...$arr][0], 2] - Rounding family (6): roundfloorceil (all pairwise) - BCMath/MBString: replace arbitrary-precision and multibyte functions with standard equivalents


Cross-Ecosystem Comparison Matrix

Operators that exist in 3+ ecosystems are considered "universal". Operators unique to 1-2 tools are noted.

Operator Category Python (irradiate) Python (others) JVM JS/TS C#/.NET Rust C/C++ PHP
Arithmetic swap Yes Yes Yes Yes Yes Yes Yes Yes
Comparison boundary Yes Yes Yes Yes Yes Yes Yes Yes
Comparison negation Yes Yes Yes Yes Yes Yes Yes Yes
Boolean andor Yes Yes Yes Yes Yes Yes -- Yes
truefalse Yes Yes Yes Yes Yes Yes -- Yes
Negation removal (not/!) Yes Yes -- Yes Yes Yes Yes Yes
Augmented assign swap Yes Yes -- Yes Yes Yes Yes Yes
Aug assign→plain assign Yes mutmut -- -- -- -- -- Yes
Number literal ±1 Yes Yes Yes -- -- -- Yes Yes
String mutation Yes (XX + emptying) Yes -- Yes Yes Yes -- --
Unary +- Yes mutmut Yes Yes Yes -- Yes --
Increment ++-- n/a n/a Yes Yes Yes -- Yes Yes
Method swaps Yes (string) mutmut Arcmutate Yes Yes (LINQ) -- -- --
Void method removal -- -- Yes -- Yes -- Yes Yes
Return value replacement Yes -- Yes -- -- Yes Yes Yes
Function body→default -- -- PIT Extreme Yes (block) Yes (block) Yes (primary) -- --
Statement deletion Yes mutpy Yes (Major) -- Yes -- -- --
Decorator removal -- cosmic-ray, mutpy -- -- -- -- -- --
Exception handler mutation Yes cosmic-ray, mutpy -- -- -- -- -- Yes
Condition→true/false Yes cosmic-ray Yes Yes Yes -- -- --
Condition negation (insert not) Yes cosmic-ray, mutpy -- -- -- -- -- Yes
Loop zero iteration Yes cosmic-ray, mutpy -- -- -- -- -- Yes
Slice index removal Yes mutpy -- -- -- -- -- --
self.xx -- mutpy -- -- -- -- -- --
super() manipulation -- mutpy -- -- -- -- -- --
Regex mutation -- -- -- Yes (26) Yes (37) -- -- Yes (5)
Optional chaining removal -- -- -- Yes -- -- -- Yes
Array/collection emptying -- -- -- Yes Yes -- -- Yes
Object literal emptying -- -- -- Yes Yes -- -- --
Type cast removal -- -- -- -- -- -- -- Yes
Function unwrapping -- -- -- -- -- -- -- Yes (49)
Ternary branch swap Yes -- -- -- -- -- -- Yes
Match/case removal Yes mutmut -- -- -- Yes -- Yes
Argument removal Yes mutmut Arcmutate -- -- -- -- --
Lambda body mutation Yes mutmut -- -- -- -- -- --
breakcontinue Yes mutmut, mutpy, CR -- -- -- -- -- Yes
Visibility reduction -- -- -- -- -- -- -- Yes
Struct/object field deletion -- -- -- -- -- Yes -- --
Match arm guard mutation -- -- -- -- -- Yes -- --
Constant→42 -- -- PIT (CRCR) -- -- -- Yes --
Operand deletion (a+ba) -- -- PIT, Major -- -- -- -- --
Argument propagation -- -- PIT, Arcmutate -- -- -- -- --

Opportunities for irradiate

Operators implemented by multiple frameworks that irradiate does not yet have, ranked by likely value for Python.

Implemented (March 2026)

The following gaps from the original audit have been closed:

  • ~~Condition negation~~ — condition_negation operator: if cond:if not (cond):, while, assert, ternary
  • ~~Condition→true/false~~ — condition_replacement operator: if cond:if True:/if False:, while, elif
  • ~~Statement deletion~~ — statement_deletion operator: assign→pass, return→return None, expr→pass, raise→pass
  • ~~breakcontinue~~ — keyword_swap operator
  • ~~Exception handler mutation~~ — exception_type operator: broaden to except Exception:
  • ~~Zero-iteration loop~~ — loop_mutation operator: for x in items:for x in []:, while cond:while False:
  • ~~Return value replacement~~ — return_value operator: return xreturn None
  • ~~Ternary branch swap~~ — ternary_swap operator: a if cond else bb if cond else a
  • ~~String emptying~~ — string_emptying operator: "foo"""
  • ~~Unary +-~~ — unary_swap operator
  • ~~Slice index removal~~ — slice_index_removal operator: x[1:3]x[:3]/x[1:], three-part slices

Remaining opportunities

  1. Decorator removal — Remove @decorator individually (cosmic-ray, mutpy). Blocked: trampoline architecture skips decorated functions entirely. Requires architectural changes to support.
  2. Constant replacement (420, 01, c-c) — More aggressive than current n+1. May produce many equivalent mutants.
  3. self.xx — mutpy only. Tests that self is correctly used. Narrow.
  4. super() manipulation — mutpy only. Tests inheritance chains. Narrow.
  5. Regex mutation — Applicable but complex. Would need a regex parser.

Not applicable to Python

  • Visibility reduction — No access modifiers.
  • Type cast removal — No explicit casts.
  • Optional chaining — No ?. operator.
  • ++/-- swap — No increment operators.