First of all, the only reason inheritance is used here is for code reuse, which is a big code smell.
Diferentes implementações de serializador (como SerializerA
, SerializerB
, SerializerC
) levam a diferentes SerializerTest
classes ( SerializerTestA
, SerializerTestB
, SerializerTestC
), que são todas "Testadores de serializadores", dando seu relacionamento "é-um" com a classe base SerializerTester
base, então a herança é provavelmente a ferramenta certa aqui.
If I now want to create another implementation of Serializer, and create a derivative of the base test class, I end up having to implement all production code in one step.
Eu não penso assim. Você inicia o TDD criando uma classe de teste SerializerTestA
(derivada de SerializerTester
, com nada mais do que criar um objeto SerializerA
. Isso não compilará - o teste é RED. Então você implementa SerializerA
com nada mais do que um construtor e implementações de método vazio para a interface Serializer
- o teste é VERDE Em seguida, você adiciona seu primeiro método de teste a SerializerTestA
, que pode apenas delegar uma chamada de teste a um método correspondente em SerializerTester
. em SerializerA
, seu teste falha - RED novamente. Em seguida, você implementa o primeiro método vazio em SerializerA
, até que o primeiro não falhe mais - o status do teste é VERDE novamente.
Portanto, desde que você não chame nenhum método de teste de SerializerTester
precisando da implementação completa da classe Serializer
, você ainda poderá fazer isso passo a passo, permanecendo no caminho clássico do TDD.