I’m currently working on an existing PHP project. The current code design is not that good, and bugs are starting to pile up. So what I want is to add a comprehensive test suite to make it more reliable.
There are already a few unit tests which are written in PHP Unit, however, the test coverage is not that good. The project does not really follow TDD or any sort of test-intensive process. As much as possible I want to have everything tested. But the problem is that I am unsure if I could just add tests for the existing code. As I mentioned, the code structure is not that good, so adding in tests might become very troublesome and difficult.
Is there a better method to add unit tests in projects such as this? Or should I just rewrite the project? Maybe module by module?
Most of the problems that occur when trying to add unit tests to an existing application appear because, usually, that app hasn’t divided its functionality good enough into classes and methods that can be tested effectively.
That’s actually one of the main advantages of not just TDD, but the good practice of writing tests as you develop the application. The tests compel you into writing concise methods with a clear purpose and as few side-effects as possible.
A full re-write would be the ultimate solution, but I doubt you have the time and energy to do that; and besides, such an action might not me completely necessary!
Honestly, in my experience, the best approach is to just start writing tests for each module at once, refactoring where needed. Start with the core elements such as, for instance, user registration and management bits, and then go further.
It might seem like a daunting task, it might make you feel like your work it in vain, but in the long run, those tests will drastically remove the time spent debugging the application!
- A great article I recommend on AltDevBlogADay (mirrored by bitsquid as the old url 404’ed). It’s not solely about writing tests, but it explains a lot of concepts related to coping with bad (or in your case, maybe just hard to test) code.
- More about PHP unit testing
We simply began testing what we could test. Classes that process data and return results can have tests written now, that work, and validate that small portions of the class can be tested. It was daunting to start, but we now have about 45% code coverage, with 3000+ tests. These tests currently catch errors when people refactor the code.
We tried to isolate modules and classes that made the testing easier, and some of the tests are simply testing constructors, public interfaces, etc… that if they change, then there is a problem as something is likely to break.
When new bugs are discovered, we try to write a test to illustrate the bug first, then we make the code changes to resolve the test. This keeps our testing moving forward.
Each day, we added a few tests until the results started to be encouraging, with a larger test base and more complete code coverage. At some point along the way, our tests actually caught problems being created as people added or changed code that broke some legacy interfaces. This was the first good win on the automated testing, as it was discovered without manual testing of old input files, that would likely have not been tested against.
Be very careful about trying to add Tests to an already existing code base. As Andrei pointed out the task is very large and TDD works best when tests are integrated from the start.
Try to add tests to your core functionality and fix the bugs the old fashioned way by developer testing the rest.