I want to write some invoicing logic, and I start coding it, using TDD.
The following example is silly, but I'm confident it represents well the everyday dilemma I'm facing
function createTestInvoice(client) { return Invoice.new( { client: client, rows: [ {item: 'apple', quantity: 1, unit_price_ 1} {item: 'banana', quantity: 2, unit_price: 2} ] } ) } al = Client.new({name: 'Al', can_buy_apples: true) assert( createTestInvoice(al).total ).to(equal(5)) john = Client.new({name: 'John', can_buy_apples: false) assert( createTestInvoice(al).total ).to(equal(4)) When I start with the implementation I realise that just the following
is not enough, since I need some kind of InvoiceRowFactory that decides how and if to allow the row to be stored.
At this point the logic I was testing in this unit would be testing some logic that is included in the InvoiceRowFactory. A test for it would be:
/* remember: John cannot buy apples */ assert(InvoiceRowFactory.call(john, {item: 'apple', quantity: 1, unit_price_ 1}).to(be(null)) How to proceed now? keep the tests in the specs of Invoice, or move them to a brand new test file of InvoiceRowFactory ? Both cases feel wrong to be, because
- if I keep the tests here, I'll be testing here something that belongs to another unit, that can and should be tested separately
- if I move the tests, I'll be stubbing the dependency. At that point, in the future, I realise this code is horrible OOP, and want to replace
InvoiceRowFactorywithInvoiceRow. So a refactorer would love not to break anything while he's refactoring, keeping all the tests all green, but how? He can't, because my test ofInvoiceis too coupled with theInvoiceRowFactorystub
I just cannot reach the point where I can look at some code and make some changes keeping confident I'll not break anything, because I write such small units, that the only way to improve them is change the way they interact.
Thank you
