Even though there are plenty introductions to TDD (even in PHP, my primary programming language now), I’m feeling a bit stuck about it.
My friend introduced me TDD a while ago, but I wasn’t actually able to understand it – what’s the point in writing tests to everything first – even the simplest tasks – when in the end, it looks it’s more efficient to test only if something doesn’t work, although it might be much harder to locate the bug (this could be solved through VCS, no?).
So is there any introduction, with dead-simple examples and arguments behind “pros”?
Something like “yeah, it’s better, because you have better design – look at this example…”
Also, it would be nice if this simple examples were in php (should be possible) or in as3 (idk…).
EDIT: I understand that you create “test” and then the function, that should pass the test. But how you say to language, what results should it have? To me it looks that you do some function… debug it (the same way as you debug in no test driven dev.) and call it test and do it again… Or?
EDIT 2: Oh… Also, is this applicable to MVC approach? Or rather, CodeIgniter Newbie MVC? 😀
EDIT 3: Read a bunch of posted and googled advices, plans, ways and tutorials. I am still not entirely into TDD – I mostly have pretty good visualisation and I think (hope?) I write pretty maintable code, so i still see it as an extra work…
One of the reasons why this is an effective means to develop is not just writing tests for new code, but those tests remain and are run against existing code, and thus form a regression test.
That means that as your project develops, people take it over or contribute, and it changes, the tests continue to determine whether your code is still running as expected.
The code that you’ve written that is sufficiently simple not to have to test may well expand and become more complex over time (to take care of edge cases, new requirements etc.). If you’re still running your tests (and you should be -via continuous integration or other means) they’ll confirm that however much refactoring you do, the code still works as it did on day 1.
I found the tutorial on Simpletest (PHP) to be really useful. It was ‘the TDD launchpad’ for me.
- Set aside a couple of hours
- Get a crude simpletest script working
- Open your mind – forget your current dev habits and ways of working for a brief time
- …and just go with the flow – following the instructions and ALL the tutorials, all the way to the end, on the simpletest.org site
Then – in the near future
- Start adopting the practices – but gradually. Don’t try and do it all at once.
- Set up a test folder to sit with one of your projects and start adding a few test cases
If you start doing the steps above now. By this time tomorrow you will definitely fully understand why TDD is so handy.
UPDATE: A note about “1. Set aside a couple of hours” – this is probably the hardest thing to do. Because:
If you are putting out feelers to consider the benefits of TDD testing – its probably a symptom that:
- Your dev work is taking a long time.
- Which means you have no spare time to set aside to learn about TDD.
- Which means your dev work is taking a long time.
- Which means you have no spare time to set aside to learn about TDD.
Like most methodologies, you have to live it to understand what it’s about, its limitations and its advantages. I recently had to write a client server application and after reading Kent Beck’s seminal book (TDD by example) on the subject decided to try to use the methodology. I have a question regarding this which was commented on quite well by a lot of people over here but here is my summary.
- It takes much longer. Atleast for me.
- It requires a lot of restructuring. This might be an advantage but there are pieces of code which I feel are convoluted just because I need to test pieces separately.
- You can get carried away with writing too many tests.
- You focus on the trees instead of the forest and have to actively guard yourself from losing focus.
- No fear of rewriting pieces. This is probably the best part since I have a programatically verifiable specification of my requirements and it’s easy to check after a coding session.
- Modularity. My functions are small, classes are well contained and modules are manageable. You do require some skill to avoid ravioli code though.
- Documentation. The tests and their names give me a good chance to structure the docs properly.
- Rethinking structure. Having to test each layer properly forces me to make solid decisions about what the pieces are and how they communicate. This led to much neater design and a much more understandable terminology.
I’d recommend the book. It’s a good read and what will give you the real deal on the methodology. It’s not panacea (contrary to what the agile fanatics might say). You can’t automatically not worry about the hard decisions just because you’re doing TDD. It might seem a little unnatural since you have to think of tests upfront but that’s just teething trouble. I’d stay away from “Dead simple” intros you find on the web because they probably miss out on important details.
Update based on comment:
Apropos, coming up with smart designs up front and changing them as you go along, that’s how I worked till I tried this. The main differences were that the structure I came up with was smarter than usual since I had continuous refinable feedback (eg. you can’t test this, it’s too monolithic-break it down, these two things are conceptually separate – see how the tests are mashed up etc.) and that the ‘dev’ steps I took were small enough to throw away without the guilt of ‘wasting time’ creeping on me. Basically, the ‘dev’ stage was more systematic and I had verifiable ways to saying what I’d done (tests either pass or fail).
I personally find the article on wikipedia to be a pretty good introduction.
The point of writing the unit test first is that by doing this you are writing the specification of your software which seems very natural to do before writing the software itself. How will a given function respond to a given input? If you later decide to change the implementation you won’t have to manually retest the whole application.
One way of phasing in tests is to only write a test when you start debugging a function. It means that tests are made first for the functions that need them most. That’s usually enough to noticeably improve development times.
That’s not test-driven development, but it will get you comfortable with writing tests and running automated test suites.
Automated test suites are great! They’re separate scripts/programs that you run which go through all the tests you’ve written (the test suite) and tell you which ones fail. It’s much faster to run the test suite than to manually do the tests yourself. Sometimes it’s even faster to run the test suite than to run your program. You can also set up your version control system so that whenever you commit, it first runs a battery of tests on the code and tells you if any fail.
I started doing tests with Django, which comes with a test runner script. Tests for models are useful because you don’t have to set up all the views and templates etc. just to check if your model is set up correctly. Tests for form processing functions are also great because you don’t have to keep manually entering the data into the form.
My form development workflow without tests:
- Make the HTML/template for the form interface and the class to handle the form
- Write the functions that validate the form data
- Open the page in my browser, fill out the form with invalid data, submit it.
- Examine the results printed on the screen to see if they’re what I expect
- Find some mistakes and modify the functions. Go back to step 3.
- Do this again a couple of times to make sure all the combinations are validated properly (e.g. must enter ID number if “Student” is checked)
- Discover something that doesn’t work, or need to change form because of client.
- Modify functions as necessary
- Go back and fill in the forms some more. Wish that Firefox autocomplete worked on more than one field at a time.
- Make the class to handle the form. (Django has a Form base class for this purpose.) Set up all the fields.
- Write the validation functions
- Write several tests, each for a combination of valid or invalid input. e.g., One that submits a form with “Student” checked but no ID#, one with “Student” checked and ID# supplied but no “First Name”, etc.
- Run the tests. Get a list of all my mistakes.
- Fix the mistakes.
- Repeat 4-5 until the test results say “Ok”.
- Make the HTML representation for the form
I’d recommend Kent Beck’s book, Test Driven Development by Example. The code samples are in Java, which is syntactically similar to PHP. That aside, the book really is a good intro to TDD.
TDD is the answer of almost everything in Software Development. This is one of the main aspects of extreme programming.
Software development is a notorious unpredictable tasks. In a small to big project, where is the grantee that the code you are writing today does not break anything of what you had written last month. Answer TDD.
Then the obvious question next would be how the TDD does that?
The answer is simple. Whatever/What function you write, you will develop a TDD for this. Over the period of time you will have a collection of TDDs. If you write something new, you write your TDD for that and tie it with the TDD- collection. The TDD-collection includes all the TDDs that you/your team had written from the very first day of your project.
If you don’t do the TDD, there is a good chance that the project can be out of the hand no matter how careful you or your team would be. It trend can be incremental from small to large projects.
No two developers are the same for sure!!We have our own way to implement the same thing in different ways. All of these will go to the code base. We must have something to harmonize ourselves. TDD is a very standard way to achieve that.