Ask HN: Do you write tests before the implementation?
1–10 of 329 posts
Re: Ask HN: Do you write tests before the implementation?
#2Once, I started with tests, but I had to rip up a lot along the way.
It is helpful to ensure testability early on. It might be easier for some devs to figure it out by actually coding up some tests early.
I won’t argue against anyone who is actually productive using hard-core TDD.
Re: Ask HN: Do you write tests before the implementation?
#3While doing this I also found one more benefit, at least for my use case. The backend for user login was simple when I started, but it started growing in a few weeks. Writing test cases saved me from manually logging in with each use case, testing some functionality, then logging out and repeating with other use cases.
Not sure if it is a practical benefit or not, but writing test cases initially also helped me rewrite the way I was configuring Redis for a custom module so that the module can be tested better.
My only issue is that it takes time, and selling higher-ups this was kind of difficult.
Re: Ask HN: Do you write tests before the implementation?
#4Almost never. I’m roughing things out first, or iterating the APIs. When the functions, data and interactions seem to stabilize, then I’ll start to put tests in. Once, I started with tests, but I had to rip up a lot along the way. It is helpful to ensure testability early on. It might be easier for some devs to figure it out by actually coding up some tests early. I won’t argue against anyone who is actually producti…
Re: Ask HN: Do you write tests before the implementation?
#5I recently started doing this. My project involved using three different services, where one of them was internal. I only had API documentation for these services and because of many reasons, there was a delay in obtaining the API keys required and I was stuck on testing my code. That's when I decided to write unit tests and mock these services wherever I am using and started testing my code. There were zero bugs in…
Re: Ask HN: Do you write tests before the implementation?
#6Can you describe the practical benefit? Say, a change is executed on one section of the (enterprise level)application. You missed addressing an associated section. This is easily identified as your test will FAIL. When the number of feature increases, the complexity of the application increases. Tests guide you. They help you to ship faster, as you don't need to manually test the whole application again. In manual testing, there are chances of missing out few cases. If it's automated, such cases are all executed. Moreover, in TDD - you only write code which is necessary to complete the feature. Personally, tests act as a (guided)document for the application.
Do you happen to rewrite the tests completely while doing the implementation? Yes, if the current tests doesn't align with the requirements.
When does this approach work for you and when did it fail you? WORK - I wouldn't call it a silver bullet. But I am really grateful/happy to be a developer following TDD. As the codebase increases, when new developers are brought in - TESTS is one of the metrics which helps me ship software. NOT WORK - a simple contact only based form(i.e. a fixed requirement having a name, email, textarea field and an upload file option), I rather test it manually than spend time writing tests
Re: Ask HN: Do you write tests before the implementation?
#7I mean how many of you stick with this test driven development practice consistently? I have been doing this for a while now. Practically, saves me a tonne of time and am able to ship software confidently. Can you describe the practical benefit? Say, a change is executed on one section of the (enterprise level)application. You missed addressing an associated section. This is easily identified as your test will FAIL.…
Re: Ask HN: Do you write tests before the implementation?
#8To answer your question properly, you need to back up a bit. What is the benefit of TDD? If you answer is "To have a series of regression tests for my code", then I think the conclusion you will come to is that Test First is almost never the right way to go. The reason is that it's very, very hard to imagine the tests that you need to have for your black box code when you haven't already written it.
You might be wondering why on earth you would want to do TDD if not so that you can have a series of regression tests for your code. Remember that in XP there are two kinds of testing: "unit testing" and "acceptance testing". An acceptance test is a test that the code meets your requirements. In other words, it's a black box test regression test. You are very likely to do acceptance testing after the fact, because it is easier (caveat: if you are doing "outside-in", usually you will write an acceptance test to get you started, but after you have fleshed in your requirements, you normally go back and write more acceptance tests).
If acceptance tests are regression tests, why do we need unit tests. A common view of "unit tests" is to say that you want to test a "unit" in isolation. Often you take a class (or the equivalent) and test the interface making sure it works. Frequently you will fake/mock the collaborators. It makes sense that this is what you should do because of the words "unit" and "test".
However, originally this was not really the case as far as I can tell (I was around at the time, though not directly interacting with the principle XP guys -- mostly trying to replicate what they were doing in my own XP projects. This all to say that I feel confident about what I'm saying, but you shouldn't take it as gospel). Really right from the beginning there were a lot of people who disliked both the words "unit" and "test" because it didn't match what they were doing.
Let's start with "test". Instead of testing that functionality worked, what you were actually doing is running the code and documenting what it did -- without any regard for whether or not it fit the overall requirements. One of the reasons for this is that you don't want to start with all of the data that you need and then start to write code that produces that data. Instead you start with a very small piece of that data and write code that produces that data. Then you modify the data and update the code to match that data. It is less about "test first" as it is about decomposing the problem into small pieces and observing the results of your development. It does not matter if you write the test first or second, but it's convenient to write the test first because before you can write the code, you need to know what change you want the code to enact.
One of the reasons why the term "BDD" was invented was because many people (myself included) thought that the phrase "Test Driven Development" was misleading. We weren't writing tests. We were demonstrating behaviour of the code. The "tests" we were writing were not "testing" anything. They were simply expectations of the behaviour of the code. You can see this terminology in tools like RSpec. For people like me, it was incredibly disheartening that the Cucumber-like developers adopted the term BDD and used it to describe something completely different. Even more disheartening was that they were so successful in getting people to adopt that terminology ;-)
Getting back to the term "unit", it was never meant to refer to isolation of a piece of code. It was meant to simply describe the code you happened to be working with. If we wanted to write tests for a class we would have called it "class tests". If we wanted to write tests for an API we would have called it "API tests". The reason it was called "unit test" (again, as far as I can tell) is because we wanted to indicate that you could be testing at any level of abstraction. It's just intended to be a placeholder name to indicate "the piece of code I'm interested in".
I think Michael Feathers best described the situation by comparing a unit to a part in a woodworking project. When you are working on a piece, you don't want any of the other pieces to move. You put a clamp on the other pieces and then you go to work on the piece that you want to develop. The tests are like an alarm that sounds whenever a piece that is clamped moves. It's not so much that you are "testing" what it should do as you are documenting its behaviour in a situation. When you touch a different part of the code, you want to be alerted when it ends up moving something that is "clamped" (i.e. something you aren't currently working on). That's all. The "unit" you want to clamp depends a lot on how you want to describe the movement. It might be a big chunk, or it might be something incredibly tiny. You decide based on the utility of being alerted when it moves.
So having said all that, what is the benefit of TDD? Not to test the code, but rather to document the behaviour. I've thought long and hard about what that means in practical terms and I've come to the conclusion that it means exposing state. In order to document the behaviour, we need to observe it. We have "tests", but they are actually more like "probes". Instead of "black box" interactions (which are fantastic for acceptance tests) we want to open up our code so that we can inspect the state in various situations. By doing that we can sound the alarm when the state moves outside of the bounds that are expected. The reason to do that is so that we can modify code in other places safe in the knowledge that we did not move something on the other end of our project.
Anything you do to expose state and to document it in various situations is, in my definition anyway, TDD. Test First is extremely useful because it allows you to do this in an iterated fashion. It's not so much that you wrote the test first (that's irrelevant). It's that you have broken down the task into tiny pieces that are easy to implement and that expose state. It just happens to be the case that it's extremely convenient to write the test first because you have to know what you want before you can write it. If you are breaking it down in that kind of detail, then you might as well write the test first. And, let's face it, it kind of forces you to break it down into that detail to begin with. That's the whole point of the exercise.
There are times when I don't do test first and there are times when I don't do TDD. I'll delve into both separately. First, I frequently don't do Test First even when I'm doing TDD if I'm working with code that has already got a good TDD shape (exposed state with documented expectations). That's because the "test" code and the production code are 2 sides of the same coin. I can make a change in the production behaviour, witness that it breaks some tests and then update the tests. I often do this to stress tests my tests. Have I really documented the behaviours? If so, changing the behaviour should cause a test to fail. If it doesn't, maybe I need to take a closer look at those tests.
Additionally, I don't always do TDD. First, there are classes of problems which don't suit a TDD breakdown (insert infamous Sudoku solver failure here -- google it). Essentially anything that is a system of constraints or anything that represents an infinite serious is just exceptionally difficult to break down in this fashion (woe be unto those who have to do Fizz Buzz using TDD). You need to use different techniques.
Jonathon Blow also recently made an excellent Twitter post about the other main place where you should avoid TDD: when you don't know how to solve your problem. It is often the case that you need to experiment with your code to figure out how to do what you need to do. You don't want to TDD that code necessarily because it can become too entrenched. Once you figure out what you want to do, you can come back and rewrite it TDD style. This is the original intent for XP "spikes"... but then some people said, "Hey we should TDD the spikes because then we don't need to rewrite the code"... and much hilarity ensued.
I hope you found this mountain of text entertaining. I've spent 20 years or more thinking about this and I feel quite comfortable with my style these days. Other people will do things differently and will be similarly comfortable. If my style illuminates some concepts, I will be very happy.
Re: Ask HN: Do you write tests before the implementation?
#9Test Driven Development is not actually synonymous with Test First Development. Test First is a method that you can use to do TDD. It's quite a good method, but it's not the only one. To answer your question properly, you need to back up a bit. What is the benefit of TDD? If you answer is "To have a series of regression tests for my code", then I think the conclusion you will come to is that Test First is almost neve…
Re: Ask HN: Do you write tests before the implementation?
#10Test Driven Development is not actually synonymous with Test First Development. Test First is a method that you can use to do TDD. It's quite a good method, but it's not the only one. To answer your question properly, you need to back up a bit. What is the benefit of TDD? If you answer is "To have a series of regression tests for my code", then I think the conclusion you will come to is that Test First is almost neve…
Thanks for your perspective. One issue is that it is often hard to tell in advance whether you know what you are doing or not. Also in my experience some implementation details can lead to a revision of the interface as well.