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.
Supportโ
Arithmetic Operatorโ
| Mutant operator | Original | Mutated |
|---|
| AdditionNegation | a + b | a - b |
| SubtractionNegation | a - b | a + b |
| MultiplicationNegation | a * b | a / b |
| DivisionNegation | a / b | a * b |
| RemainderToMultiplication | a % b | a * b |
๐ Back to Top
Array Declarationโ
| Mutant operator | Original | Mutated |
|---|
| ArrayConstructorItemsRemoval | new Array(1, 2, 3, 4) | new Array() |
| ArrayLiteralItemsRemoval | [1, 2, 3, 4] | [ ] |
๐ Back to Top
Assignment Expressionโ
| Mutant operator | Original | Mutated |
|---|
| AdditionAssignmentNegation | += | -= |
| SubtractionAssignmentNegation | -= | += |
| MultiplicationAssignmentNegation | *= | /= |
| DivisionAssignmentNegation | /= | *= |
| RemainderAssignmentToMultiplicationAssignment | %= | *= |
| LeftShiftAssignmentNegation | <<= | >>= |
| RightShiftAssignmentNegation | >>= | <<= |
| LeftShiftAssignmentToUnsignedRightShiftAssignment | <<= | >>>=ยฒ |
| RightShiftAssignmentToUnsignedRightShiftAssignment | >>= | >>>=ยฒ |
| UnsignedRightShiftAssignmentToLeftShiftAssignment | >>>= | <<=ยฒ |
| UnsignedRightShiftAssignmentToRightShiftAssignment | >>>= | >>=ยฒ |
| BitwiseAndAssignmentNegation | &= | |= |
| BitwiseOrAssignmentNegation | |= | &= |
| NullCoalescingAssignmentToAndAssignment | ??= | &&=ยน |
- ยน: Only supported by Stryker-JS
- ยฒ: Only supported by Stryker.NET
๐ Back to Top
Block Statementโ
This group has one mutant operator, the BlockRemoval mutant operator. This mutant operator removes the content of every block statement. For example the code:
function saySomething() {
console.log('Hello world!');
}
becomes:
function saySomething() {}
๐ Back to Top
Boolean Literalโ
| Mutant operator | Original | Mutated |
|---|
| TrueNegation | true | false |
| FalseNegation | false | true |
| NotRemoval | !(a == b) | a == b ยน |
- ยน: Not supported by Stryker4s
๐ Back to Top
Checked Statementโ
Stryker.NET specific mutator
| Mutant operator | Original | Mutated |
|---|
| CheckedRemoval | checked(2 + 4) | 2 + 4 |
๐ Back to Top
Conditional Expressionโ
| Mutant Operator | Original | Mutated |
|---|
| LessThanToFalse | for (var i = 0; i < 10; i++) { } | for (var i = 0; false; i++) { } ยน |
| GreaterThanToFalse | while (a > b) { } | while (false) { } |
| GreaterThanToFalse | do { } while (a > b); | do { } while (false); |
| GreaterThanToTrue | if (a > b) { } | if (true) { } |
| GreaterThanToFalse | if (a > b) { } | if (false) { } |
| GreaterThanToTrue | var x = a > b ? 1 : 2; | var x = true ? 1 : 2; ยน |
| GreaterThanToFalse | var x = a > b ? 1 : 2; | var x = false ? 1 : 2; ยน |
- ยน: Not supported by Stryker4s
๐ Back to Top
Equality Operatorโ
| Mutant operator | Original | Mutated |
|---|
| LessThanBoundary | a < b | a <= b |
| LessThanNegation | a < b | a >= b |
| LessThanEqualBoundary | a <= b | a < b |
| LessThanEqualNegation | a <= b | a > b |
| GreaterThanBoundary | a > b | a >= b |
| GreaterThanNegation | a > b | a <= b |
| GreaterThanEqualBoundary | a >= b | a > b |
| GreaterThanEqualNegation | a >= b | a < b |
| EqualityNegation | a == b | a != b |
| InequalityNegation | a != b | a == b |
| StrictEqualityNegation | a === b | a !== b ยน |
| StrictInequalityNegation | a !== b | a === b ยน |
- ยน: Only supported on StrykerJS and Stryker4s
๐ Back to Top
Logical Operatorโ
| Mutant operator | Original | Mutated |
|---|
| AndNegation | a && b | a || b |
| OrNegation | a || b | a && b |
| NullCoalescingToAnd | a ?? b | a && b |
๐ Back to Top
Method Expressionโ
Due to differences in language syntax, method expressions are implemented differently in each Stryker framework:
StrykerJSโ
| Mutant operator | Original | Mutated |
|---|
| EndsWithToStartsWith | endsWith() | startsWith() |
| StartsWithToEndsWith | startsWith() | endsWith() |
| TrimToTrimEnd | trim() | trimEnd() |
| TrimToTrimStart | trimEnd() | trimStart() |
| TrimToTrimEnd | trimStart() | trimEnd() |
| SubstrRemoval | substr() | |
| SubstringRemoval | substring() | |
| UpperCaseToLowerCase | toUpperCase() | toLowerCase() |
| LowerCaseToUpperCase | toLowerCase() | toUpperCase() |
| LocalLowerCaseToLocalUpperCase | toLocalLowerCase() | toLocalUpperCase() |
| LocalUpperCaseToLocalLowerCase | toLocalUpperCase() | toLocalLowerCase() |
| SortRemoval | sort() | |
| SomeToEvery | some() | every() |
| EveryToSome | every() | some() |
| ReverseRemoval | reverse() | |
| FilterRemoval | filter() | |
| SliceRemoval | slice() | |
| CharAtRemoval | charAt() | |
| MinToMax | min() | max() |
| MaxToMin | max() | min() |
Stryker.NETโ
| Mutant operator | Original | Mutated |
|---|
| DistinctRemoval | Distinct() | |
| ReverseRemoval | Reverse() | |
| OrderByRemoval | OrderBy() | |
| OrderByDescendingRemoval | OrderByDescending() | |
| SingleOrDefaultToFirstOrDefault | SingleOrDefault() | FirstOrDefault() |
| FirstOrDefaultToSingleOrDefault | FirstOrDefault() | SingleOrDefault() |
| FirstToLast | First() | Last() |
| LastToFirst | Last() | First() |
| AllToAny | All() | Any() |
| AnyToAll | Any() | All() |
| SkipToTake | Skip() | Take() |
| TakeToSkip | Take() | Skip() |
| SkipWhileToTakeWhile | SkipWhile() | TakeWhile() |
| TakeWhileToSkipWhile | TakeWhile() | SkipWhile() |
| MinToMax | Min() | Max() |
| MaxToMin | Max() | Min() |
| SumToCount | Sum() | Count() |
| CountToSum | Count() | Sum() |
| AppendToPrepend | Append() | Prepend() |
| PrependToAppend | Prepend() | Append() |
Stryker4sโ
| Mutant operator | Original | Mutated |
|---|
| FilterNegation | a.filter(b) | a.filterNot(b) |
| FilterNotNegation | a.filterNot(b) | a.filter(b) |
| ExistsToForAll | a.exists(b) | a.forall(b) |
| ForAllToExists | a.forall(b) | a.exists(b) |
| TakeToDrop | a.take(b) | a.drop(b) |
| DropToTake | a.drop(b) | a.take(b) |
| TakeRightNegation | a.takeRight(b) | a.dropRight(b) |
| DropRightNegation | a.dropRight(b) | a.takeRight(b) |
| TakeWhileToDropWile | a.takeWhile(b) | a.dropWhile(b) |
| DropWhileToTakeWhile | a.dropWhile(b) | a.takeWhile(b) |
| IsEmptyNegation | a.isEmpty | a.nonEmpty |
| IsNonEmptyNegation | a.nonEmpty | a.isEmpty |
| IndexOfToLastIndexOf | a.indexOf | a.lastIndexOf(b) |
| LastIndexOfToIndexOf | a.lastIndexOf(b) | a.indexOf(b) |
| MaxToMin | a.max | a.min |
| MinToMax | a.min | a.max |
| MaxByToMinBy | a.maxBy(b) | a.minBy(b) |
| MinByToMaxBy | a.minBy(b) | a.maxBy(b) |
๐ Back to Top
Object literalโ
| Mutant operator | Original | Mutated |
|---|
| ObjectPropertiesRemoval | { foo: 'bar' } | { } |
๐ Back to Top
Optional chainingโ
StrykerJS specific mutator
| Mutant operator | Original | Mutated |
|---|
| OptionalMemberToRequired | foo?.bar | foo.bar |
| OptionalComputedToRequired | foo?.[1] | foo[1] |
| OptionalCallToRequired | 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
String Literalโ
| Mutant operator | Original | Mutated |
|---|
| FilledStringToEmpty | "foo" (filled string) | "" (empty string) |
| EmptyStringToFilled | "" (empty string) | "Stryker was here!" |
| FilledInterpolatedStringToEmpty | s"foo ${bar}" (string interpolation) | s"" ยน |
| FilledInterpolatedStringToEmpty | `foo ${bar}` | `` |
ยน For Stryker4s, only works with string interpolation and not other types of interpolation (like Scalameta quasiquotes) to avoid compile errors
๐ Back to Top
Unary Operatorโ
| Mutant operator | Original | Mutated |
|---|
| PlusNegation | +a | -a |
| MinusNegation | -a | +a |
๐ Back to Top
Update Operatorโ
| Mutant operator | Original | Mutated |
|---|
| PostfixIncrementNegation | a++ | a-- |
| PostfixDecrementNegation | a-- | a++ |
| PrefixIncrementNegation | ++a | --a |
| PrefixDecrementNegation | --a | ++a |
๐ Back to Top