BDD has been discussed and dissected by many developers and code philosophers since its inception. Thinking about system behaviour is key. Thinking about the manner in which the system will react to external forces in a natural way is core to BDD. Perhaps insight into raw TDD itself will show just how this natural wrapper around TDD emerged.

A system or application emerges (from nothing) incrementally through TDD. What does this really mean? It simply means that a part of a system is constructed by way of the fulfilment of an expectation stated before that part of the system exists. What exactly is this expectation? It is a test (and we know that a test aggresively asserts that something is true about that part of the system, in a nutshell). A test must be satisfied.

//Here's our test subject
public class ZipcodeVerifier(){
   private boolean wasZipValid = false;
   public boolean isZipcodeValid(int zipcode){
       this.wasZipValid = true;
       return this.wasZipValid;
   }
}
//Here's our test
public class ZipcodeValidator{
  @Test
  public void testGoodZipcodeIsIndeedGood(){
     assertTrue(new ZipcodeVerifier().isZipcodeValid(22030));
  }
}

Now, suppose the exercise that just occurred created part of a system (S1). If we step back for a second, we see that S1 was created with a one or more techniques available to TDD (for example Kent Beck gives an example of making a simple test pass, using a technique known as ‘faking it’, where we return the exact type required by the test immediately with no logic attached to determining that value( From his book “Test-Driven Development”)). Let define “faking it”, one of the techniques used, as (tk1).

Also, S1 reacted (S1r) by providing the a value after completing its mission (a boolean). Not all subsystems need to do that (return type void).S1 also changed its internal state from false (S1s1) to true (S1s2). It was not necessary for S1’s own state to change (it may just as well have changed another subsystem’s state, S2, once it, in turn, comes into existence later).

In summary, the simple TDD exercise fulfilled the expectations of a test by creating a subsystem (S1) with a TDD technique (tk1, Beck’s technique) that reacted (S1r) by returning some information (true/false) and changing its internal state (from S1s1 to S1s2).

S1’s change of state calls to mind a style of software architecture: REST (Representational State Transfer). The restful state of the subsystem S1 changed by applying the technique (tk1). Note that some other subsystem, Sn, may have had its state changed too (or instead of S1, or even in addition to S1). The point is, a subsystem’s state is changing when a TDD technique (one or more, tk1…tkn) is applied to it.

But as the number of tests on the same test-subject grows, many more other subsystems will emerge (eg: a refactor may move some code into a private method). Those subsystems may change, in time, the states of other existing subsystems.

The representational state of any one subsystem (Snsn) now seems to become more and more important in determining how another subsystem (Sn+1sm) will react (Sn+1r) OR change the state of yet another subsystem from (Sn+2sy) to (Sn+2sy+1).

Now, if one had to pick any subsystem (Sb) and decide before-hand what one wishes its state to be (Sbsn) (that is, we wish for it to possess a representational state of a specific kind), we have already set an test-expectation for Sb.

Most importantly, however, when we actually specify in (what seems like a natural) descriptive state-representational language about the state of other subsystems that would help give Sb the desired state, we arrive at BDD (or at least the beginings of it). This applies also to the pure inputs to Sb that would cause the needed reaction, Sbr.

For example:
@Test
public void checkThatAddressContainsStateSymbolGivenANonNullZipcode(){}

In effect, we need the subsystem containing what we understand as an Address (for a customer or business) to contain (to possess a state) a State Code (eg: VA or KY) given that another subsystem, the Zipcode Handler, contains a valid state (a non-null zipcode).

Going back to the original example, we can see that there really is no other subsystem that determines S1’s state. We were dealing purely with a reaction (S1r) from the subsystem. If S1 had been re-written as follows:

//Here's our test subject
public class ZipcodeVerifier(){
   private boolean zipValid = false;
   private SimpleDelegator delegator;
   public boolean isZipcodeValid(int zipcode){
       delegator = new SimpleDelegator();
       setZipValid(delegator.determineValidity(zipcode));
       return getZipValid();
   }
  public boolean getZipValid(){
        return this.zipValid;
  }
  public void setZipValid(boolean valid){
        this.zipValid = valid;
   }
}
//Here's our test
public class ZipcodeValidator{
  @Test
  public void testGoodZipcodeIsIndeedGood(){
     assertTrue(new ZipcodeVerifier().isZipcodeValid(22030));
  }
}

Here, we see that S1’s state will change based on another subsystem internal state. The test is really checking that S1 has the state we expect. How? Because of the line:

return getZipValid();
based on the line:
setZipValid(delegator.determineValidity(zipcode));

…So BDD is another way of inquiring whether states and reactions are what they should be from the various subsystems that make up the main system using TDD’s rich toolset of techniques…but more importantly, doing so in simple, descriptive (almost human) terms….

, essentially:


[ BDD = Creating ∑[S1, S2, …, Sn]
injecting fn( { Ss = fn(S1s, S2s, …, Sns ) } and { Sr = fn(S1r, S2r, …, Snr ) } ) using { tk1, tk2, …, tkn } ]