views:

976

answers:

14
+20  Q: 

Should I Use TDD?

I'm the only developer in my (very small) company and I'm about to start on a medium sized ASP.NET web application for said company.

I'm trying to figure out if I should learn Test Driven Development (TDD) and implement it in this application.

I need to start developing our new application shortly and I'm worried about testing. I've programmed for many years but have never done any unit testing.

I've read numerous online resources regarding TDD but I'm unsure whether I'll have a 'good enough' grasp on it to make it effective in the application.

Any suggestions and or 'good' resources would be helpful.

+18  A: 

Remember this: the only bad test is the one you don't execute.

Now, do you need to dive directly into TDD? Maybe not. But you should definitely start unit testing whatever you can. You can't unit test GUIs very well, and that's fine -- save those for UAT.

But any sort of logic you might execute behind the scenes? Yep, you should test it.

Start by just trying to test individual methods. As you go you'll start running into pain, because most likely your code isn't designed to be tested. This is fine; refactor your code! Keep doing so until you can test your code. Remember what you had to do and do that the first time the next time you write code.

After a few iterations, you'll learn what you need to learn (really, you can only learn it by doing) and the pain will go away. When that happens, I'd suggest you're probably ready to look into TDD.

Randolpho
+1: Just do it. "won't learn it well enough' is a way of preventing progress by demanding "well enough" before even starting. Just start!
S.Lott
@S.Lott: Exactly!
Randolpho
Remember this: the only bad test is the one you don't execute.Reminds me of http://www.youtube.com/watch?v=l1wKO3rID9g :)
Surya
Good points. I guess I just need to do it and see how it goes. That's really the only way to learn something. Thanks
CalebHC
I can't agree with: "the only bad test is the one you don't execute". Perhaps a worse test is one that *appears* to test something but doesn't, giving a false sense of security. Another kind of bad test is one that tests the infrastructure rather than your code - for instance, testing that when I assign a value to an integer variable that the assignment occurred correctly.
JeffH
+2  A: 

I'm still a new developer and stepped into a company where the application development was already ongoing. TDD helps me ensure that new changes don't break what has been done already and as I work along it helps from having to do massive amoounts of bug hunting when I add or modify code.

I have loved everything I have learned from it and strongly recommend taking the time to learn TDD.

-my .02

Jon Ownbey
+6  A: 

The best way to learn is by doing. If you've read that much on it, it's time to dive in - and as a single developer, having unit tests can be a godsend, since there's not another pair of eyes to look over your code.

Harper Shelby
+9  A: 

Note that TDD is not about testing; it is a development process. The testing is not done to replace the testing function - it is what defines the dev process.

It sounds like you are talking about unit testing and other automated testing. Testing is good. Automated testing is good. Don't be afraid to make mistakes. If you think about your code and how to automate testing as much as possible then you are in a good position - however there is a cutoff of diminishing returns. 100% automated testing is probably not something that is cost-effective - especially for an organization that you describe.

If you are really talking about TDD (What the experts would call TDD), that can also be good. There are many development processes. It is good to remember that development processes are frameworks and guides - not a religion to be followed like a quest. No process is one-size fits all. Do what makes sense for you and improve as you go. Having just one person in a dev organization makes changing process fairly painless. Address your high-risk issues first and put some lightweight process in place for those before going after low-value issues.

Tim
+19  A: 

It depends on where your priorities lie. If you're interested in furthering yourself as a developer, TDD is definitely worth looking into if only for the experience. It'll help you rethink the way you code and probably make you a better developer because of it.

But that could easily be outweighed by how much TDD hampers your ability to get your product out in a timely manner. You mentioned that you're the only developer working at this company and that means that the pressure is on you to get your project done. TDD is certainly a great practice, but sometimes real life constraints and practicality must come first.

So in short, if you can spare the time then yes, use TDD. It's actually not that much overhead and you can always skip the testing in a pinch. But if you're really strapped for time and don't think you'll be able to incorporate it without putting your product and job at risk, nobody would fault you for skipping it. The purists will disagree, but it's not a black and white world and sometimes compromises must be made to get things done.

