The new Stryker.NET is packed with a lot of new awesome features ๐ For the past few months we've been working hard and introduced a lot of new mutators. This can have an effect on your mutation score. So don't be surprised if your score comes out a bit higher or lower after updating. Here is a short summary of everything new.

## Test all projects in a solutionโ

Since 3.1 a long awaited feature is finally here!

When running from your project root (where your solution file is located) and passing the solution file, Stryker will analyze your solution and mutate all projects it can find.

`cd C:\myprojectroot\`

dotnet stryker --solution "C:\myprojectroot\mysolution.sln"

Since 3.2 if a single solution file is present in the directory, stryker will use that solution file and start in solution context. In that case the `--solution`

option is not required.

## Math mutationsโ

Stryker will now mutate math methods when it encounters them. All available mutations are:

Original | Mutated |
---|---|

`Math.Acos()` | `Math.Acosh()` |

`Math.Acos()` | `Math.Asin()` |

`Math.Acos()` | `Math.Atan()` |

`Math.Acosh()` | `Math.Acos()` |

`Math.Acosh()` | `Math.Asinh()` |

`Math.Acosh()` | `Math.Atanh()` |

`Math.Asin()` | `Math.Asinh()` |

`Math.Asin()` | `Math.Acos()` |

`Math.Asin()` | `Math.Atan()` |

`Math.Asinh()` | `Math.Asin()` |

`Math.Asinh()` | `Math.Acosh()` |

`Math.Asinh()` | `Math.Atanh()` |

`Math.Atan()` | `Math.Atanh()` |

`Math.Atan()` | `Math.Acos()` |

`Math.Atan()` | `Math.Asin()` |

`Math.Atanh()` | `Math.Atan()` |

`Math.Atanh()` | `Math.Acosh()` |

`Math.Atanh()` | `Math.Asinh()` |

`Math.BitDecrement()` | `Math.BitIncrement()` |

`Math.BitIncrement()` | `Math.BitDecrement()` |

`Math.Ceiling()` | `Math.Floor()` |

`Math.Cos()` | `Math.Cosh()` |

`Math.Cos()` | `Math.Sin()` |

`Math.Cos()` | `Math.Tan()` |

`Math.Cosh()` | `Math.Cos()` |

`Math.Cosh()` | `Math.Sinh()` |

`Math.Cosh()` | `Math.Tanh()` |

`Math.Exp()` | `Math.Log()` |

`Math.Floor()` | `Math.Ceiling()` |

`Math.Log()` | `Math.Exp()` |

`Math.Log()` | `Math.Pow()` |

`Math.MaxMagnitude()` | `Math.MinMagnitude()` |

`Math.MinMagnitude()` | `Math.MaxMagnitude()` |

`Math.Pow()` | `Math.Log()` |

`Math.ReciprocalEstimate()` | `Math.ReciprocalSqrtEstimate()` |

`Math.ReciprocalSqrtEstimate()` | `Math.ReciprocalEstimate()` |

`Math.ReciprocalSqrtEstimate()` | `Math.Sqrt()` |

`Math.Sin()` | `Math.Sinh()` |

`Math.Sin()` | `Math.Cos()` |

`Math.Sin()` | `Math.Tan()` |

`Math.Sinh()` | `Math.Sin()` |

`Math.Sinh()` | `Math.Cosh()` |

`Math.Sinh()` | `Math.Tanh()` |

`Math.Tan()` | `Math.Tanh()` |

`Math.Tan()` | `Math.Cos()` |

`Math.Tan()` | `Math.Sin()` |

`Math.Tanh()` | `Math.Tan()` |

`Math.Tanh()` | `Math.Cosh()` |

`Math.Tanh()` | `Math.Sinh()` |

## Object initializer mutationโ

We already had mutations for emptying lists and arrays. Now object initializers had their turn.

`var myObject = new MyClass() {`

property1 = "",

property2 = Int.MaxValue

}

Will be mutated into an empty object initializer:

`var myObject = new MyClass() {}`

## Null-coalesingโ

Null checking is an important part of our code nowadays. Syntethic sugar has made life easier. But it's also easy to overlook during testing. That's why we now mutate Null-coalesing operators and assignments.

### Null-coalescing assignment mutationโ

`var object1 ??= object2;`

Will be mutated into:

`var object1 = object2;`

### Null-coalescing operator mutationsโ

Original | Mutated |
---|---|

`a ?? b` | `b ?? a` |

`a ?? b` | `a` |

`a ?? b` | `b` |

## Extra linq mutationsโ

It seems we missed some Linq methods when initially creating the Linq mutator. The following mutations have been added to the Linq mutator.

Original | Mutated |
---|---|

`MinBy()` | `MaxBy()` |

`MaxBy()` | `MinBy()` |

`SkipLast()` | `TakeLast()` |

`TakeLast()` | `SkipLast()` |

`Order()` | `OrderDescending()` |

`OrderDescending()` | `Order()` |

`UnionBy()` | `IntersectBy()` |

`IntersectBy()` | `UnionBy()` |

## Conditional operator mutationsโ

We already mutated conditional operators like `&&`

and `||`

. But using pattern matching a different type of `and`

and `or`

exist. They are now also mutated.

Original | Mutated |
---|---|

`and` | `or` |

`or` | `and` |

## Equality operator mutationsโ

The same thing for equality operators. In pattern matching instead of `==`

and `!=`

you can use `is`

and `is not`

. Those are now mutated as well.

Original | Mutated |
---|---|

`is` | `is not` |

`is not` | `is` |

## Nuget restoreโ

For .NET Framework projects an extra Nuget Restore is needed. When the MsBuildPath was provided to Stryker this was not used by the Nuget Restore. This could result in exceptions.

From now on the Nuget Restore will also use the provided MsBuildPath in the options.

## What's next? ๐ฎโ

We have some exciting features on our backlog that you can expect in the coming releases.

We are working on getting test information into the html reporting. You'll be able to see what test have been executed. What mutations they cover, and even what tests didn't kill any mutations.

Furthermore, now that multiple source projects can be mutated, configuring stryker can become difficult. What if you want to exclude a mutation only in 1 project? That's why we want to support multiple config files. One per source project.

In the long term we also want to focus more on performance. All these new mutations make running Stryker.NET painfully slow. We have some ideas on how to do this. But new ideas are always welcome. Join the discussion on our slack channel or by sending a tweet.