I have my easy function made, and honestly figuring out a test to write for it was harder than writing the code. (This seems to be a recurring theme with me and Test Driven Development).

The function is 3 lines of code, and one of those lines is just for readability.

(defn update-board-easy [board]
  (let [available-moves (core/get-available-moves board)]
    (core/update-board (rand-nth available-moves) board)))

core/get-available-moves takes a board (sequence of numbers and either string “X” or “O”) and filters out anything that is not a number.

I wrote a detailed post about rand-nth yesterday in case you missed it.

This was all easy to write… Most of it was already written by me weeks ago! The part I had to reach out for help on was how to test for random. My mentor Alex gave me a nice shift in perspective when I asked about it. Testing for random isn’t what we’re really trying to do here. We know that rand-nth works, it’s an official clojure.core function. What we need to test is that our function is working as intended. In order to accomplish this, I needed the random number to be something consistent in my tests. I managed to get this done with the with-redefs function.

(it "returns a random valid move on empty board"
      (with-redefs [rand-nth (stub :rand-nth {:return 0})]
        (should= ["X" 1 2 3 4 5 6 7 8] (sut/update-board-easy (range 9)))))

with-redefs lets us redefine a function inside a function. Its syntax is similar to let. First word in the bracket is the binding, the second is what you want to change. In our case above we used stub to make the return of rand-nth to consistently be 0.

Now that we have consistent outputs, we have consistent tests!