DEV Community

Discussion on: The TDD Test

Collapse
 
eljayadobe profile image
Eljay-Adobe • Edited

It can. It's a technique, and a foundation upon which many other agile engineering practices are built upon.

Where I've found that it works is under these conditions:

  • developers are actually doing it
  • tools being used actually support it
  • diligently avoid polluting unit tests with integration tests

In my experience, the developer team was initially forced to do TDD by management. The platform we used was Visual Studio, C#, NUnit, and NCrunch. There was an entirely separate integration test system. The unit tests ran in a few seconds, and thanks to the magic of NCrunch had practically immediate feedback as you were typing in Visual Studio. After the development team acclimated, all the developers on the team were really enamored with TDD, unit tests, and the tools we were using. My anecdotal assessment is that unit testing avoided 98% of the bugs that we had experienced on the first generation system (which was not TDD and had no unit tests) -- that was the value of having a unit test suite (~70% coverage) to ensure basic correctness.

Where TDD is difficult to do is if the development team is recalcitrant, the tools being used are inimical to TDD, or the unit tests system becomes polluted with non-unit tests.

For example, in my current project the development team has almost no interest in unit tests (let alone TDD), C++ is not a TDD nor unit test friendly language, and for the small number of ostensible "unit tests" we do have over half of them are actually integration tests and take far too long to run as unit tests.

On systems where I think TDD is even more critical is larger systems that use a duck typed language. When I worked on a large TypeScript based project, I lamented that we did not have a unit test suite. (Whether we would have created that unit test suite using the TDD technique is orthogonal.)

Collapse
 
vdedodev profile image
Vincent Dedo

I was working in a python environment and we had lots of unit tests but worked in a more TLD style (test last development). Most of our tasks were open enough that TDD would mean doing all the design up front rather than refactoring as we went along.

My question was more about how writing the test first is meant to work in practice? Do you know what your units are meant to be? Do requirements have to be complete and explicit?

Thread Thread
 
eljayadobe profile image
Eljay-Adobe • Edited

My question was more about how writing the test first is meant to work in practice?

It's meant to work in practice by putting pressure on the developers to use most of the principles of SOLID (especially LSP, ISP, and DIP), Law of Demeter (related to DIP), Design by Contract (related to LSP), YAGNI, KISS, GRASP, SOC (related to SRP), DRY code and WET tests.

The "how to" steps are the steps I cited above in the posting. It's a very fast cycle.

Do you know what your units are meant to be?

The unit test is written moments before the code that implements the functionality.

If the developer does not know what is being implemented, then how would the developer know what to implement (regardless of TDD or unit tests)?

Do requirements have to be complete and explicit?

For the unit tests, no. Unit tests are for testing units. With TDD, unit tests are a means to guide design. (q.v. Growing Object-Oriented Software, Guided by Tests by Steve Freeman and Nat Pryce.)

Requirements are at the level of acceptance tests, and perhaps integration tests and system tests.

Unit tests are written by developers, to aid development. Acceptance tests (and integration tests, and system tests) are written by quality engineers to ensure what the developers created meets the requirements.

Think of it this way: you have a bolt and a nut. You can create all sorts of tests to make sure the bolt works correctly, and all sorts of tests to make sure the nut works correctly. Those are unit tests. As soon as you write tests for the bolt-and-nut, that is no longer a unit, now it is an assembly, and these are not unit tests -- they are assembly tests (which is a kind of integration test).

I was working in a python environment and we had lots of unit tests but worked in a more TLD style (test last development).

Since you are using TLD and Python, you could probably dispense with unit testing altogether, and use something like Python Contracts module, by Rob King / deadpixi. This one supports require, ensure, invariant, types, and transform. Also supports async function (aka coroutines).