Skip to main content

Supported mutators

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โ€‹

MutatorStrykerJSStryker.NETStryker4s
Arithmetic Operatorโœ…โœ…โŒ
Array Declarationโœ…โœ…โŒ
Assignment ExpressionโŒโœ…n/a
Block Statementโœ…โœ…โŒ
Boolean Literalโœ…โœ…๏ธโœ…
Checked Statementn/aโœ…n/a
Conditional Expressionโœ…โœ…โœ…
Equality Operatorโœ…โœ…โœ…
Logical Operatorโœ…โœ…โœ…
Method Expressionโœ…โœ…โœ…
Object literalโœ…n/an/a
Optional chainingโœ…โŒn/a
Regexโœ…โœ…โœ…
String Literalโœ…โœ…โœ…
Unary Operatorโœ…โœ…โŒ
Update Operatorโœ…โœ…n/a

Arithmetic Operatorโ€‹

Mutant operatorOriginalMutated
AdditionNegationa + ba - b
SubtractionNegationa - ba + b
MultiplicationNegationa * ba / b
DivisionNegationa / ba * b
RemainderToMultiplicationa % ba * b

๐Ÿ” Back to Top

Array Declarationโ€‹

Mutant operatorOriginalMutated
ArrayConstructorItemsRemovalnew Array(1, 2, 3, 4)new Array()
ArrayLiteralItemsRemoval[1, 2, 3, 4][ ]

๐Ÿ” Back to Top

Assignment Expressionโ€‹

Mutant operatorOriginalMutated
AdditionAssignmentNegation+=-=
SubtractionAssignmentNegation-=+=
MultiplicationAssignmentNegation*=/=
DivisionAssignmentNegation/=*=
RemainderAssignmentToMultiplicationAssignment%=*=
LeftShiftAssignmentNegation<<=>>=
RightShiftAssignmentNegation>>=<<=
BitwiseAndAssignmentNegation&=|=
BitwiseOrAssignmentNegation|=&=
NullCoalescingAssignmentToAndAssignment??=&&=ยน
  • ยน: Only supported by Stryker-JS

๐Ÿ” 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 operatorOriginalMutated
TrueNegationtruefalse
FalseNegationfalsetrue
NotRemoval!(a == b)a == b ยน
  • ยน: Not supported by Stryker4s

๐Ÿ” Back to Top

Checked Statementโ€‹

Stryker.NET specific mutator

Mutant operatorOriginalMutated
CheckedRemovalchecked(2 + 4)2 + 4

๐Ÿ” Back to Top

Conditional Expressionโ€‹

Mutant OperatorOriginalMutated
LessThanToFalsefor (var i = 0; i < 10; i++) { }for (var i = 0; false; i++) { } ยน
GreaterThanToFalsewhile (a > b) { }while (false) { }
GreaterThanToFalsedo { } while (a > b);do { } while (false);
GreaterThanToTrueif (a > b) { }if (true) { }
GreaterThanToFalseif (a > b) { }if (false) { }
GreaterThanToTruevar x = a > b ? 1 : 2;var x = true ? 1 : 2; ยน
GreaterThanToFalsevar x = a > b ? 1 : 2;var x = false ? 1 : 2; ยน
  • ยน: Not supported by Stryker4s

๐Ÿ” Back to Top

Equality Operatorโ€‹

Mutant operatorOriginalMutated
LessThanBoundarya < ba <= b
LessThanNegationa < ba >= b
LessThanEqualBoundarya <= ba < b
LessThanEqualNegationa <= ba > b
GreaterThanBoundarya > ba >= b
GreaterThanNegationa > ba <= b
GreaterThanEqualBoundarya >= ba > b
GreaterThanEqualNegationa >= ba < b
EqualityNegationa == ba != b
InequalityNegationa != ba == b
StrictEqualityNegationa === ba !== b ยน
StrictInequalityNegationa !== ba === b ยน
  • ยน: Only supported on StrykerJS and Stryker4s

๐Ÿ” Back to Top

Logical Operatorโ€‹

Mutant operatorOriginalMutated
AndNegationa && ba || b
OrNegationa || ba && b
NullCoalescingToAnda ?? ba && b

๐Ÿ” Back to Top

Method Expressionโ€‹

Due to differences in language syntax, method expressions are implemented differently in each Stryker framework:

