Struggling with cyclical dependancies in unit tests

I’m trying to practice TDD, by using it to develop a simple like Bit Vector. I happen to be using Swift, but this is a language-agnostic question.

My BitVector is a struct that stores a single UInt64, and presents an API over it that lets you treat it like a collection. The details don’t matter much, but it’s pretty simple. The high 57 bits are storage bits, and the lower 6 bits are “count” bits, which tells you how many of the storage bits actually store a contained value.

So far, I have a handful of very simple capabilities:

  1. An initializer that constructs empty bit vectors
  2. A count property of type Int
  3. An isEmpty property of type Bool
  4. An equality operator (==). NB: this is a value-equality operator akin to Object.equals() in Java, not a reference equality operator like == in Java.

I’m running into a bunch of cyclical dependancies:

  1. The unit test that tests my initializer need to verify that the newly constructed BitVector. It can do so in one of 3 ways:

    1. Check bv.count == 0
    2. Check bv.isEmpty == false
    3. Check that bv == knownEmptyBitVector

    Method 1 relies on count, method 2 relies on isEmpty (which itself relies on count, so there’s no point using it), method 3 relies on ==. In any case, I can’t test my initializer in isolation.

  2. The test for count needs to operate on something, which inevitably tests my initializer(s)

  3. The implementation of isEmpty relies on count

  4. The implementation of == relies on count.

I was able to partly solve this problem by introducing a private API that constructs a BitVector from an existing bit pattern (as a UInt64). This allowed me to initialize values without testing any other initializers, so that I could “boot strap” my way up.

For my unit tests to truly be unit tests, I find myself doing a bunch of hacks, which complicate my prod and test code substantially.

How exactly do you get around these sorts of issues?