True Test Driven Development

So currently I am working on a project. I am trying to follow TDD as much as possible. I want my tests to drive my implementation.

Now suppose I realise before itself that I need a class called Animal, and then i start writing specs for it, and then implement the method for the Animal class like speak. But later I realise I am need a way for a cow to speak and also a Cat to speak. So i write the specs for them first which drives my implementation so complete their method implementations. In this you can then starting doing the inheritance where Cat < Animal and in this case you are not writing any new specs and just modifying the old specs.

Now here is the 2nd scenario. You know u want a cow and a cat and they have their versions of the speak method. You write specs, make them pass. During the refactoring u realise that u should start doing the inheritance and then u introduce the Animal class just ike above and then start moving code from ur subclasses to the animal classs. Do u write specs in this case?

Would this be TDD in this true sense?

Sorry for my lame English since English is not my native language.

I think than you must to think about what you want to do and how you want to make it working. As example, you want to have a cat which say “miaou”. You can write a spec like this :

describe Cat 
  it "say miaou" do
    expect(subject.speak).to eq "miaou"
  end
end

Run it to make if fail. Do the simplest code to make it working. Refactor and pass to the next spec.

You want to have a cow which say “meuh” and you write this :

describe Cow
  it "say miaou" do
    expect(subject.speak).to eq "meuh"
  end
end

Run it to make if fail. Do the simplest code to make it working. You don’t really need to do a subclasses or a composition at this point. Imagine you want to introduce the notion of living for both. First you implement it for Cat like this

describe Cat 
  it "say miaou" do
    expect(subject.speak).to eq "miaou"
  end


  it "is living" do
    expect(subject).to be_living
  end
end

Run it to make if fail. Do the simplest code to make it working. Now, at the refactor part, you now you will use elsewhere so you can introduction a module and test it like this :

describe ActsAsAnimal
  class Animal
    include ActsAsAnimal
  end

  it "is living" do
    expect(Animal.new).to be_living
  end
end

Now, use the new module in your classes. Do you still need the spec in Cat spec? No because you assume that the module is working so you can remove it. You can now use the module in the cow class without to add a spec.

The final implementation can be like this :

class Cat
  include ActsAsAnimal
  
  def speak
    "miaou"
  end
end

class Cow
  include ActsAsAnimal
  
  def speak
    "meuh"
  end
end

module ActsAsAnimal
  def living
    true
  end
end

Now lets talk about BDD insteed TDD. Does provide classes about Cow and Cat is what you want to give the final user? I think not. With BDD, you must to think about what the user want to do and how he what to do it. You must to start by the higher level with tools like capybara or cucumber. Run your spec to make it fail and when you make the code to make it work do the unit tests as in the example with Cow and Cat.

TDD and BDD are hard to learn. The important thing is to find your own way. How can you be more productive and how can you have a good feeling of what you are doing.

I did a longest answer than I except at the beggining. My answer is not the “truth”. Their is no “True TDD”. There is only best practices provided by guys who went by the same way than you are doing now and say what they learn.

Bye!

1 Like

You should not think like this before hand. When writing a test, think about the behaviour you need to add to the system, such as I need a way to create cats, or I need have a cat meow. Then write the simplest thing you can think of, if it is to create a Cat class, so be it.

If you think of your tests from this perspective, I think you’ll find it easier to know how to go about it.

1 Like

@zamith @Guirec_Corbel Thanks a ton guys :smile: