This post is something of a follow-up to https://groups.google.com/forum/#!topic/clean-code-discussion/to5UHcVEQgo (A Friendly Amendment), in which I proposed an amendment to the UB Cannon:
Over the years I have come to describe Test Driven Development in terms of three simple rules. They are:
- You are not allowed to write any production code unless it is to make a failing unit test pass.
- You are not allowed to write any more of a unit test than is sufficient to fail; and compilation failures are failures.
- You are not allowed to write any more production code than is sufficient to pass the one failing unit test.
(emphasis supplied). This was reiterated in UB’s recent video, where he characterizes these rules as an essential “discipline” of software development.
My proposal was to replace the word “unit” with “automated”, deferring to Beck’s famous tome:
For the vast majority of us … following these two simple rules can lead us to work to our potential:
- Write a failing automated test before you write any code
- Remove duplication
(emphasis supplied). And it is significant to note that KB’s definition of a unit test is fairly limited, essentially to tests that can be run independently from one another.
The motivation for my amendment was that several “whole application” development strategies use — indeed by design — automated integration and acceptance tests to begin building a testable “walking skeleton” of the application, dropping down to unit tests as specific functionality is identified. I used a number of examples in support of this practice, pointing to the Corey Haines videos and other “whole application” development screencasts. Response was mixed, but largely along the lines of:
and the like. This is not a fair summary, but I have to say that after watching UB’s recent video on “Advanced TDD” (where he restated the cannon rules as an essential discipline), and the current clean coders “Java Case Study,” (using Fitnesse acceptance tests to develop outline production code), I have been suffering some cognitive dissonance.
I would be curious if people might reconsider the suggestion that using acceptance/integration testing to drive out initial program structure is inconsistent (by amending “unit” test to read “automated” test in the cannon) with the principles of DDD and TDD? Forgive me if I seem to be beating a dead horse, but isn’t the most recent case study exactly what I proposed? Can we agree that doing so (to build a walking skeleton for example) is NOT a violation of fundamental TDD discipline?
It's still very grey to me how granular you get FROM the BDD tests and the dance in how you get to those lower level tests and how you segregate or if you aren not to segregate them out to cover different layers of your sub app code.
Frederik,I have to be honest. I thought I was over complicating things, but hell you bring it to a new level :). Whether I call the BDD acceptance Tests Unit Tests or not THEY ARE TESTS. You create your acceptance tests. Then you have super glue in the middle that decouples you from the lower-level implementation (driven by TDD Tests - I know you'll cringe, now, I hope you do).
And Like you said:"when you need to write your classes (if you use classes), it makes sense to also write unit tests for them"
You just said it. I don't care whether I call the lower-level use case tests TDD tests, unit tests, or BDD Unit tests. I really don't fing care.
My definition is: A Unit Test is a test written by a programmer, for that programmer.
In other words, as a programmer you write a test that satisfies some need that you have. It doesn't matter what "level" the tests is written at, or whether you are testing a features, or a connection, or a protocol. What matters is that you, the programmer, needed to write the test for your own reasons.
I define "Acceptance Tests" as tests written by "the business" for "the business". If the business never writes or reads acceptance tests, and if programmers write them instead, then they are unit tests, and should be written in code, not in some BDD language. The only reason to write tests in a BDD language is if "the business" is somehow involved.