I really want to use TDD in my professional work to ensure it’s robust and stable but I’m struggling a bit in following the process as soon as I reach a little bit of complexity.
I was wondering how you all go about it?
I really want to use TDD in my professional work to ensure it’s robust and stable but I’m struggling a bit in following the process as soon as I reach a little bit of complexity.
I was wondering how you all go about it?
For further actions, you may consider blocking this person and/or reporting abuse
Hanzla Baig -
Hanzla Baig -
shadowy-pycoder -
Michael Joseph -
Top comments (12)
Firstly, I second the recommendation for Kent Beck's book made by @Evgeniy.
The next thing is that I don't find TDD suitable for "prototyping", or trying things out with code until you have a general idea of what you need to do.
In other words, if I ask you "how would you do X", and your response is "no idea", then maybe you can't use TDD, because you might not know how you could possibly design the code. First you might try out some code until you get the general idea. Then your response may change to "Oh I see. I would have a random generator here, use the result like so and return blah". You can work with this.
That's because when doing TDD you're essentially asking "how do I want to call this method or class"? Writing the test means you have answered this question in your head. That's equivalent to asking "how do I design this feature?", at least from the point of view of the rest of the codebase. So to TDD is equivalent to having figured out a design, at least for the immediate test you want to write.
So, you either:
Of course, in all cases you can go back and make changes, so don't worry about getting it perfect.
Also the more you use TDD, the better you'll get, so keep it up!
Unless you have an abstraction on top of an existing business area everywhere it is really hard to do TDD. In the latter case TDD is only suitable for implementing change requests or small feature updates to existing code.
It is easy to write a test with framework of abstractions:
instead of just a plain disaster:
Starting a project with TDD might IMHO kill the project in question unless you're doing something you've already done before many times and you have very clear idea what to do at each step.
I think it depends. However I'm not so sure about the particular example above.
Sure, maybe if you're really experienced with TDD, you could work with that. But it might be best to start with very little code per test. That way you focus on testing a unit, a public function of the class, not the entire class in one test.
So you only test a small thing at a time, and design a small thing at a time. Also you can go in a loop of writing a single test, making it pass, repeat. It's not necessary to write more.
One of the important parts is the design, please see my previous comment for more details on that.
As I also mentioned, TDD is optional. If your code design is sufficient, and you don't require the benefits of TDD, then that's okay too.
In a test you should test isolated feature.
In my example I tested correct instantiation of an object only. That's it. I didn't even test if the function Bark() produces any result, let alone a correct result based on constructor parameters. Only if it exists in a list of available object functions for a dog type object. I honestly don't think that's too much for a test content.
Do you think it is?
In contrast any other approach cannot even compile your test project as it cannot resolve Dog class.
Then if you fix it, it won't compile unless you implement missing properties.
Then you implement the properties but you miss getter logic (e.g. return age if only birth date was provided).
And so on.
I need some explanation from you.
Your test examples instantiate the dog class twice to compare immutable properties. You did not even change the object state, why should you write another test to make sure the dog can bark while not testing his fur color? I don't think that makes sense. It would, only if barking changes the fur color or if the fur color changes does in fact change the output of the Bark() function. But I assume that is not the case, is it?
I find it unusable that my tests do not compile and do not fail properly until I implement the missing code. That's a big no-no for my CI/CD pipeline...
Okay fair enough. Yeah I guess the example you gave didn't really have functionality, it was more of an object which just holds properties.
You're right that we need to test an isolated feature. However what is an isolated feature? It's subjective. For an object with getters and setters, I would argue that an isolated feature is a single property you can set and get. But someone could argue that the object can't be used until everything has been set properly. In that case the test would require setting everything, as you say.
So in the end it depends. If we don't need to set everything at once, then perhaps it would be easier to have one test where we only check the age getter and setter, and another test for the name, and so on... But of course it's up to requirements and personal preference.
Not compiling is acceptable when we do TDD, it's just something we have to work with.
Edit: For the CI/CD pipeline, we don't have to commit until both a test and implementation are working.
I'm repeating myself here but TDD is optional. If it doesn't work for your workflow or preference that's fine. Sometimes I can't use it either. Sometimes I just build and refactor later.
My issue with not compiling is that it breaks my CI/CD pipeline. I'd like to create tests in my test project and the whole solution just compiles but the tests fail. This way my Jenkins/Bamboo/whatever can produce meaningful message to the developers in form of a failed test report instead of a bunch of compiler errors hidden in tons of output.
Thanks for discussion I realized some thinks I was not aware of. ;)
*I added a quick edit above about the CI/CD issue.
I definitely think TDD is worth doing, from my experience anyway. I think I might try and do the ‘figure out the design first’ method and then go back and refactor. That seems like the easiest method to get the ball rolling.
I found it really hard to write tests against Interfaces, Classes, Properties and Methods that do not yet exist. They basically make my solutions to not compile and throw a bunch of errors. If you ever find a way, please let me know...
I mean if you write a complex test against non-existent code then you've actually already:
If you've made all this (which IMHO takes most of the time), why didn't you just also write the method body?
I suppose it’s a question of ‘Are you doing TDD in a pure fashion?’ Vs ‘Do you want to be pragmatic about how you implement a good practice?’
Try "Test Driven Development: By Example" book by TDD's author(Kent Beck).
Thanks! Will give it a look