I got as far as: Oh, and good luck mocking your database and HTTP request objects. and just stopped. If you don't have any experience with TDD, then don't write about it. Mocking HTTP request objects is incredibly trivial and tools are written in every language to do just that.
I don't know why these articles keep getting written. No one's forcing you to write your tests first, and if you can't wrap your head around the benefits (which the author clearly can't) then don't do it. It's fine. I'll still continue to utilize TDD, and continue to pump out significantly more code (with significantly less bugs) than the code I produced without TDD. Yes, there's definitely code I write where I don't write the tests first. It happens, sometimes it's just easier to bang something out because you aren't sure what you're building. That doesn't mean TDD is a failure, it's a tool, like anything else. Use it where it's appropriate, because the benefits are massive.
That is very likely not true. If TDD is your "process" at work, then you are being forced to write your tests first.
If TDD was chosen to be your process because of erroneous assumptions about the values of TDD, its strengths and its weaknesses, and those erroneous assumptions are a result of religious zealotry squashing the heretics rather than reasoned debate, then you have a problem.
Religion belongs in the church, not in software. It frustrates me how poor the technical debates in software can be because people get so attached to their technology. It is directly analogous to an artist demanding a specific type of paint for all their work who freak out when somebody says "you know, a gallon of latex paint might be better than that tube of acrylic for painting the walls in here."
Isn't pair programming where you sit back and think about kittens while someone else monopolizes your keyboard? If they want to write the tests first, let 'em.
I think you're being a bit overly sensitive. I'm describing what you can do other than quit if you don't want to do pair programming. Nobody ever says no to carte blanche to do whatever they want, and if you give them your keyboard, they won't even know you're mentally watching YouTube videos involving rainbows, a repeating soundtrack, and pop-tarts taped to cats.
I forgot, anti-TDD is the trend these days. Should have made a joke about TDD being an STD in the programming world. Much better then actually contributing or correcting those who are wrong.
I know all too well, though I was being a little oblique about it. Also, your religious TDD folks and your religious pair programmers are often the same people (same religion?)
> If TDD is your "process" at work, then you are being forced to write your tests first.
Not necessarily. Usually you're only required to write a test before you start working on a specific feature. If you just want to research something I've never seen anyone who'd get in the way of you pulling up a REPL.
But even so, saying you're forced to is like saying your company forces you to check your work into a VCS before they'll give you credit for having written it. Or forces you to fix bugs/add features from a list instead of just ad-hoc.
You should have continued. His point is that while TDD is good for some things it misses huge areas and has very little ROI in most simplistic cases.
Yes, you can mock HTTP requests, but there are numerous bugs you wouldn't catch unless you went and hit your application with an actual browser. Similarly, you can mock the database, but you're not testing all the "magic" the database does and all the myriad combinations it could fail.
For those cases, tests have value in telling you where the bug isn't.
For me, one of the biggest benefits of code that has been written to be testable is that it's been designed such that it's possible to reason about fine-grained details. If I find a problem, I can generally start adding tests as part of the debugging procedure to make assertions about the specific part of the code that I think might be failing.
That's much harder to do at a sufficiently high level of detail if the code wasn't structured to make it easy from the start.
> Similarly, you can mock the database, but you're not testing all the "magic" the database does and all the myriad combinations it could fail.
You are correct. And this is why you unit test the DB and all the stored procs and queries you perform there.
And, this is also why you can add in tests that do use the database connection, and test the more complete stack. TDD does not limit you to only use the tests at the application level. It does not limit you to building other forms of tests. To imply that is dishonest. It would be akin to me saying "Because you do not use TDD, you do not test."
I have no intention of ever mocking the database, and I mock HTTP requests solely so I can work on my app without an internet connection. Look, a better approach is to use TDD for things it makes sense for. Spending a ton of time to mock out your database does nothing for you. Is mysql going to fail for you? Is the mysql driver that a million people are using going to fail for you? No? So, don't mock it out.
You don't mock the drivers.. you abstract the database layer to test for a particular data. For instance, you make getName() returns empty string, 1000 wide character string, strings with unicode, etc. It's not about MySQL; it's about what mysql returns.
Let's say you have a class that writes a string to the database. You abstract out the actual writing to the database of this string thinking it's always going to work, it's just dumping data after all. Your test passes, everything is good.
Now you optimize your database and add a restriction to make the string at most 50 characters. Your test still passes, but you now have a bug. OK, so you should've had a restriction in your BO. You add that restriction and move on.
Your DBA comes along and adds an integrity check or a trigger that makes the insertion fail if some weird condition is met. Your test passes, but you have a bug.
This can get even more interesting when you hit some basic database rule that you didn't even know it existed. You assume the insertion will work, but it won't. You now have a bug.
You've tested that 2 + 2 = 4, and it works, but when that code is linked with the actual database you realize that in some cases 2 + 2 doesn't equal 4.
I'm not saying don't have unit tests, but when it comes to bugs, the fast majority of these bugs, in my experience, come from the glue, from the assumption that the piece you're integrating with should work one way, but reality begs to differ.
IMO, TDD is a crutch. It can be useful but don't think just because they make you faster they they will continue to be necessary. I know plenty of people that found TDD extremely helpful but most of them have moved on, not because they had not found it useful but because they slowly got faster without it. I think it works like training wheals because you notice problems sooner you can start to recognize they approaches that lead to those problems and avoid making those mistakes in the first place.
PS: Having a great tests can really help maintain code, but I would much rather have cleaner code than more tests.
That's not why it's faster. It's faster because I never have to manually run through whatever I'm developing. On a large feature that I can completely write using TDD, I don't ever 'test' the feature until I'm completely finished. There's a MASSIVE time savings in not ever having to walk through anything in a web browser, and never creating any regressions while fixing anything that breaks later in development.
I'm surprised not many people have talked about BDD. BDD lets you focus on the behavior of a method, class, or a set of methods/classes that interact with each other without worrying about the internal implementation details, unlike TDD where you test every method and may end up with tests for dead code. BDD lets you paraphrase what you're trying to do and tells you when you're done. Having said that, i have to agree that TDD/BDD is just a tool and no one should be forced to using it as the only method.
As far as the problem of mocking http requests is concerned, most frameworks like Rails/Spring come with http mocks. But a much better solution is to make your controller code as trivial as possible and move as much of your business logic to models. RESTful design helps you solve this problem. This is not just useful for web applications. Moving your logic from controllers to models is a good MVC principle too. It gives you the flexibility to use a different GUI toolkit for the same code.
As far as the problem of mocking database calls, it depends on whether you prefer your test suites to be real or fast. For simple database calls, I'd rather hit the database and end up with tests that assert behavior than tests which redundantly repeat what the code is trying to do using mocks. Mocking is still a useful technique for things you can't control like an External API.
TDD/BDD is useful for most of the model-centric work we do in Web based software. I'm not sure how useful it would be in areas like language design, framework design, mathematical modeling, algorithm design etc. QuickCheck or some other form of program verification will be a much better choice if your work involves designing/verifying complex algorithms. Djikstra's quote:"Testing shows the presence, not the absence of bugs" points out the problems with TDD. TDD ensures your system satisfies the specs and the addition of new features don't break existing behavior. But it does not protect your system from behaviors you did not anticipate when you wrote the code/tests in the first place. TDD/BDD will not make you a smarter programmer. Genius programmers like Rich Hickey don't need TDD. Hey, But we are mere mortals who work with other mere mortals in building non trivial systems. And TDD is just one of the ways to ensure fewer bugs in the system.
More accurately, nobody's forcing you to take a job where you disagree with the methodology.
I've had to deal with agile whining for nearly a decade now. The only thing to do is ask them to find work elsewhere: they won't be happy on an agile project, and the agile project won't be happy with them.
I don't know why these articles keep getting written. No one's forcing you to write your tests first, and if you can't wrap your head around the benefits (which the author clearly can't) then don't do it. It's fine. I'll still continue to utilize TDD, and continue to pump out significantly more code (with significantly less bugs) than the code I produced without TDD. Yes, there's definitely code I write where I don't write the tests first. It happens, sometimes it's just easier to bang something out because you aren't sure what you're building. That doesn't mean TDD is a failure, it's a tool, like anything else. Use it where it's appropriate, because the benefits are massive.