StrykerJSโ€‹

Mutant operatorOriginalMutated
EndsWithToStartsWithendsWith()startsWith()
StartsWithToEndsWithstartsWith()endsWith()
TrimToTrimEndtrim()trimEnd()
TrimToTrimStarttrimEnd()trimStart()
TrimToTrimEndtrimStart()trimEnd()
SubstrRemovalsubstr()
SubstringRemovalsubstring()
UpperCaseToLowerCasetoUpperCase()toLowerCase()
LowerCaseToUpperCasetoLowerCase()toUpperCase()
LocalLowerCaseToLocalUpperCasetoLocalLowerCase()toLocalUpperCase()
LocalUpperCaseToLocalLowerCasetoLocalUpperCase()toLocalLowerCase()
SortRemovalsort()
SomeToEverysome()every()
EveryToSomeevery()some()
ReverseRemovalreverse()
FilterRemovalfilter()
SliceRemovalslice()
CharAtRemovalcharAt()
MinToMaxmin()max()
MaxToMinmax()min()

Stryker.NETโ€‹

Mutant operatorOriginalMutated
DistinctRemovalDistinct()
ReverseRemovalReverse()
OrderByRemovalOrderBy()
OrderByDescendingRemovalOrderByDescending()
SingleOrDefaultToFirstOrDefaultSingleOrDefault()FirstOrDefault()
FirstOrDefaultToSingleOrDefaultFirstOrDefault()SingleOrDefault()
FirstToLastFirst()Last()
LastToFirstLast()First()
AllToAnyAll()Any()
AnyToAllAny()All()
SkipToTakeSkip()Take()
TakeToSkipTake()Skip()
SkipWhileToTakeWhileSkipWhile()TakeWhile()
TakeWhileToSkipWhileTakeWhile()SkipWhile()
MinToMaxMin()Max()
MaxToMinMax()Min()
SumToCountSum()Count()
CountToSumCount()Sum()

Stryker4sโ€‹

Mutant operatorOriginalMutated
FilterNegationa.filter(b)a.filterNot(b)
FilterNotNegationa.filterNot(b)a.filter(b)
ExistsToForAlla.exists(b)a.forall(b)
ForAllToExistsa.forall(b)a.exists(b)
TakeToDropa.take(b)a.drop(b)
DropToTakea.drop(b)a.take(b)
TakeRightNegationa.takeRight(b)a.dropRight(b)
DropRightNegationa.dropRight(b)a.takeRight(b)
TakeWhileToDropWilea.takeWhile(b)a.dropWhile(b)
DropWhileToTakeWhilea.dropWhile(b)a.takeWhile(b)
IsEmptyNegationa.isEmptya.nonEmpty
IsNonEmptyNegationa.nonEmptya.isEmpty
IndexOfToLastIndexOfa.indexOfa.lastIndexOf(b)
LastIndexOfToIndexOfa.lastIndexOf(b)a.indexOf(b)
MaxToMina.maxa.min
MinToMaxa.mina.max
MaxByToMinBya.maxBy(b)a.minBy(b)
MinByToMaxBya.minBy(b)a.maxBy(b)

๐Ÿ” Back to Top

Object literalโ€‹

Mutant operatorOriginalMutated
ObjectPropertiesRemoval{ foo: 'bar' }{ }

๐Ÿ” Back to Top

Optional chainingโ€‹

StrykerJS specific mutator

Mutant operatorOriginalMutated
OptionalMemberToRequiredfoo?.barfoo.bar
OptionalComputedToRequiredfoo?.[1]foo[1]
OptionalCallToRequiredfoo?.()foo()

๐Ÿ” Back to Top

Regexโ€‹

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:

OriginalMutated
^abcabc
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 operatorOriginalMutated
FilledStringToEmpty"foo" (filled string)"" (empty string)
EmptyStringToFilled"" (empty string)"Stryker was here!"
FilledInterpolatedStringToEmptys"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 operatorOriginalMutated
PlusNegation+a-a
MinusNegation-a+a

๐Ÿ” Back to Top

Update Operatorโ€‹

Mutant operatorOriginalMutated
PostfixIncrementNegationa++a--
PostfixDecrementNegationa--a++
PrefixIncrementNegation++a--a
PrefixDecrementNegation--a++a

๐Ÿ” Back to Top