sandal edited this page Dec 6, 2011 · 6 revisions

As a software project becomes more mature, it tends to have fewer obvious defects. A great way to make sure this happens is to maintain a comprehensive suite of regression tests. Because I wrote an entire Practicing Ruby article on this topic, I won't discuss it in great deal here, but I will provide a brief summary of its core ideas here to refresh your memory.

The comment system on Practicing Ruby uses Github style @mentions to send notifications to users whenever they are mentioned in a conversation. Because it was Jordan's first time implementing this feature, he originally missed a couple important edge cases: case-folding and punctuation stripping. Without these small transformations, our @mentions support would be too cumbersome to use, so we went ahead and added them. However, before we did so, we added a couple tests to reproduce the problem:

test "match mentioned users without case sensitivity" do
  frank = Factory(:user, :github_nickname => "frank-pepelio")

  comment = Factory(:comment,
    :body => "I mention @FRANK-pepelio")

  mentioned_users = comment.mentioned_users

  assert_equal [frank], mentioned_users

test "allows user mentions to include punctuation" do
  frank = Factory(:user, :github_nickname => "frank-pepelio")
  person = Factory(:user, :github_nickname => "person")

  comment = Factory(:comment, :body => "@person, @frank-pepelio: YAY!")
  mentioned_users = comment.mentioned_users

  assert_equal 2, mentioned_users.count
  assert mentioned_users.include?(person)
  assert mentioned_users.include?(frank)

The benefit of adding these tests is that they explicitly outlined the desired behavior in a way that would be verified every time we ran our test suite. This means that if we ever end up refactoring our @mentions code and forget about these edge cases, our tests will complain loudly, helping us catch the problem before it ends up affecting anyone.

While those practicing true TDD may write this sort of test without even thinking about it, even those who are resistant to writing automated tests should be sure to do so for any defects or missed edge cases in their code. Coming up with a minimum reproducing example is 90% of the battle when it comes to fixing bugs like this, and once you've done that you are most of the way to having a proper test. Introducing new bugs into a system is inevitable, but it is possible to prevent them from having a recurring impact on users by using this technique.

It is also worth mentioning that in addition to tests specifically designed to ensure that particular bug fixes remain applied, system-wide integration tests will often help to uncover new problems even if they do not specifically test for them. This technique is a bit complicated to summarize, but there is an example of it shown in the Practicing Ruby article about this topic, so be sure to read it if you haven't already.

Turn the page if you're taking the linear tour, or feel free to jump around via the sidebar.

You can’t perform that action at this time.
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.
Press h to open a hovercard with more details.