3

I am experimenting with junit5 and pitest. My code under test looks like:

// [...]
InputStream istream = this.getClass().getResourceAsStream("/" + file.getName());
if (istream == null) // 1. negated condition -> suvived 
 {
  istream = Files.newInputStream(this.files.get(varname).toPath(), StandardOpenOption.READ);
 }
try (BufferedReader reader = new BufferedReader(new InputStreamReader(istream, StandardCharsets.UTF_8))) // 2. removed call to java/io/BufferedReader::close → SURVIVED // 3. removed call to java/lang/Throwable::addSuppressed → SURVIVED
 {
  // [...]
 } // 4. removed call to java/io/BufferedReader::close → SURVIVED

Within this small block of code I have left 4 survived mutations I would like to kill. Killing could happen by adding/changing a test or also by refactoring the code.

My problem is now that the first mutation is an equivalent mutant - were I have no idea how to refactore it away. The other three mutations are implicit by the try-resource-statement.

So my question is how to refactor this 4 mutations away? Because I am sure they can not be killed by additional/changed tests.

PowerStat
  • 3,757
  • 8
  • 32
  • 57

1 Answers1

1

The first mutant is only equivalent if the observable behavior of the function is the same on both sides of the if statement.

For this to be the case 'file' and 'this.files.get(varname)' would need to always resolve to the same inputstream.

If they can resolve to different inputstreams then a test can be constructed to kill the mutant.

If they will always resolve to the same thing, then why is the first branch needed? Unless it exists for is some concern that cannot be tested (e.g. performance) then the first branch is not required and the stream can always be resolved from 'this.files.get(varname).toPath()'.

The other mutants are a little trickier.

They are equivalent as they deal with a non unit testable concern (resource management). More importantly they're 'junk', as they are a compiler construct and do not map directly back to code.

Pitest tries to filter out junk mutants like these, but the filtering is imperfect as they are not clearly identified as compiler constructs in the byte code.

The 1.4.8 release correctly filters out all these mutants if I paste your snippet into a file and edit so that it compiles. If you can paste a full compilable class that reproduces the issue I can see if the filtering can be tweaked to pick up these mutants in context.

henry
  • 5,923
  • 29
  • 46
  • I worked with the 1.4.8 and the 0.8 junit5 plugin. I will try to make a complete minimal example. – PowerStat Jun 05 '19 at 05:00
  • I have made my project now available at: https://github.com/PowerStat/TemplateEngine It's maven/eclipse based and used Java 11.03 for the moment. – PowerStat Jun 05 '19 at 10:04
  • The idea of the first mutation is to allow the loading of template files also from inside the jar file (in which the TemplateEngine is packaged). But how to write a test for that when pitest works on target/classes? – PowerStat Jun 05 '19 at 14:28
  • In the meantime I have added a test for the classpath loading - was tricky, but possible. – PowerStat Jun 14 '19 at 05:53
  • Just for your information I have updated to pitest 1.4.9, but still having the try-resource mutations. – PowerStat Jun 21 '19 at 14:56
  • Yes, there were no fixes around junk filtering in 1.4.9. Unfortunately it'll be a while until I get chance to look at it. – henry Jun 21 '19 at 15:21
  • Is there a chance that I can help you with this - I have checked out the repository, but no idea where and how to start. – PowerStat Jun 21 '19 at 19:06
  • 1
    @PowerStat if you're feeling brave you can take a look at https://github.com/hcoles/pitest/blob/master/pitest-entry/src/main/java/org/pitest/mutationtest/build/intercept/javafeatures/TryWithResourcesMethodVisitor.java – henry Jun 22 '19 at 20:26