1

I'm new to BDD, even to whole testing world.

I'm trying to take BDD practices when writing a simple linear algebra library in swift. So there would be many value object types like Matrix, Vector etc. When writing code, I suppose I still need to stick to the TDD principle (am I right?):

Not writing any single line of code without a failing test

To implement a value object type, I need to make it conform to Equatable protocol and implement its == operator. This is adding code, so I need a failing test. How to write spec for this kinda scenarios ?

One may suggest some approach like:

describe("Matrix") {
    it("should be value object") {
        let aMatrix = Matrix<Double>(rows: 3, cols:2)
        let sameMatrix = Matrix<Double>(rows: 3, cols:2)
        expect(sameMatrix) == aMatrix
        let differentMatrix = Matrix<Double>(rows: 4, cols: 2)
        expect(differentMatrix) != aMatrix
    }
}

This would be an ugly boilerplate for two reasons:

  1. There may be plenty of value object types and I need to repeat it for all of them
  2. There may be plenty of cases that would cause two objects being not equal. Taking the spec above for example, an implementation of == like return lhs.rows == rhs.rows would pass the test. In order to reveal this "bug", I need to add another expectation like expect(matrixWithDifferentColmunCount) != aMatrix. And again, this kinda repetition happens for all value object types.

So, how should I test this "isEqual" ( or operator== ) method elegantly ? or shouldn't I test it at all ?


I'm using swift and Quick for testing framework. Quick provides a mechanism called SharedExample to reduce boilerplates. But since swift is a static typing language and Quick's shared example doesn't support generics, I can't directly use a shared example to test value objects.

I came up with a workaround but don't consider it as an elegant one.

Nandin Borjigin
  • 2,094
  • 1
  • 16
  • 37

1 Answers1

1

Elegance is the enemy of test suites. Test suites are boring. Test suites are repetitive. Test suites are not "DRY." The more clever you make your test suites, the more you try to avoid boilerplate, the more you are testing your test infrastructure instead of your code.

The rule of BDD is to write the test before you write the code. It's a small amount of test code because it's testing a small amount of live code; you just write it.

Yes, that can be taken too far, and I'm not saying you never use a helper function. But when you find yourself refactoring your test suite, you need to ask yourself what the test suite was for.

As a side note, your test doesn't test what it says it does. You're testing that identical constructors create Equal objects and non-identical constructors create non-Equal objects (which in principle is two tests). This doesn't test at all that it's a value object (though it's a perfectly fine thing to test). This isn't a huge deal. Don't let testing philosophy get in the way of useful testing; but it's good to have your titles match your test intent.

Rob Napier
  • 286,113
  • 34
  • 456
  • 610