4

I have the following ActiveRecord model class method:

def self.find_by_shortlink(shortlink)
  find_by!(shortlink: shortlink)
end

When I run Mutant against this method, I'm told there were 17 mutations and 16 are still "alive" after the test has run.

Here's one of the "live" mutations:

-----------------------
evil:Message.find_by_shortlink:/home/peter/projects/kaboom/app/models/message.rb:29:3f9f2
@@ -1,4 +1,4 @@
 def self.find_by_shortlink(shortlink)
-  find_by!(shortlink: shortlink)
+  find_by!(shortlink: self)
 end

If I manually make this same change, my tests fail - as expected.

So my question is: how do I write a unit test that "kills" this mutation?

pdoherty926
  • 9,895
  • 4
  • 37
  • 68

1 Answers1

3

Disclaimer, mutant author speaking.

Mini cheat sheet for such situations:

  1. Make sure your specs are green right now.
  2. Change the code as the diff shows
  3. Try to observe an unwanted behavior change.
    1. Impossible?
      1. (likely) Take the mutation as better code.
      2. (unlikely) Report a bug to mutant
    2. Found a behavior change: Encode it as a test, or change a test to cover that behavior.
  4. Rerun mutant to verify the death of the mutation.
  5. Make sure mutant actually lists the tests you added as used for that mutation. If not restructure the tests to cover the subject of the mutation in the selected tests.

Now to your case: If you apply the mutation to your code. The argument gets ignored and essentially hardcoded (the value for key :shortlink used in your finder does not change depending on argument shortlink). So the only thing you need to do in your test is adding a case where the argument shortlink matters to the expectation you place in the test.

If passing self as value for the :shortlink finder has the same effect as passing in the current argument you test, try to use a different argument. Coercion of values in finders can be tricky in AR, there is the chance your model coerces to the same value you are testing as argument.

mbj
  • 1,042
  • 9
  • 19
  • Thanks for the detailed answer! There's something I'm still not understanding (a few things, actually, but I'll keep this concise) about my example. Changing the parameter to `self` causes an `ActiveRecord:;StatementInvalid` exception. Is that because of the coercion issues you mentioned or is that a corner case that Mutant expects my tests to cover? – pdoherty926 Jun 02 '15 at 04:15
  • What it means is that your tests don't verify what the value is at all. The fact that the value can be replaced with self (a convenient stand-in for a random object) means that there's no specification for that part of the method. – dkubb Jun 02 '15 at 04:26
  • @dkubb Would that mean mocking `find_by!`, adding an assertions to my tests about the value of the parameter or something else? Could point me an example of that sort of specification? – pdoherty926 Jun 02 '15 at 04:45
  • If you do not want to touch the DB a message expectation for `#find_by!(shortlink: your_argument)` would do the job. Than your spec would only guarantee your method `#find_by_shortlink` transforms into a finder. Which is enough, as you should trust the implementation of `#find_by!` already. – mbj Jun 02 '15 at 16:41