This post started as a comment to Michael Rooney's question: Failing tests: When are they okay?, and then it became a bit too long for a comment.

picture of a green traffic light
Green light by morberg, cc:by-nc

For me the most important aspect of a build is to accurately represent my knowledge about the health of the product. New problems must be noticed as soon as possible. This won't happen if the developers are used to seeing (and ignoring) broken builds.

For this reason you want to distinguish known failures from unknown failures. For example, it's okay to commit a test that reproduces a bug even if you don't have a fix for that bug, but do it in a way that keeps the buildbot green. (Two common ways of doing that is marking the test in a special way so the test runner knows it's expected to fail, or disabling the test so that it doesn't even run.) The worst thing ever is fragile tests that fail only sometimes, especially if everyone grows accustomed to them. I speak from experience. I still have nightmares...

Collaboration is not reason enough to break the trunk. You can use branches or send patches via email, whichever works best. Patches are often simpler when you're taking over someone's unfinished work when that someone gets stuck and asks for help, or if you decide to switch machines when pair-programming. Sometimes I use shell one-liners like 'ssh othermachine svn diff /path/to/source/tree | patch -p42' to get the changes into my checkout. Branches are more appropriate for longer-term collaboration. It's perfectly fine to have a broken test suite on a branch -- you can always discard it; that's what you do to prototypes. Reimplementing something you've already done, in a cleaner fashion, is often a simple and rather pleasant way of merging.

If the tools you have aren't polished enough and you don't feel comfortable creating new branches even when they're necessary, invest a day every now and then improving your tools (shameless plug: eazysvn, because eazysvn switch -c newbranch does not require you to lose your train of thought remembering how to type long subversion URLs for svn cp).

That's all theory; in practice IMHO it's acceptable to take shortcuts. Small self-contained checkins are best (and this topic deserves a blog post of its own), but if you're forced to wait 20 minutes for the full test suite before every one of them, you won't use small checkins. It's fine to run just a subset of tests covering the code you've changed before every checkin, even if that means you sometimes will break the build by accident. However it's your responsibility to clean up any breakage if it occurs before you leave at the end of the day (or at least to feel guilty when you don't).

Back to the original question: I can imagine only one set of circumstances where the right thing to do is to knowingly commit a broken test to trunk. Imagine that you discovered a show-stopper bug, but the fix is elusive. By committing a failing test you force the whole team to notice it, drop everything else and work on the problem. And you also prevent somebody from accidentally releasing a broken version of the product. (Your release process includes a step ensuring that all the tests pass, right?)