We now have a testing framework in Drupal core. What we need to move forward is some structure that makes writing tests easy and efficient so that we can go towards our 100% code coverage goal without wasting development resources.
After today's IRC conversation on the topic of unit testing, the decision was taken to implement unit tests the same way as functional tests are currently implemented, without mock objects or functional overrides at runtime (see this issue for an explanation: http://groups.drupal.org/node/10957). However, the discussion also touched on many key points that are relevant no matter what approach we take, so here's a summary for those who weren't there.
One of the main outcomes was the need for a better organization of the various kinds of tests that we have. With a clear structure in place, we could put test files in place with minimal code, thus making it easier for contributors to create patches without having to figure out where to add files or how to trick cvs into creating a patch for new files. These basic files would also make it easier to point people to simple tasks that can be processed in a short amount of time without the need for an extensive understanding of the code.
In order for tests to be easy to write, they must be easy to read and easy to understand. The existing tests are the best documentation that we have for contributors who are new to automated testing. We currently have many tests that try to cover a whole module's functionalities with a long list of assertions. The problem with such tests is that they make it hard to track down what is happening when a test fails (even if we know what assertion failed, we might need to debug the code that sets the fixture – the environment in which the test is run). It is also a lot easier to create a small test than it is to make a small addition to an existing mastodon. In other words, tests need to be refactored, just like code.
Besides reorganizing the structure of the tests, it is also important to make a distinction between the different kinds of tests. It's not because we are using the same mechanism to process “unit” tests as we do for functional tests that they are the same thing. We currently have tests that simulate specific sequences of user actions (like user.test), tests that simulate the execution of code with specific parameters (like search.test), and some that are somewhere in between (path.test). In order to better structure our tests, we need to be able to indicate what kind of simulation they perform. Should unit tests be in separate files, separate classes, or even simply separate methods? Wherever we put that separation, we also need to make sure that the naming conventions reflect it.
Finally, making Drupal testable requires refactoring code, and refactoring code breaks existing tests, but this is what is supposed to happen. The whole reason to use automated tests is to be agile and make this kind of overhaul possible by making us aware of how we break things. Converting Drupal to a fully tested framework is a big task, but the work we do now will make future work easier and our testing system (both the testing framework and the tests themselves) will get more stable, to the point where we can make big improvements without breaking everything.
Note: Credits for many of these points go to the people involved in the IRC discussion (mainly webchick and chx), but I've mixed in my own opinion so criticisms go to me.
Comments
Mock Functions in PHP
I've posted a first draft of a Mock functions library for php. It's up on the workhabit blog, for those who are interested.
http://www.workhabit.org/mock-function-testing-drupal
This is the first step of making it possible to test drupal modules and components in isolation. I'd love to hear everyone weigh in on whether this is a good approach for core, or for modules themselves (either contrib or core).
simpletest mock functions
I've wanted this as well. I did find that start of an existing project here.
http://www.phppatterns.com/docs/develop/simpletest_mock_functions
I've emailed the original author as to it's status
On a purely selfish level,
On a purely selfish level, here's what I'd like to see happen over the next few weeks:
automated testing of whether patches apply or not, Rok suggested he could have this working almost immediately. I think there's at most 50 patches in the RTBC and CNR queues that actually apply at the moment (out of over 250 or so). This will
a) get people used to the testing bot telling them their patch is no good
b) clean up the issue queues without me having to do it maually
c) focus human review efforts on patches that actually apply (let alone don't break tests)
Get internal browser test coverage of core up to 95% as a number one priority to save clicky breaky patch reviewing
Work on providing SimpleTests for the 50 or so patches left in the queue - both via educating people supplying the patches and/or providing them directly (I haven't written any tests yet so this includes me - and I tend to learn by example personally).
Work on a catch-up plan for API level tests based on parts of core that don't look likely to change drastically within the next 2 months.
For API level testing we're starting from almost zero, so we need to have 3 and 4 working in tandem. The less duplication and test rewriting we get at an early stage, the more coverage we get up front. Once it gets over 50% coverage it's less of an issue if tests are being rewritten all the time - but for example I don't see much point in writing a bunch of tests for the old database layer if that's going to disappear in 3 weeks - and if we're trying to make writing tests an entry point into core development a lot of people won't know which bits of core are in line for a rewrite.
To back up webchick, I probably tested over 500 patches against D6. I did most of this on an XP machine at my work via putty to a Debian VPS during spare minutes. I think I could probably get runkit running in a few minutes on that VPS or on my ubuntu machine at home, but I certainly wouldn't have done this when I began reviewing patches if it'd been a prerequisite - because my entry into core development was trying to get a bug fixed that was pissing me off on my Drupal site.
On mocking, I know people are happy to leave it to later, and I think this makes sense until we've exhausted the possibilities offered by SimpleTest (both internal browser and API level). If/when we need mocking down the line, it'll be a for those functions which can't be usefully tested functionally (chx mentioned node_load on irc) - if it's a few special cases like that, then I don't see a problem with special cases in terms of how the tests have to be run, or a unique test syntax - because it'll be a minority of core that requires this to give useful feedback compared to the work put in, if everything else is covered in other ways.
filed some issues
OK so on IRC last night it was suggested to flood the issue queue with issues for outstanding tests. I've made a start on this.
Modules with no .test at all:
* Open ID
* Color
Tests with obvious outstanding issues/omissions in them:
* Help
* Forum
* Blog
* System
* Misc phpdoc cleanup (patched as I went)
I've also filed a feature
I've also filed a feature request over at http://drupal.org/node/256185 for automated patch testing by the TestBedBot (just whether patches apply, not SimpleTests yet) - this'll help weed out stale patches, and hopefully get people used to things being set to CNW automatically.