Kevin Pang
+1  A: 

Do you have components that are easily unit-testable? Can you construct your app to be a set of unit-testable components? That's really the mindset to think in when working in a TDD environment.

Its easy to say "its a GUI app! its impossible to unittest my stuff"! This can be a self-fulfilling prophecy. Certainly you can't easily unittest the layout of all your widgets, but how much of your program is tied to how your widgets are layed out? You may stop yourself from doing good TDD because some aspect is too tightly coupled to the layout of your GUI widgets, or its too tightly coupled to something else not easily unittestable. Stop and challenge yourself-- is this really the case? Can I compartmentalize and modularize my code such that it can be better isolated from these parts of the system? Is it appropriate to do so (do the unittesting gains merit the cost?). Don't accept carte blanche that its impossible just because your software is tied to non-unittestable components.

Doug T.
+2  A: 

Only one developer is actually a fairly small sized development effort. Even if you expect a lot of screens, it still takes a long time to for a single coder to get into something medium (unless they've gone nuts with cutting and pasting).

I'm not a big fan of TDD, but if you are relatively new programmer (less than 10 years) you're by yourself and you're worried about quality issues, I'm sure it will both slow you down, but also help you improve your work. For younger programmers it forces them to focus more intently on the real underlying behavior of the code and get it working one step at a time (one early common mistake is too pound in massive amounts of code, and then try to debug it all at once. Old coders can get away with it, young ones usually need to work on smaller pieces at a time). Fans often say it majorly changed the way they code (usually making the overall work easier). At very least you could start with it, and ditch it later if it isn't really helping.

Your biggest problem, for which TDD won't help, is getting a good architectural structure for the web app. One that you won't want to throw away in five months. Web apps can be very tricky, few people get it right in the first ten or twelve times.

Paul W Homer
+9  A: 

I can't emphasize enough the advantages of a TDD-based development method. When you adopt TDD, your unit-tests become first-class citizens alongside the code you write, instead of being code which is maintained for the sake of having unit-tests and not being kept up-to-date.

In TDD, you use your unit-tests as an executable specification of what your component should do. You would do this by considering what you want your component to do, and then writing tests to exercise this functionality. Since your code initially won't have any of this functionality, all of the new tests you write would fail or be red. Once you've got your tests, start implementing the component. Gradually, as you add the required functionality, the red tests will turn green. The nice thing is that after you've implemented enough functionality to make all your tests pass, you know that you've completed implementing the intended specification and know exactly where to stop. Too often I've seen situations where a developer will have completed implementing the required functionality but doesn't stop, instead enhancing the component and adding extra functionality and eye-candy, none of which is part of the required specification, wasting active development time.

Once you have your unit-tests, it's easy to set this up in a continual integration environment. This environment would check-out the latest code from your repository, build it, and then run your unit-tests. If any regression happens, if anyone checks in any code which breaks your unit-tests, you'll know about it pronto, instead of finding out after it's been deployed to your production environment. To ensure that new code doesn't introduce a regression, we've set up login-hooks on our repository to ensure that all code submitted has also had the accompanying tests run and that they pass. This is especially helpfully when you have multiple people working on a project, as they can see via whatever monitoring dashboard you might use whether the repository is good to sync to at that point in time or not. It's also easy to locale a particular version of the repository which does work, letting people work with known-good versions, while someone else is working on fixing whatever issue is currently breaking your build. This would also potentially mean that any 'green' build as indicated by the dashboard is a build that has a very good probability of not encountering issues when pushed to a production environment.

Many people think that adopting TDD would mean extra work and hassle, and that it would be more time-consuming. Consider though that the extra time spent writing tests will prevent any functionality that is being tested from breaking, and that you'd be finding those breaks sooner, rather than later.

Another advantage of using TDD is that you'll give your design far more attention, and that it would be far better structured and componentized over a non-TDD approach. This componentization is important to be able to have a unit-test suite which is quick to execute and non-brittle.

GUI-testing is difficult, but not impossible. Consider web-UI testing technologies such as Selenium, WebDriver and Watir, which can exercise web-UIs programmatically. It's easy to misuse these tools too, by performing only expensive end-to-end testing using them. A far better approach is to abstract your UI layer so that it can be tested in isolation, independently of your business logic. You don't want a UI test going and performing operations on a database.

To re-cap, you want to write efficient unit-tests to make using TDD a pleasant experience, rather than a burden. Your tests should be quick, test components in isolation, and should ideally be run all the time.

What I've described here is an ideal case. You don't have to adopt every single idea mentioned, but you can pick and choose whatever works to make your development process more efficient.

Roshan
Thanks for your reply
CalebHC
+2  A: 

I recently started to use TDD as well on all new code. Yes at first it looked like it was just a waste of time since all my logic was too tightly coupled with the Gui, so I couldn't write any unit tests that really could garantee that my code does what it should be doing.
But after a while I realized that writing unit tests was such a pain because the code was written badly. I started to refactor my code in such a way so I could write unit tests for it that mattered. I started to make my methods shorter, made more use of interfaces and tried to separate the logic as much as possible from the Gui.
I think the purpose of using unit tests beside testing and validating your code is to just make you an overall better programmer. So anyhow it's worth the effort learning it.

Mez
+1  A: 

Thanks everyone for the replies. A lot of you have good stuff to say and I'm trying to put all of that into consideration as I try to decide if I should use a TDD approach. I just thought I would say that the project I'm implementing will be using ASP.NET MVC, and NHibernate for the persistence. I guess this setup makes TDD a little easier because everything is already pretty separated.

CalebHC
+1  A: 

The overhead of TDD reduces as you gain experience in it, and soon becomes less than the overhead of not developing using TDD.

However the overhead to begin with can be significant, you will lose time doing things the wrong way through lack of experience. A critical project is a risky place to include the time it takes to learn a new development technique

David Sykes
+1  A: 

Caleb - I wanted to pitch a site that has been constructed to aid learning TDD by yourself at home. You learn better if you are not under pressure. Just google for "tdd-problems" and you will find it.

Thanks, I'll check it out!
CalebHC
+1  A: 

If done pragmatically it can be a huge benefit. The argument against it always seems to be that it takes too much time but as we all know if many cases knowingly sacrificing quality can be even more detrimental.

It's been 3 years since I learned TDD and I can honestly say that I've seen it bring huge value and I've also seen it be a complete waste of time.

Here is an example of each...

Beneficial: Working on a solution that was fairly complex, had many dependencies and variations and was constantly evolving. Designing with testing in mind and have a regression suite of unit tests allowed us to adapt to change quickly and be able to refactor code for increased maintainability. We used the 80/20 rule when creating unit tests and left out low value test cases.

Not Beneficial: It was (dogmatically) decided we must have an automated test for every test case QA could think of, even UI cases. Many cases were so rudimentary and involved very little, very simple code. Getting many of these to work required vast amounts of setup and increased the amount of tests to maintain so much it was slowing us down significantly.

George
+1  A: 

Thought I would summarise and comment on some of the above comments:

  1. Yes TDD is about Design. It is not about testing.
  2. Not sure why QA were getting involved with George’s design stage. It sounds like they were specifying automated tests. As Tim pointed out, it’s a Development Process.
  3. Kevin, you said ‘skip the testing’. One more time. TDD is about Design, it is NOT about testing. OK You can skip the design, but the finished app will be buggy and unsupportable.
  4. Roshan mentioned, ‘executable specification of what your component should do’. That means fully up to date documentation. When you are new to a project you can get up to speed very quickly, you can see exactly what the original Developer intended. And, as Jon mentioned you can make code changes and ensure that nothing is broken.
Steve