DEV Community

João Forja 💭
João Forja 💭

Posted on

What are your thoughts on testing and TDD?

I discovered testing and TDD when I was in university. I was trying to find something that could improve my programming skills overall and not just my skills in a specific language or stack.

To cut a long story short, I had excellent results as my grades greatly improved across all programming subjects. It wasn't only due to TDD, but it played an important role.

Because of how well things went during university, I naturally used it and still use it in my professional life as a Front-end developer. And given that I'm able to keep my developer experience pretty stress free code-wise, I'd say that things have been going pretty well.

If I had to say why I find testing and testing as used in TDD so amazing is because of 2 things:

  1. It forces me to think before and while I write code. This makes me find holes in the requirements and opportunities to improve the code's design.
  2. _It gives me a development process that lets me stay focused on my task at hand, which makes me more productive and less stressed.

Although it can be frustrating at the beginning, my opinion on testing and TDD is pretty good, and I recommend people try it out.

What's your opinion on testing and TDD?

Top comments (39)

Collapse
 
alainvanhout profile image
Alain Van Hout

Unsurprisingly, whether TDD and automated testing in general is useful/essential depends greatly on the task at hand. Similarly, riding your bicycle to work has a great ROI value, but using it to get a snack from the fridge, not so much 😆.

Collapse
 
