Carlos Ble

Carlos Ble

I am a professional software developer, I solve problems.

I also teach and mentor developers to build better software.

Developing software since 2001.

Can I help you?

  • Do you need high quality tailor-made software?
  • Need training on TDD, clean code or refactoring?
  • Is it risky? do you need advise?
  • May I pair with you to write better code?

Events

Upcoming public training courses:

  1. [Online - en Español] 25 y 26 de Junio
    Test Doubles con JavaScript - Online
  2. [in English] July 7, 8 & 9
    TDD (open to the public) - Tenerife, Canary Islands
  3. [en Español] 14 y 15 Julio
    TDD (en abierto) - Gran Canaria, Canary Islands
  4. [in English] October 13, 14 & 15
    TDD (open to the public) - London, UK
  5. [en Español] 29, 30 y 31 de Octubre.
    TDD (en abierto) - Madrid, Spain

Conferences:

  1. I'll be at SocratesUK 2014
  2. I'll be at the London Test Gathering Workshops.

Archive for February, 2009



I've realized that test code difficult to write and read is sometimes a code smell. It could mean the test code is wrong or the SUT (subject under test) itself is wrong. I've got myself thinking of how to test a method X of a class C which is calling another method Y within the same class, but avoiding or stubbing the call to Y.

Here are some ideas to work around this issue (python code).
The SUT:

  1.  
  2. class MyClass:
  3. def substractOne(self, arg1):
  4. return arg1 -1
  5.  
  6. def calculate(self, x, y):
  7. result = x * y
  8. return self.substractOne(result)
  9.  

Basic tests:

  1.  
  2. class SomeTests(mocker.MockerTestCase):
  3. def test_substractOne(self):
  4. instance = MyClass()
  5. result = instance.substractOne(10)
  6. self.assertEqual(result, 9)
  7.  
  8. def test_calculate(self):
  9. instance = MyClass()
  10. result = instance.calculate(1, 5)
  11. self.assertEqual(result, 4)
  12.  

So far so good, but.... what would happen if "substractOne" was "saveCustomerMoney"... would you let your test change a bank account?. No!. If we already have a separate test for "saveCustomerMoney", we just want to test "calculate" (which would have a differente name, of course).

From now bear in mind that we need to test "calculate" avoiding the call to "substractOne".

Steve Freeman wrote that composition would be the solution. Composition is a refactoring. Composition means in this context, to extract classes from MyClass encapsulating methods regarding their functionality. Ask yourself this: "do all those methods belong in that class, or are they for totally different proposes?". The solution in code:
The new SUT:

  1.  
  2. class MathOperation():
  3. def __init__(self, substract, multiply):
  4. self.substract = substract
  5. self.multiply = multiply
  6.  
  7. def calculate(self, x, y):
  8. result = self.multiply.simpleMultiply(x, y)
  9. return self.substract.substractOne(result)
  10.  
  11. class Multiply():
  12. def simpleMultiply(self, x, y):
  13. return x * y
  14.  
  15. class Substract():
  16. def substractOne(self, arg):
  17. return arg -1
  18.  

The test: (remember we want to avoid calls to substractOne)

  1.  
  2. def test_MathOperation(self):
  3. mockSubstract = self.mocker.proxy(Substract)
  4. x = 5
  5. mockSubstract.substractOne(x)
  6. self.mocker.result(x)
  7.  
  8. self.mocker.replay()
  9.  
  10. multiply = Multiply()
  11. instance = MathOperation(mockSubstract, multiply)
  12. result = instance.firstMethod(1, 5)
  13. self.assertEqual(result, 5)
  14.  

Right, but if you don't need composition? If both methods belong in the same class according to the domain model?. You can use the "extract method" refactoring so that calculate would be like this:

  1.  
  2. def calculate(self, x, y):
  3. result = self.simpleMultiply(x, y)
  4. return self.substractOne(result)
  5.  

And now you can test simpleMultiply and substractOne separately.

But say I still want to call "calculate" in a test to make sure it does not blow up. That would call substractOne and we can't allow that in the test. Polymorphism is a good answer.
The SUT:

  1.  
  2. class MyClass:
  3. def substractOne(self, arg1):
  4. return arg1 -1
  5.  
  6. def calculate(self, x, y):
  7. result = x * y
  8. return self.substractOne(result)
  9.  

The test:

  1.  
  2. def test_calculate(self):
  3. class ChildClass(MyClass):
  4. def substractOne(self, arg1):
  5. return arg1
  6.  
  7. instance = ChildClass()
  8. result = instance.calculate(1, 5)
  9. self.assertEqual(result, 5)
  10.  

Actually the mock framework can do this for us too but the code above is probably easier to understand.

But what do we do if the method is recursive?. You can modify the method to keep the functionality with an iterative implementation. In my opinion that is too much work. You can use the mock framework to exercise the SUT in the first call and mock the first and further recursive calls.


Thanks to the testdrivendevelopment mailing list, it is a really good place for the TDD community.