I have my own little project I am creating using RoR, I plan it to have small-medium load.
With no doubt I started with BDD and TDD (Cucumber and RSpec to be exact, but I am also experienced with TestUnit), I like it but since it’s my own project and it’s a somewhat startup – I am changing many things in it, many requirements, many ideas how things should work and look. So it becomes too much time-consuming to always code it using BDD and TDD, even if I cover only common cases.
What should I do? Should I sacrifice BDD and TDD for productivity till I get to some point when I have a solid basis and it’s time for production, and than I write tests?
Should I write them right now but as minimal as possible? Should I only write RSpec and forget about Cucumber for now? Or maybe just TestUnit to test model for now since it’s the most important and everything else can change?
Thanks in advance!
Update:
I know all the pros of TDD and BDD, by no means it makes it easier to scale and bugfix application in future and save time, but maybe it’s more reasonable in my situation to wait few weeks till I have at least some skeleton architecture of my app and than once I am sure with it I can cover it with tests to have a solid base? And than continue with TDD and do all the tests with TDD.
1
There is a difference between prototypes and code written with the goal to be run in production.
-
Prototypes are done to quickly test a concept. Code quality, security, maintainability don’t matter. What matters is to finish the piece of software quickly in order to have the results (i.e. if the ideas behind are viable) as soon as possible.
-
Production code is expected to be more tested and more reliable, easy to maintain, secure, etc. If you sacrifice code quality, architecture or testing in order to accomplish the task quicker, it will hurt you sooner or later. In essence, not spending one hour testing your code now will cost you (or your colleagues) days later, because of a strange bug you could have caught easily if you were testing your code.
If your intent is to use the code later, write it as it was expected to live forever. Skip testing only if you know, for sure, that the code will be thrown away very soon (soon: in a few weeks).
3
It is a trade off, however, in most cases the answer is, yes, you should use TDD (or BDD).
Studies show that TDD may cause a an increase in initial time to develop but reduction in number of defects outweighs this.
Detecting defects later on adds substantially to the cost of development. TDD gives you faster feedback and allows you to identify defects as close to writing the code as possible.
TDD also gives a number of other benefits (when applied correctly).
- It encourages more loosely coupled code, as tightly coupled code is harder to test.
- It highlights violations of SRP, as extra responsibilities add an extra dimension to the test meaning a combinatorial explosion in number of tests.
- It facilitates pair programming, see Ping Pong Programming.
It’s fine – with provisos. I think your question can be rephrased simply as – “is it OK to take on technical debt?”
i.e.
Is it OK to produce things in a quick and dirty way when other factors demand it?
To which the slightly woolly answer is “yes, sometimes – as long as you pay off your debts”.
There’s further nuances to your question. Such as whether TDD will actually slow you down that much. I would argue that, assuming you already know how to do TDD and how to use those tools, then it won’t slow you down at all. It will force you to make design decisions that you would have encountered anyway, and probably help you solve them more quickly. If, on the other hand, it’s going to take you some time to learn the methodology and the tooling, then it might not be plausible to factor in all that learning time too.
The second is whether those other factors really demand you to take on technical debt. Startups and new products are a pretty natural habitat for technical debt. If not getting something out by a given time means going out of business, then you better take on some technical debt. If taking on some technical debt means the prototype of your self-driving car might crash, it’s better to delay the release. I don’t think technical debt should de facto be the first thing to cater for a tight deadline – pushing back to stakeholders for a delayed release (or same date different scope) should be your first option, whenever possible.
Lastly, are you sure you’re going to pay off your debt in a timely fashion? Are you really, really sure? It is all too easy to give in to external factors (they never seem to go away) and eventually you get to a point where all you’re doing is paying off the interest on your debt.
If you need to compromise your tests, you could try to identify the bits where incorrect results are less important. But you should strive to have as much code as you can tested, before it gets committed to your version-control mainline.
You can, of course, sacrifice testing and tackle the problems this may cause further down the line. You could do some prototyping of new code outside version control, as long as that NEVER hits production, to figure out what the right direction is.