odedshr profile image
Oded Sharon
  1. The clients don't pay for writing tests, the pay for code that works. That established, how much (percentage-wise) are you planning to spend on writing tests?
  2. Brenan Keller @brenankeller wrote: "A QA engineer walks into a bar. Orders a beer. Orders 0 beers. Orders 99999999999 beers. Orders a lizard. Orders -1 beers. Orders a ueicbksjdhd. First real customer walks in and asks where the bathroom is. The bar bursts into flames, killing everyone." (and that's my personal experience, writing gazillion tests and still failing at runtime)
  3. TDDS are just as important as making small git commits or saving your work every 2 minutes; They are sort of insurance that you're not messing up, yet the unexpected will always surprise you.

Yes, TDD is great, but only when it makes sense (i.e. don't make it into religion);

Collapse
 
imforja profile image
João Forja 💭

People certainly can take it too far and make it into a religion. Like it is some silver bullet that will solve all development problems when it won't. It's a technique that has its advantages and limitations, although I'd say it is one of the more useful ones I've come across. But I'm probably totally biased.

About point 2, I think it covers one of the limitations of TDD. TDD can never find an unexpected new bug in a system for a simple reason. We are the ones writing the tests, and that means that they are limited by our imagination. And, speaking for myself, we aren't very good at imagining all the ways our programs can break. We could try to stretch our imagination and write tons of tests, but then we end up with a codebase that's much harder to maintain than it needed to be. The way I found to deal with this issue is just to write enough tests to force me to implement a feature, and after the feature is "done" use exploratory testing to find bugs I didn't imagine could exist. And then write regression tests for those new-found bugs. It's been working great so far :)

Collapse
 
haruanm profile image
Haruan Justino

I think item 1 does not consider the time spent on executing tests. When we work with software that keeps evolving during the time, writing tests makes you spend less time with tests then executing them manually every time.

Collapse
 
g105b profile image
Greg Bowler

There's a difference between an engineer and a hacker. One isn't better than the other, but have different values.

Applying an engineering approach to software development is impossible without test driven development, but sometimes hacking something together is where the value is.

Collapse
 
imforja profile image
João Forja 💭

You reminded me of a talk from Kent Beck . He expressed really well that idea that hacking and engineering can have important roles in development depending on which stage a project is at.

Collapse
 
johnwantsmore profile image
John

I'm frankly still struggling to grasp how to implement tests/TDD effectively in a large, real-world application.

(More specifically, I have trouble with the idea of unit tests; functional tests fit my thinking and understanding better).

I've had a taste of how useful it can be in small side projects, but when I look at the large-scale fintech loan pricing product I develop for a client, while I can INSTANTLY see the value in having a suite of tests that will guarantee adding a new variable doesn't break the pricing algorithm, I just can't picture how to build up the suite of tests around it.

I'm also still "catching up" on general thinking around pure functions and testable code, so I'm sure that's where a lot of the problem lies for me. Poorly written code will never be effectively testable.

So all of that said, I'm working hard towards learning and using TDD.

P.S. - Don't get "comfortable enough" with what you know and stop learning and keeping up with best practices and paradigms, especially not for years "while you focus on the business side." Playing catch up after 15 years in the industry is just. no. fun.

Collapse
 
imforja profile image
João Forja 💭

I agree that in real-world applications, it's harder to do TDD. In my opinion, it's due to the increase in the complexity of the domain. So my strategy has been to break features down into degenerate cases that are simple enough for me to know how to write a test for them. After implementing the degenerative case, I then proceed to iterate into the next degenerate case that brings me closer to the full-fledged feature.

This example is a bit too simple, but if I have to develop a table that fetches data and has tons of sort options, my tests will probably go something like this "Shows loading while fetching" -> "Can show an error message when fetching data fails" -> "Show's message to the user if there's no data to show" -> "Can show one row" -> "Can show multiple rows" -> "Can filter rows by 'Property1' " -> "Can filter rows by 'Property2' " -> "Can filter rows by 'Property1' and 'Property2' " -> etc. Some tests might be redundant at the end of the implementation, and I'll probably delete them if that's the case. But going through this process gives me more confidence in what I'm doing and tend to lead to better tests and design.

Small steps help a lot.

Collapse
 
jaedle profile image
jaedle

Testability comes from good design and architecture, I agree.
But starting somewhere is really important. Maybe you can start with a high level test without edge cases like:

Given this input I expect this output. Add a few of them covering different code paths (delta coverage per test) and try to move forward.

Collapse
 
jamesmh profile image
James Hickey

The Pragmatic Programmer (book) nails it:

Thinking about writing a test for our method made us look at it from the outside, as if we were a client of the code, and not its author.

And:

...most of the benefit of testing comes from thinking about the tests and their impact on the code. And, after doing it for so long [30 years], I could do that thinking without actually writing tests. My code was still testable, it just wasn't tested.

Collapse
 
bcbreeden profile image
Brian Breeden

I like this perspective.

Collapse
 
cullophid profile image
Andreas Møller

Indeed. But you really don't need to be doing TDD for 30 years (or at all) to get there

Collapse
 
imforja profile image
João Forja 💭

Gotta love that book. It aged really well!

Collapse
 
leob profile image
leob

TDD: absolutely fantastic and valuable if you have the skills and discipline to use it. One of the most elusive phenomena in software engineering, something of a holy grail, many people say they want it, comparatively very few actually do it (or do it well, at least).

Collapse
 
pclundaahl profile image
Patrick Charles-Lundaahl

I use TDD semi-regularly in my hobby projects. I've also spent the last month getting my team's main tool set up with a proper test suite. It's more for regression tests than TDD, but I'm excited about it, all the same.

I would say my experience with TDD is fairly similar - my code is better, and I think about my designs in more detail before implementing. I don't usually implement all the tests up-front, but I'll write down a large number of test synopses, and then implement the most important ones (and come back after to fill in the edge cases, just to validate my work).

Collapse
 
imforja profile image
João Forja 💭

That's a great observation. A lot of developers don't know how to write tests and how to write testable code. I think that a lot of that has to do with the culture of the company they're in. Especially when we're talking about project-based companies, which tend to privilege shipping as soon as possible vs. reducing the cost of development on the medium to long term, it's a kind of environment that privileges hacks over a sustained practice, which makes testing and TDD hard to flourish. So it's unlikely for someone working in a situation like that to be given the time to learn or to have someone to teach them how to test/TDD. At least, that's my experience.

Collapse
 
adrianmarkperea profile image
Adrian Perea

I use it all the time, based on the same two points you mentioned.

Collapse
 
tulkdan profile image
Pedro Correa

Pros

For me it's the best way to implement a feature, you simply implements slowly and with a lot of confidence.

And the mais reason that i like it, is that you tend to create the feature in the most readable way.

Collapse
 
imforja profile image
João Forja 💭

Completely agree!

I liked how you mentioned that it lets you implement something slowly and with lots of confidence. I think it clearly expresses the feeling of being in control of the code that TDD can give.