I'm writing a classic binary search function in Clojure and testing it with the mutant mutation testing library.
My tests work fine in terms of correctness, but mutation testing reports one surviving mutant that I can't get rid of — even after writing what I thought were thorough test cases.
My code:
(defn binary-search
([coll target]
(binary-search coll target 0 (dec (count coll))))
([coll target left right]
(if (<= left right)
(let [mid (quot (+ left right) 2)
mid-val (nth coll mid)]
(cond
(= mid-val target) mid
(<= mid-val target) (binary-search coll target (inc mid) right)
:else (binary-search coll target left (dec mid))))
-1)))
Test cases:
(deftest binary-search-test
(is (= (search/binary-search [1 2 3 4 5 6 7 8 9] 5) 4))
(is (= (search/binary-search [2 2 2 2 2 2 2] 1) -1))
(is (= (search/binary-search [42] 42) 0))
(is (= (search/binary-search [1 2] 2) 1))
(is (= (search/binary-search [10 20 30 40 50] 30) 2))
(is (= (search/binary-search [10 20 30 40 50] 60) -1))
(is (= (search/binary-search [10 20 30 40 50] 50) 4))
(is (= (search/binary-search [10 20 30 40 50] 40) 3))
(is (= (search/binary-search [1 2 3 4 5 6 7 8 9] 9) 8))
(is (= (search/binary-search [7 4 3 0 1 8 2] 2) -1)))
Mutant survivor:
(defn binary-search
([coll target]
(binary-search coll target 0 (dec (count coll))))
([coll target left right]
(if (<= left right)
(let [mid (quot (+ left right) 2)
mid-val (nth coll mid)]
(cond
(= mid-val target) mid
(<[-=-] mid-val target) (binary-search coll target (inc mid) right)
:else (binary-search coll target left (dec mid))))
-1)))
I’ve verified that the < comparison does get executed by multiple test cases. But the mutated operator (<[-=-]) should cause an error — and yet the mutant survives.
My questions:
- Has anyone seen this kind of "survivor" mutant that seems syntactically broken?
- Could this be a limitation or bug in the mutant tool?
- Is there a way to configure it to treat malformed mutations as killed?
- Or should I be writing different kinds of tests to kill this?