Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

docs(mutators): add mutant operator name proposal #1458

Merged
merged 6 commits into from
Mar 15, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
293 changes: 148 additions & 145 deletions docs/supported-mutators.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,47 +28,47 @@ All Stryker versions support a variety of different mutators. We've aligned on a

## Arithmetic Operator

| Original | Mutated |
| -------- | ------- |
| `a + b` | `a - b` |
| `a - b` | `a + b` |
| `a * b` | `a / b` |
| `a / b` | `a * b` |
| `a % b` | `a * b` |
| 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

| Original | Mutated |
| ----------------------- | ------------- |
| `new Array(1, 2, 3, 4)` | `new Array()` |
| `[1, 2, 3, 4]` | `[ ]` |
| Mutant operator | Original | Mutated |
| ---------------------------- | ----------------------- | ------------- |
| ArrayConstructorItemsRemoval | `new Array(1, 2, 3, 4)` | `new Array()` |
| ArrayLiteralItemsRemoval | `[1, 2, 3, 4]` | `[ ]` |

[🔝 Back to Top](#)

## Assignment Expression

| Original | Mutated |
| -------------------- | -------------------- |
| `+=` | `-=` |
| `-=` | `+=` |
| `*=` | `/=` |
| `/=` | `*=` |
| `%=` | `*=` |
| `<<=` | `>>=` |
| `>>=` | `<<=` |
| `&=` | <code>&#124;=</code> |
| <code>&#124;=</code> | `&=` |
| `??=` | `&&=`¹ |
| Mutant operator | Original | Mutated |
| --------------------------------------------- | -------------------- | -------------------- |
| AdditionAssignmentNegation | `+=` | `-=` |
| SubtractionAssignmentNegation | `-=` | `+=` |
| MultiplicationAssignmentNegation | `*=` | `/=` |
| DivisionAssignmentNegation | `/=` | `*=` |
| RemainderAssignmentToMultiplicationAssignment | `%=` | `*=` |
| LeftShiftAssignmentNegation | `<<=` | `>>=` |
| RightShiftAssignmentNegation | `>>=` | `<<=` |
| BitwiseAndAssignmentNegation | `&=` | <code>&#124;=</code> |
| BitwiseOrAssignmentNegation | <code>&#124;=</code> | `&=` |
| NullCoalescingAssignmentToAndAssignment | `??=` | `&&=`¹ |

- ¹: Only supported by Stryker-JS

[🔝 Back to Top](#)

## Block Statement

Removes the content of every block statement. For example the code:
This group has one mutant operator, the `BlockRemoval` mutant operator. This mutant operator removes the content of every block statement. For example the code:

```javascript
function saySomething() {
Expand All @@ -86,11 +86,11 @@ function saySomething() {}

## Boolean Literal

| Original | Mutated |
| ----------- | ---------- |
| `true` | `false` |
| `false` | `true` |
| `!(a == b)` | `a == b` ¹ |
| Mutant operator | Original | Mutated |
| --------------- | ----------- | ---------- |
| TrueNegation | `true` | `false` |
| FalseNegation | `false` | `true` |
| NotRemoval | `!(a == b)` | `a == b` ¹ |

- ¹: Not supported by Stryker4s

Expand All @@ -100,56 +100,56 @@ function saySomething() {}

Stryker.NET _specific mutator_

| Original | Mutated |
| ---------------- | ------- |
| `checked(2 + 4)` | `2 + 4` |
| Mutant operator | Original | Mutated |
| --------------- | ---------------- | ------- |
| CheckedRemoval | `checked(2 + 4)` | `2 + 4` |

[🔝 Back to Top](#)

## Conditional Expression

| 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;` ¹ |
| 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

| 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` ¹ |
| 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

| Original | Mutated |
| ----------------------------- | ----------------------------- |
| `a && b` | <code>a &vert;&vert; b</code> |
| <code>a &vert;&vert; b</code> | `a && b` |
| `a ?? b` | `a && b` |
| Mutant operator | Original | Mutated |
| ------------------- | ----------------------------- | ----------------------------- |
| AndNegation | `a && b` | <code>a &vert;&vert; b</code> |
| OrNegation | <code>a &vert;&vert; b</code> | `a && b` |
| NullCoalescingToAnd | `a ?? b` | `a && b` |

[🔝 Back to Top](#)

Expand All @@ -159,92 +159,94 @@ Due to differences in language syntax, method expressions are implemented differ

### StrykerJS

| 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()` | ` ` |
| `min()` | `max()` |
| `max()` | `min()` |
| 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

| 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()` |
| 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()` |

### Stryker4s

| 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)` |
| 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

| Original | Mutated |
| ---------------- | ------- |
| `{ foo: 'bar' }` | `{ }` |
| Mutant operator | Original | Mutated |
| ----------------------- | ---------------- | ------- |
| ObjectPropertiesRemoval | `{ foo: 'bar' }` | `{ }` |

[🔝 Back to Top](#)

## Optional chaining

| Original | Mutated |
| ---------- | --------- |
| `foo?.bar` | `foo.bar` |
| `foo?.[1]` | `foo[1]` |
| `foo?.()` | `foo()` |
StrykerJS _specific mutator_

| Mutant operator | Original | Mutated |
nicojs marked this conversation as resolved.
Show resolved Hide resolved
| -------------------------- | ---------- | --------- |
| OptionalMemberToRequired | `foo?.bar` | `foo.bar` |
| OptionalComputedToRequired | `foo?.[1]` | `foo[1]` |
| OptionalCallToRequired | `foo?.()` | `foo()` |

[🔝 Back to Top](#)

Expand Down Expand Up @@ -293,32 +295,33 @@ Strings and literals identified to a regex are mutated in the following way:

## String Literal

| Original | Mutated |
| -------------------------------------- | --------------------- |
| `"foo"` (non-empty string) | `""` (empty string) |
| `""` (empty string) | `"Stryker was here!"` |
| `s"foo ${bar}"` (string interpolation) | `s""` ¹ |
| 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}\`` | `\`\`` |
Comment on lines +302 to +303
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, sorry! #3066 fixes that.

Btw, it's not the line breaks, but the way of escaping backticks.


¹ For Stryker4s, only works with string interpolation and not other types of interpolation (like [Scalameta quasiquotes](https://scalameta.org/docs/trees/guide.html#with-quasiquotes)) to avoid compile errors

[🔝 Back to Top](#)

## Unary Operator

| Original | Mutated |
| -------- | ------- |
| `+a` | `-a` |
| `-a` | `+a` |
| Mutant operator | Original | Mutated |
| --------------- | -------- | ------- |
| PlusNegation | `+a` | `-a` |
| MinusNegation | `-a` | `+a` |

[🔝 Back to Top](#)

## Update Operator

| Original | Mutated |
| -------- | ------- |
| `a++` | `a--` |
| `a--` | `a++` |
| `++a` | `--a` |
| `--a` | `++a` |
| Mutant operator | Original | Mutated |
| ------------------------ | -------- | ------- |
| PostfixIncrementNegation | `a++` | `a--` |
| PostfixDecrementNegation | `a--` | `a++` |
| PrefixIncrementNegation | `++a` | `--a` |
| PrefixDecrementNegation | `--a` | `++a` |

[🔝 Back to Top](#)