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?

Latest comments (39)

Collapse
 
cullophid profile image
Andreas Møller

I personally never found TDD all that helpful. It can be a great tool for providing feedback during development but it's not the only one.

With typescript + hot reloading, TDD doesn't really bring any value for me.

I also rarely write unit tests for the same reason.

Collapse
 
marinafroes profile image
Marina Costa

Hi, João. I'm a code newbie and I'm still on that frustrating stage, trying to understand and implement tests in React. The concept of testing and TDD is great, but right now I don't know exactly how to get started. Do you have any recommendation for me?
For instance, do you use react-testing-library? Do you recommend a good resource for learning it (or other testing libraries)? Any hint will be really appreciated. :D

Collapse
 
imforja profile image
João Forja 💭

Hi Marina :)

When dealing with React applications, I tend to use Cypress, cypress-testing-library, react-testing-library, and Jest.

While knowing how to use test-related tools is a good thing, after you've learned the basics (running tests, assertions, and mocks), learning more about the tools probably won't do much to alleviate your testing/TDD frustrations, as most of them come from a lack of understanding of the goals and processes of testing/Test-driving an application.

Do you have a specific example of something that you would like to test but don't know how? I think I can give more accurate and useful hints if we go over a specific example that's causing you frustration, rather than talking about what I think is important in general when testing an application :)

Collapse
 
marinafroes profile image
Marina Costa

Hey João, thanks for replying.
I think you are right, I'll first learn the basics of testing before diving deeper in the tools. That's where the frustration comes from, for sure.
No specific examples right now, but you answer already helped me. And I'll keep following your other articles on this subject. Thanks!

Thread Thread
 
imforja profile image
João Forja 💭

Glad I could help. Feel free to reach out if you have any particular question you think I could answer :)

Collapse
 
jaedle profile image
jaedle • Edited

I kindly disagree: The tests should not affect the implementation.

I use TDD all the time (on my job and 90% of my hobby projects) and the most I think I like about it:
the structure of the test can be completely decoupled from the structure of the implementation:
Maybe the test has 2 classes, but the implementation has 1, 2 or even 15. I always test the outside behavior of the module, never private details.

 
odedshr profile image
Oded Sharon • Edited

I get you. Writing tests is indeed important, I'm happy for you that all your clients can not only afford your work but also understand and value the quality of your outputs. I also appreciate the fact you clearly know how to efficiently write concise tests that give you and your client great certainty that the code won't fail. I wish all the clients would be like your clients.

Collapse
 
odedshr profile image
Oded Sharon

How much time do you spend on writing tests?
Let's say the client asked you for a feature that will take you 1 hour to write and 2 hours to include tests. Will you charge him for 2 hours? What if the client cannot afford two hours? Will you be willing to reduce the amount of tests? (Imagine it's a question you're asked in a job interview - how critical is it for you to meet the deadline?)

Collapse
 
ashleyjsheridan profile image
Ashley Sheridan

I think sometimes TDD gets confused with ensuring good unit test coverage. True TDD means writing the tests before the actual code, something I admit I've never been a fan of or managed to get into the practice of doing. However, I am a fan of good (meaningful) test coverage, I just write tests after writing the code.

I think after a while of writing tests, you end up learning how to write code that's more testable as a matter of course.

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
 
dbroadhurst profile image
David Broadhurst

If you are a very lean team trying to move quickly and progress is more important than stability then it makes no sense to spend time writing tests for code you know will radically change.

It's so frustrating to see teams trying to hit coverage numbers with useless tests. Put a value in a prop and see if the value was rendered. Lol, we've got 90% coverage with mostly useless tests that add no value, but we've got high coverage.

Projects move through different phases and high-performance teams adjust to ensure the business is supported in a way that makes the most sense for each phase.

Collapse
 
psfeng profile image
Pin-Sho Feng

I'm of the opinion of DHH, that there's a lot of test-induced damage caused by TDD.

These days I almost never write unit tests anymore, I've almost completely replaced them with integration tests, as suggested by Kent C. Dodds. As I work on the backend with Kotlin, I use test-containers to spin-up the DB, RabbitMQ or whatever, and then test the app as if it was a function (hitting an endpoint and asserting the response, for example).

One of the biggest advantages to doing this is that the tests are completely decoupled from the code (which you typically get when you use mocks), so you can refactor freely and all you have to do is run the tests to see you haven't broken anything.

When you do these sort of tests, TDD doesn't apply much anymore because you often need to connect a few components before you can actually see a result, so the "write a failing test, fix it" iterative process doesn't fit.

One question I often get when someone sees this approach for the first time is, what do you do when the system under test has a lot of variations? For those cases, I've found that a table-driven approach has always worked well. I've found that the amount of permutations you'd write if you were unit testing would pretty much be the same, if not more as some tests from other layers might overlap.

Another good article on the topic that describes well the philosophy: blog.twitter.com/engineering/en_us...

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 😆.