Live data from Hacker News

Ask HN: Help me see why everyone seems to love TDD?

news.ycombinator.com

11–20 of 89 posts

Re: Ask HN: Help me see why everyone seems to love TDD?

#12
Most importantly, for a larger code-base, unit tests allow a team to make structural and behavioral changes with much less risk of breaking existing functionality. This is especially true when one has a lot of business and domain rules to maintain. One small code change to core logic can have great impact.

Also, I have a lot of customers to support. Unit tests allow me to have confidence that I won't get 'the middle of the night call'. Largely because of them, my small team is able to work 40 hours a week and focus on adding new value rather than putting out fires.

Unit tests provide self-documentation. When starting to get familiar with new code, I first look for unit tests. If written properly, they provide great examples of primary use cases.

Finally, unit tests allow me to design better systems and interfaces. I can take a class or library and work on it in isolation from other parts of the system. Starting from consumer interface first, I can focus on what is really important and to make that interface much more usable. I can add parts incrementally without worry of breaking that core.

Like most things in software, TDD has trade offs. At first, implementation is much slower, and it requires significant knowledge of unit test best practices. I've seen a lot of bad unit tests: ones that don't test important things, ones that rely on external systems or libraries. I've seen developers get caught in 'unit test paralysis' - where they avoid tackling more important things because they are too focused on testing edge-cases, etc.

There's an entire art to unit testing. It requires pragmatism. For small projects, they're probably overkill. But, when your system grows to have many dependencies, some several years old, and someone has to make a change - ahhh, they're the best.

Re: Ask HN: Help me see why everyone seems to love TDD?

#13

#1 A change in your current process must be "sold" in the business context of $$savings (faster dev cycle, lower number of bugs, lower cost of support) or increase in developer productivity/utilization or increase in customer satisfaction. #2 Inadequate unit testing almost always correlates to greater defects in the support/maintenance cycle. So I would recommend gathering some data around it: for e.g., number of ope…

You're not going to get a much better reply than this. Speak their language, they will listen. Especially if you have access to historical data, it can be pretty easy to cherry pick some examples of where the improved QA would have had drastic savings.

People fear change, but no one wants to throw away money. Make them see the dollar signs.

Re: Ask HN: Help me see why everyone seems to love TDD?

#14
TDD came out of agile programming which is also more concerned with fast delivery than NASA-style correctness. It's a tool supposed to help you go faster.

If you want an agile unit test suite, it has to run in seconds, not minutes. TDD will make this very clear. If you have problems with the test suite being slow, you have to fix it!

A test suite that developers actually like to run is an enormous value, maybe especially for new team members. It gives you confidence when making changes and adding features.

A basic purpose of TDD is to make it obvious when code is hard to test, so that you're always encouraged to write units that can be unit tested without difficulty. That's a skill that takes some practice and learning, and you need to pay real attention to it. When your team understands how to do it, that's when the test suites start to make real sense, and it becomes pretty much a pleasure to write the tests.

I don't know about being a consultant but I'd like to say that comprehensive testing is a necessary standard part of professional programming just like serious manufacturers verify the quality of components. It can also reduce the stress and anxiety of developers which leads to a better work environment and better quality.

As a coder in a team with half legacy and half well tested code, I know it was a delight to work on the modules developed according to good TDD practice.

Re: Ask HN: Help me see why everyone seems to love TDD?

#15
I've seen two main reasons why people love TDD.

First, testing is hard. It's a different mindset than development. TDD places testing first, which forces people to think about testing while doing development. From many accounts, this is an eye-opener which gets people to understand more about the whole process.

Second, it's a negotiation tactic. Developers usually have much less negotiation experience or influence in a project. It's all too easy to get something "working", then buckle under pressure to ship, even if the code isn't fully tested. Pressure is highest at the end of a project, so placing tests first means they won't be cut back as much. Also, developers can point to the methodology as a way to deflect the pressure from themselves.

Personally, I've tried TDD and found it to get in my way more than it's helpful. I mostly write my tests after writing the code, in an iterative style so the tests are usually written shortly after the development. (I have another stage of testing when I write the documentation and cookbook - that's where I usually find the code which is implemented "as specified", but where there sharp corners I didn't identify until I could use the code as part of a system.)

I have no answers to your underlying goal. One observation: you wrote "Unit tests aren't "valuable" to the customer". Have they considered value to the company?

Re: Ask HN: Help me see why everyone seems to love TDD?

#16
Well, I'm not entirely sold on TDD just yet, but after applying it for a few years now, the benefits seem to be:

- Requires you to think about structure before you write the actual code. Code that is unit testable is usually better code. (but not necessarily)

- Requires you to think about the scenarios that you will support beforehand.

- Ensures that every file is unit tested. Without TDD you can have untested files. Why unit tests are great is another topic entirely.

- Ensures that tests cannot return false positives. TDD requires you to write and run your tests before any real code is written, so all tests should be red in the beginning. If you write your tests afterwards, your test could be green when in fact the code is incorrect.

What I don't like about TDD is that it pushes your code towards very easy to test code, which is not always better code. I'm more inclined nowadays to just start with the actual code, refactor iteratively until I'm satisfied, and then write the tests. This reduces the total amount of work, because otherwise you also need to refactor your tests every iteration, which only gets written at the end with my method. The downsides are that unit tests can be forgotten, or that you can write false positive tests. In my experience though, this rarely happens.

