0

In our development, we use TDD, so we have some tests like this:

"User" should {
  "return 'Mike' if its name is 'Mike'" in {
      val user = User("Mike")
      user.getName === "Mike"
  }
  "return 20 if its age is 20" in {
    val user = User(age = Some(20))
    user.getAge === Some(20)
  }
}

The tests we are writing here looks like "Unit tests".

Then I found specs2 provides another kind of syntax which is more expressible, which I'm interested in:

def is = s2"""
   User can have name and age, and we have ways to get them, say, if we have a user whose name is "Mike" and the age is "20",
     - we can the name "Mike" [$e1]
     - also can get the age 20 [$e2]
"""
def e1 = {
  val user = User("Mike")
  user.getName === "Mike"
}
def e2 = {
  val user = User(age = Some(20))
  user.getAge === Some(20)
}

I want to try it with TDD, but soon I found this kind of tests are "Acceptance specification". There is a strong question came into my mind:

What kind of tests are they if we mention "TDD"? Must they be "Unit tests"? Is it good practice to use the "acceptance specification" to drive the implementation?

Freewind
  • 193,756
  • 157
  • 432
  • 708

3 Answers3

2

I want to clarify that in specs2 the terms "Acceptance" and "Unit" refer more about "styles" rather than activities.

I named the "Acceptance specifications" as such because they allow you to express yourself in a style that is common to "acceptance" document which should be easily readable by a non-developer (that is, not cluttered with too much code).

On the other hand the "Unit specifications" are being expressed in a style that is more familiar to people writing unit tests.

But I don't consider this denomination to be prescriptive at all. You are free to choose whatever style you prefer and I frequently use the "Acceptance" style for unit tests!

Eric
  • 15,494
  • 38
  • 61
1

I don't think TDD strictly requires a specific definition of "unit tests" vs. any other kind of tests. The specific kinds of tests are just an implementation detail. What TDD focuses on is the repeatability of those tests to provide quick feedback to the development effort. TDD doesn't necessarily care about what kind of tests they are, it just cares about using those tests to drive the development of the system.

To that end, any tests which can be executed quickly and repeatedly (as part of the red/green/refactor cycle) can drive the development in a TDD style.

If you can imagine some alternate world where somehow an entire manual QA department was enclosed in a temporal field which allowed them to run through hours and hours of manual tests in the span of a second to an external observer, those manual tests could be used as TDD tests to those external observers. (Though measuring code coverage would be difficult...)

Any exhaustive set of repeatable tests which can be executed quickly can be used for TDD.

David
  • 208,112
  • 36
  • 198
  • 279
1

TDD is not prescriptive about the kind of tests. You write the tests to specify/explore and use then as regression harness. So if you need to specify a unit of work, you will probably write a unit test. And if you need to specify an entire system, you will probably write test external to the system that you will not call a unit test.

Note that the term "unit" is really dependant of your point of view. One could consider as a unit test a test that describes a functional unit even if a lot of code is executed.

ericminio
  • 116
  • 5