All Stryker versions support a variety of different mutators. We've aligned on a standard naming scheme so it is easy to switch and compare implementations. The difference in support is listed below.
| Original |
Mutated |
a + b |
a - b |
a - b |
a + b |
a * b |
a / b |
a / b |
a * b |
a % b |
a * b |
🔝 Back to Top
| Original |
Mutated |
new Array(1, 2, 3, 4) |
new Array() |
[1, 2, 3, 4] |
[ ] |
🔝 Back to Top
| Original |
Mutated |
+= |
-= |
-= |
+= |
*= |
/= |
/= |
*= |
%= |
*= |
<<= |
>>= |
>>= |
<<= |
&= |
|= |
|= |
&= |
??= |
&&=¹ |
- ¹: Only supported by Stryker-JS
🔝 Back to Top
Removes the content of every block statement. For example the code:
function saySomething() {
console.log('Hello world!');
}
becomes:
function saySomething() {}
🔝 Back to Top
| Original |
Mutated |
true |
false |
false |
true |
!(a == b) |
a == b ¹ |
- ¹: Not supported by Stryker4s
🔝 Back to Top
Stryker.NET specific mutator
| Original |
Mutated |
checked(2 + 4) |
2 + 4 |
🔝 Back to Top
| Original |
Mutated |
for (var i = 0; i < 10; i++) { } |
for (var i = 0; false; i++) { } ¹ |
while (a > b) { } |
while (false) { } |
do { } while (a > b); |
do { } while (false); |
if (a > b) { } |
if (true) { } |
if (a > b) { } |
if (false) { } |
var x = a > b ? 1 : 2; |
var x = true ? 1 : 2; ¹ |
var x = a > b ? 1 : 2; |
var x = false ? 1 : 2; ¹ |
- ¹: Not supported by Stryker4s
🔝 Back to Top
| Original |
Mutated |
a < b |
a <= b |
a < b |
a >= b |
a <= b |
a < b |
a <= b |
a > b |
a > b |
a >= b |
a > b |
a <= b |
a >= b |
a > b |
a >= b |
a < b |
a == b |
a != b |
a != b |
a == b |
a === b |
a !== b ¹ |
a !== b |
a === b ¹ |
- ¹: Only supported on StrykerJS and Stryker4s
🔝 Back to Top
| Original |
Mutated |
a && b |
a || b |
a || b |
a && b |
a ?? b |
a && b |
🔝 Back to Top
Due to differences in language syntax, method expressions are implemented differently in each Stryker framework:
| Original |
Mutated |
endsWith() |
startsWith() |
startsWith() |
endsWith() |
trim() |
|
trimEnd() |
trimStart() |
trimStart() |
trimEnd() |
substr() |
|
substring() |
|
toUpperCase() |
toLowerCase() |
toLowerCase() |
toUpperCase() |
toLocalLowerCase() |
toLocalUpperCase() |
toLocalUpperCase() |
toLocalLowerCase() |
sort() |
|
some() |
every() |
every() |
some() |
reverse() |
|
filter() |
|
slice() |
|
charAt() |
|
| Original |
Mutated |
Distinct() |
|
Reverse() |
|
OrderBy() |
|
OrderByDescending() |
|
SingleOrDefault() |
FirstOrDefault() |
FirstOrDefault() |
SingleOrDefault() |
First() |
Last() |
Last() |
First() |
All() |
Any() |
Any() |
All() |
Skip() |
Take() |
Take() |
Skip() |
SkipWhile() |
TakeWhile() |
TakeWhile() |
SkipWhile() |
Min() |
Max() |
Max() |
Min() |
Sum() |
Count() |
Count() |
Sum() |
| Original |
Mutated |
a.filter(b) |
a.filterNot(b) |
a.filterNot(b) |
a.filter(b) |
a.exists(b) |
a.forall(b) |
a.forall(b) |
a.exists(b) |
a.take(b) |
a.drop(b) |
a.drop(b) |
a.take(b) |
a.takeRight(b) |
a.dropRight(b) |
a.dropRight(b) |
a.takeRight(b) |
a.takeWhile(b) |
a.dropWhile(b) |
a.dropWhile(b) |
a.takeWhile(b) |
a.isEmpty |
a.nonEmpty |
a.nonEmpty |
a.isEmpty |
a.indexOf |
a.lastIndexOf(b) |
a.lastIndexOf(b) |
a.indexOf(b) |
a.max |
a.min |
a.min |
a.max |
a.maxBy(b) |
a.minBy(b) |
a.minBy(b) |
a.maxBy(b) |
🔝 Back to Top
| Original |
Mutated |
{ foo: 'bar' } |
{ } |
🔝 Back to Top
| Original |
Mutated |
foo?.bar |
foo.bar |
foo?.[1] |
foo[1] |
foo?.() |
foo() |
🔝 Back to Top
Regular expressions are parsed and mutated separately. This is done by recognizing new Regex("...") call signatures in each language. Scala and JavaScript also have shorthand syntax, /regex/ and "regex".r respectively, which are mutated as well.
StrykerJS and Stryker4s use the awesome ⚔ weapon-regex to mutate their regular expressions. All Level 1 mutations are generated.
Strings and literals identified to a regex are mutated in the following way:
| Original |
Mutated |
^abc |
abc |
abc$ |
abc |
[abc] |
[^abc] |
[^abc] |
[abc] |
\d |
\D |
\D |
\d |
\s |
\S |
\S |
\s |
\w |
\W |
\W |
\w |
a? |
a |
a* |
a |
a+ |
a |
a{1,3} |
a |
a*? |
a |
a+? |
a |
a{1,3}? |
a |
a?+ |
a |
a*+ |
a |
a++ |
a |
a{1,3}+ |
a |
(?=abc) |
(?!abc) |
(?!abc) |
(?=abc) |
(?<=abc) |
(?<!abc) |
(?<!abc) |
(?<=abc) |
\p{Alpha} |
\P{Alpha} ¹ |
\P{Alpha} |
\p{Alpha} ¹ |
\P{Alpha} |
\p{Alpha} ¹ |
¹ JVM only.
🔝 Back to Top
| Original |
Mutated |
"foo" (non-empty string) |
"" (empty string) |
"" (empty string) |
"Stryker was here!" |
s"foo ${bar}" (string interpolation) |
s"" ¹ |
¹ For Stryker4s, only works with string interpolation and not other types of interpolation (like Scalameta quasiquotes) to avoid compile errors
🔝 Back to Top
| Original |
Mutated |
+a |
-a |
-a |
+a |
🔝 Back to Top
| Original |
Mutated |
a++ |
a-- |
a-- |
a++ |
++a |
--a |
--a |
++a |
🔝 Back to Top
| Original |
Mutated |
Acos() |
Acosh() |
Acos() |
Asin() |
Acos() |
Atan() |
Acosh() |
Acos() |
Acosh() |
Asinh() |
Acosh() |
Atanh() |
Asin() |
Asinh() |
Asin() |
Acos() |
Asin() |
Atan() |
Asinh() |
Asin() |
Asinh() |
Acosh() |
Asinh() |
Atanh() |
Atan() |
Atanh() |
Atan() |
Acos() |
Atan() |
Asin() |
Atanh() |
Atan() |
Atanh() |
Acosh() |
Atanh() |
Asinh() |
BitDecrement() |
BitIncrement() |
BitIncrement() |
BitDecrement() |
Ceiling() |
Floor() |
Cos() |
Cosh() |
Cos() |
Sin() |
Cos() |
Tan() |
Cosh() |
Cos() |
Cosh() |
Sinh() |
Cosh() |
Tanh() |
Exp() |
Log() |
Floor() |
Ceiling() |
Log() |
Exp() |
Log() |
Pow() |
MaxMagnitude() |
MinMagnitude() |
MinMagnitude() |
MaxMagnitude() |
Pow() |
Log() |
ReciprocalEstimate() |
ReciprocalSqrtEstimate() |
ReciprocalSqrtEstimate() |
ReciprocalEstimate() |
ReciprocalSqrtEstimate() |
Sqrt() |
Sin() |
Sinh() |
Sin() |
Cos() |
Sin() |
Tan() |
Sinh() |
Sin() |
Sinh() |
Cosh() |
Sinh() |
Tanh() |
Tan() |
Tanh() |
Tan() |
Cos() |
Tan() |
Sin() |
Tanh() |
Tan() |
Tanh() |
Cosh() |
Tanh() |
Sinh() |