The most important part - imho - is to have meaningful unit tests.

Truth be told, I value solid integration tests more than unit tests, because they actually test the input/output of your system, which at the end of the day is the most important thing. Unfortunately integration tests tend to be more fragile and require more maintenance. On the other hand, they are more resistant against refactoring, while unit tests essentially have to be rewritten when any kind of refactoring happens.

Nowadays, I write both unit tests and integration tests, which is expensive to write and maintain, but in return they provide you with peace of mind and confidence, which is priceless imho.

Re: Ask HN: Help me see why everyone seems to love TDD?

#17
1. TDD can make delivery timelines more predictable, as there is less chance of regressions being introduced as new features are added. This predictability can allow a team to scale up to larger and more lucrative projects.

2. TDD enhances the capacity for necessary refactoring to take place which reduces the complexity of the codebase. By reducing complexity we can increase development productivity.

3. TDD itself can speed up development. A developer will necessarily have to test the feature he is building. Manually testing this feature will be time consuming and repetitive. An automated test allows the developer to quickly test the specific element that is being built in a repeatable and verifiable manner.

4. You are saying that the QA team is not catching all the defects. What else is new, but if you are delivering poor quality product to your customers then this may have commercial consequences in the future, if not already.

5. TDD is best practice and is necessary for the professional development of the team. If TDD is not supported it will negatively impact the ability of the business to retain good developers.

But aside from that, if we are talking about software development inside large corporations, we are probably talking about half-baked internal projects that aren't going to go anywhere due to a variety of reasons. The are probably a whole host of things to change within any large corporate of which the introduction of TDD is but a minor concern.

Re: Ask HN: Help me see why everyone seems to love TDD?

#18

Taking 40min for the unit tests to run points to a problem, however, I've seen my fair share of "TDD geniuses/advocated" that love doing things that slow everything down (like writing hundreds of minuscule testings where 2 or 3 things could be tested in the same test, big setup methods, etc)

Hmm, having a test do anything more than one thing sounds like a functional or integration test.

Re: Ask HN: Help me see why everyone seems to love TDD?

#19
First of all, if your unit tests take 40 minutes to run (unless it's an insanely large codebase) then there's something wrong with your unit tests.

TDD isn't as much about being "correct" as it is about writing your API (and I mean internal API -- the classes and methods your software uses internally) first and then implementing the details. A side effect of TDD should be better designed software, which should in turn speed up your development.

The reason I brought up slow unit tests first is multi faceted. Most likely, they aren't really unit tests. You're probably testing the class in addition to the classes that your classes are touching (i.e. DB connections, etc). This is probably partially because unit tests are foreign to your developers and thus they don't know how to properly write unit tests, but additionally (more important to your concern about delivering software quickly) its probably a result of your classes not being easily testable. By making your classes more testable, you end up breaking things up, removing dependencies, programming to interfaces instead of implementations, etc.

Additionally, its easy to argue why delivering correct software helps deliver software quicker. If you deliver broken software, which takes down systems, developers need to spend time fixing the broken software. This time spent is extremely expensive. It disrupts the day, is a distraction, and depending on the extremity of the bug, can affect entire teams.

Beyond all that, knowing earlier on that your software is correct helps you move on to the next thing. When I say this, I don't mean verifying correctness after pushing to production. As an example, you need to update a database record based on some input from the user. Traditionally in order to do this you need to write a method on a model to do the updating, and you need to write a controller to call that method given query parameters, and you need to write a view to take user input and post a form. You may start with the model method, and it'll take you an hour to finally be able to test that your model method is working properly. If this fails, you have three separate places where it could have failed, so you need to look through the code to figure out where exactly it fails. Was it a forgotten csrf token? Did you forget to save in your model method? Did your controller simply not call the model method? With TDD, you'd write a test first to verify your model is working. Then you'd write a test to verify your controller is working (or not? some people don't test controllers). Then you'd write a test that your view shows the form and submits. As a result, you'll find out earlier and more specifically where issues lie.

All that said, its good to learn how to TDD with very strictly writing tests first, but in practice you need to understand the need to be pragmatic about it. It often doesn't make sense to write tests first, and you need to understand that its unrealistic to test every possible case.

Re: Ask HN: Help me see why everyone seems to love TDD?

#20
The deal with TDD is you write twice as much code and you have less than half the bugs. As the project grows, it gets harder and harder to maintain and change unless you have good tests. Most projects without good tests that I've seen grow to a certain size and then become very difficult to make progress on because people are too scared of breaking things and the releases inevitably take a very long time due to all the QA.

One great thing about TDD is that I can pick up a project I Haven't touched in a very long time or am new to and work on it and as long as all the tests run, I know I didn't break anything. Without tests, the intimate knowledge of the requirements of a system tend to get lost and the project quickly becomes unmaintainable without a guru and active development.

I'd also say that having some tests from the start is much better than not having tests. The main reason for this is that to have tests, the code has to be developed with testing in mind. The second thing is that if you have a build system and a framework for writing tests, you can easily add new tests for tricky bugs or corner cases.

If you really want to go fast and loose, you should at least have a happy path integration test, a test for all the dao methods and at least a happy path test for the controllers. Any parts of the code that are tricky or algorithmically clever should also have tests. As your QA team runs into regressions, write tests for those regressions. This is a way I've found to amortize the test writing somewhat. It's important though that the test running is integrated into the build at these levels and is run before every release.

Post reply on HN