@should do test-driven development

May 11, 2014

I recently described the @should taglet created by OpenMRS that helped the community adopt and sustain better testing practices.  Mário asked a good question about test-driven development (TDD):

I believe that BDD and TDD are very connected (except, when talking about integration tests). But I don’t see how [we can] use TDD if we need to create the @should tags first. Could you please clarify a little bit how that would work?Mário Areias

While I don’t think we’re doing much TDD in the OpenMRS Community at this point, it would be great to evolve this direction.  The real question is: will the @should tags that helped us start testing our code become an impediment to TDD?  I don’t think so.

Let’s try a simple example to see how we could be TDD-ish with @should tags.  Imagine that we want to be able to get the age in years of a person:

class Person {
  Integer getAge(Date onDate) {
    return 0; // TODO: return age
  }
}

Before we write any code, we describe the expected behavior.  To keep the example brief, I’ll just describe a couple expected behaviors:

class Person {
  /**
   * Returns person's age in years.
   * @should return null for date before birthdate
   * @should not round up age
   */
  Integer getAge(Date onDate) {
    return 0; // TODO: return age
  }
}

Next, we invoke the Behavior Test Generator plugin to automatically do the busy work of generating the skeleton for our unit tests.

class PersonTest {
  void getAge_shouldReturnNullForDateBeforeBirthdate() {
    // TODO: write unit test
  }
  void getAge_shouldNotRoundUpAge() {
    // TODO: write unit test
  }
}

So, now we can write our unit tests and see them fail, like any newborn tests in TDD would do.  Granted, in this example, you don’t technically start with the test code, but you can start with describing behavior (using @should tags) prior to writing code and using those tests to drive development.  So, yes, we start with @should tags; however, @should tags, can precede any actual code, since they are effectively shorthand for the tests we are writing before coding.

2 Comments
Ben W
May 12, 2014 @ 6:59 am

That works for modifying existing code. But Mario was probably referring to creating new classes/methods. In that case you have nowhere to put the @should tag. True TDD says you write one test method first with one line of failing test code, then make that code pass. Then repeat. In that case you need to write the @should annotations later… Or have them reverse engineered by a plugin from the test names that you end up using.

Reply
    burke
    May 29, 2014 @ 2:59 pm

    Yeah. It’s not full TDD; however, I consider the @should tag as part of the testing process, so writing @should tags before code still fits (or could fit) the TDD approach, IMHO.

    I suppose we could try to go the other direction – i.e., build @should tags from unit tests, but it would require that the test method name creation be facilitated. For example, “say what should happen, then we’ll automatically create a unit test method for you with the right name.”

    Reply

Leave a Reply

Your email address will not be published. Required fields are marked *


*