Test Driven Development Examples?
esnyder queries: "I find the pragmatic/agile/XP hype about test driven development compelling, but find it hard to see how to test first (or even unit test at all) in some situations. I would like to explore some extended examples of it in a moderate to large scale real world codebase to improve my test design skills. Can anyone recommend some F/OSS software projects that consistently use test driven development processes that I could check out? Preferable over 50K lines of code, but I'd welcome pointers to anything that people think would be helpful."
Where I work we're coding a dating site. Currently, it's up to about 180K lines of scripts written in PHP. However, not a lot of it was written with unit testing (and test-driven development) in mind. I'm a big believer in unit testing but it's been hard to get the other members on board as they complain how hard it is to write unit tests for web pages. Bah.
So, most of the library functions that I wrote (stuff like except an integer, return a text string from a list) have been unit tested by myself, and every time I change a function or a class, I try and write a unit test for it.
Seriously, you just need to dive right in and think about how you make your code easy to test. I use the SimpleTest testing framework (it's PHP), and I always feel good when my array of tests all run correctly when I make a major change to the code that impacts a huge portion of the site.
If test-driven development has done one thing, it's forced me to carefully examine my code to create a way to make sure it is actually working according to the business logic we've been asked to implement.
The Python programming language and all of its standard library modules make extensive use of unit tests and TDD.
It would have been helpful if you'd mentioned the language you're using, and the types of applications (since of course both of those make a huge difference).
If you're using Java for web development, I'd suggest reviewing the Struts Applications Project on SourceForge.
It's a collection of documentation and applications using Struts that are really "done right" -- with documentation, sensible and scalable design, fully implemented testing (unit level AND on the HTTP level). I'm currently roaming through the AppFuse source in there -- it's basically designed to give you a complete setup to start building your app on, with common functions already built-in.
From the site:
AppFuse
An application for starting your Struts-based applications. Checkout from CVS and execute "ant -Dapp.name=yourApp -Ddb.name=database" to instantly be up and running with a Tomcat/MySQL app. Uses Ant, XDoclet, Hibernate, JUnit, Cactus, StrutsTestCase, Canoo's WebTest, Struts Menu, Display Tag Library, JSTL and Struts (including Validator and Tiles). Features include CMA, Remember Me, Self Registration, Password Hint. The fuse to start your apps.
There are only 10 types of people: those who understand decimal, those who don't, and, uh, 8 other types I forget.
I wrote a series of tests for code I have written for what I would term a trivial application. Took me about 3 months to develop. The series of tests for about 50% of the code and missed 50%. The vast majority of the bugs came from the second half of the code.
Second. The tests themselves act as documentation. I am anoyed that I pick up generic routines like a CSV file reader and there is subroutines but no way to figure out how to use them. A test suite acts as sample code as well.
This process is balance, you don't test every detail but you do codify some tests. When you find a bug you codify a test and then you NEVER reintroduce the same bug. I find that in general I reintroduce bugs about once for every month of coding. Since this application only gets worked on in random blocks of a week here and there I am not focussed on the whole application and I simple forget. Use the computer to validate that you have not made a mistake.
These sort of tests saves my reputation, does not frustrate my users.
Sorry to let you know but, you didn't write good unit tests and probably did waste your time. I've found very close to 100% of the bugs in Vstr a network IO string library using unit tests. That includes a couple of ones that would have been damn hard to track down otherwise.
However it's been over a year since 1.0.0 which had a unit test for every function and every function option, to the last release which had over 99% code coverage found a couple of weird corner case issues (not just bugs, but optimizations that could never be reached for some reason). And going from 98% coverage to 99% coverage took a significant time investment, and required significant thinking about how the test should be written.
As with much software development, it's easy to write simple tests that don't show much and aren't very useful. It's much harder to write tests that find bugs (and you have to appraoch writing the tests with a very different mindset to how you approach writting the code you are testing. This is not even close to being "Like picking lint from your belly-button."
ustr: Managed string API with ave. 44% overhead over strdup(), for 0-20B
I'm sure a lot of people have grounds to object, but I suggest, depending on the nature of the project, it's a good idea to be intelligently selective about what does and does not need to be unit tested. Consider:
::sigh::
Do write a test case if:
+ a failure could introduce data propagation issues
+ it performs some intricate mathematical or logical function whose result must be precise
+ you're writing test cases to hunt down bugs that you know are in you're code; keep those test cases
+ you're uncomfortable about the quality of your code
+ an error might kill someone, or otherwise be Really Bad
Don't bother writing a test case if:
- you can use a guard clause or assertion instead
- a failure in the code will otherwise be immediately obvious
- the code generates massive amounts of data which need not be mathematically precise (i.e. graphical output)
- you don't feel it
I should probably write more test cases, according to my own guidelines.
Upstairs Dog, Downstairs People.
My experience has been that "unit testing" slows development to a painfully slow crawl.
This is a common miconception about test-driven development. Sure, when you look at the speed at which new features go in, "development" seems to be slowing to a crawl.
But this is a very short-sighted and limited view of the whole project lifecycle. I've found that having great unit tests for my code actually help in the long run for adding new features. And that's not just adding the features to the code base, that's all the way to the end -- making sure they work properly.
Nevermind the benefit they give while refactoring in an agile development process: the unit tests become a sort contract you can guarantee will work for objects that use your code, no matter the internals of a function. For refactoring this is invaluable.
In short, you're not alone. Very few developers think long term like this and it's a shame. But once you drink the unit testing/test driven design (TDD) kool-aid I guarantee you'll never go back. I wouldn't think of writing code without unit tests any more and quite often it's TDD.
----- rL
Where I work, unit tests are a requirement, not a luxury. WIthout fail, the projects with the most unit tests have the fewest bugs, and the projects with the fewest unit tests have the most bugs. I'm not exagerating.
My question to you is, if you have no unit tests, how can you be sure that the code works at all? Manual testing? Do you cover all the code paths with manual testing? It must take forever, or your application is rather trivial.