Search code examples
javamutation-testingpitest

Mutation Testing - Negated conditional on a for-each loop?


we are just playing around a bit with mutation testing and there is one thing I don't understand. Why is it always trying to apply the "Negated Conditional Mutator" on my for-each loops like this one:

for (final Order order : orders)

If I take a look at the description of the mutator (http://pitest.org/quickstart/mutators/#NEGATE_CONDITIONALS), then it should just mutate conditions like != to == or < to >=. So I don't really understand why it's used there and why it sometimes fails and sometimes doesn't.

Could someone explain this to me, please?


Solution

  • This is a consequence of PIT mutating bytecode rather than source.

    The bytecode for the for each loop looks something like

    INVOKEINTERFACE java/util/List.iterator ()Ljava/util/Iterator;
    ASTORE 2
    L2
    ALOAD 2
    INVOKEINTERFACE java/util/Iterator.hasNext ()Z
    IFEQ L3
    ALOAD 2
    INVOKEINTERFACE java/util/Iterator.next ()Ljava/lang/Object;
    <contents of the loop>
    GOTO L2
    L3
    

    So basically behind the scenes it is creating a iterator and checking the value of hasNext. While it's true it executes the loop by jumping to L2.

    The conditional mutation is to the IFEQ L3 call that checks the return code of hasNext to exit the loop.

    It would be nice if PIT could detect conditional statements generated by for each loops. I'm not sure that I've ever looked at this particular case, but in general distinguishing between bytecode produced by language features and bytecode that maps directly back to developer written code is either difficult or impossible.

    Update - as of 1.2.5 pitest should avoid mutating the conditional in for each loops.