Keep Calm and Kill Mutants
Written by Alexander Shestakov   
Monday, 22 August 2016
Article Index
Keep Calm and Kill Mutants
Testing, Testing
Stricter Equality

This is similar to the[ ]vs fetch case. Mutant again states that using a more strict code (see here for details) doesn't break the tests. In our case it doesn't matter (equal? on integers is pretty straightforward), but in real projects, especially with hashes and custom implementation of hash function it may lead to problems. So, we are replacing comparisons with equal? and re-running Mutant:

mut21

Mutation coverage is now 95.25 percent. We are close to the finish line:

mut22

This last line will remove any votes on the step, into which the workflow puts rejects.

I think our tests are only using FORCE permission after the reject operation. That is why removing this line does not break the suite.
In fact, there is VOTE activity after reject action in "should be able to reset votes by reject action from #{permission} actor" case, but since workflow contains only one step, @current_step does not get decremented.

We need to modify 'reject should erase votes from current and previous step' case slightly:

mut23

Now, when all mutants have been killed, mutant happily reports 100 percent mutation coverage.

mut24

Conclusion

Traditional coverage tools only highlight code executed by running a test suite. Let's run a little thought experiment: squint for a second, blink twice and imagine all assertion checks from your test suite have just disappeared. Will that affect coverage? It's very refreshing to realize it will not. Furthermore, even having full branch coverage does not guarantee you are safe, see here for examples. Ask yourself a very simple question: are you still sure that the test suite you have is actually able to detect failures in the code?

Aside from branch coverage, mutation testing is intended to ensure code is meaningfully tested, giving your test suite powers to weed out broken code. However, no formal guarantees can be given; it's a way to perfection, but not ideal in itself.

As a tool, mutant can be used for many tasks. One example is using it as a guide to write better tests (it highlights code paths that were never executed). Or it can be utilized to highlight tests, which are not contributing anymore into branch coverage (deleting such tests will still show 100 percent mutation coverage).

I personally don't always use mutant in my day-to-day development job, and I'm not here to convince you absolutely must. But, it does help to better understand and improve your code and coding skills overall. To explore different mutation operators mutant can apply to your code, see here. Give it a try!

 shestakov-keep-calm

 

About the Author

Alexander Shestakov is a software engineer with Itransition. He graduated from Belarusian State University of Informatics and Radioelectronics with honors, with a degree of Engineer of Radio Electronics. His areas of interest are Ruby, Rails, Haskell, software architecture, and unit and integration testing.

 

More Information

Mutation testing on Wikipedia

Mutant (GitHub) 

You can download the code for this article from the CodeBin (note you have to register first) - look for "mutation testing".

 

To be informed about new articles on I Programmer, sign up for our weekly newsletter, subscribe to the RSS feed and follow us on Twitter, FacebookGoogle+ or Linkedin.

 

 



Last Updated ( Wednesday, 31 August 2016 )