Streamlined BDD Using SubSpec for xUnit.NET

tdd, code 0 comments suggest edit

I admit, up until now I’ve largely ignored the BDD (Behavior Driven Development) Context/Specification style of writing unit tests. It’s been touted as a more approachable way to learn TDD (Test Driven Development) and as a more natural transition from user stories to the actual code design. I guess my hesitation to give it a second thought was that I felt I didn’t need a more approachable form of TDD.

Recently, my Subtext partner in crime, Steve Harman, urged me to take another fresh look at BDD Context/Specification style tests. I trust Steve’s opinion, so I took another look and in doing so, the benefits of this approach dawned on me. I realized that it wasn’t BDD itself I didn’t like, after all, I did enjoy writing specs using minispec and IronRuby. I realized that the part I didn’t really like was the .NET implementations of this style. Keep in mind that I do not claim to be an expert in TDD or BDD, I’m just a student and these are just my observations. I’m sure others will chime in and provide corrections that we can all learn from.

SpecUnit.NET example

For example, let’s take a look at one example pulled from the sample project of Scott Bellware’s SpecUnit.NET project, which provides extensions supporting the BDD-style use with .NET unit testing frameworks and has really pushed this space forward. I trimmed the name of the class slightly by removing a couple articles (“the” and “an”) so it would fit within the format of my blog post.

[Concern("Funds transfer")]
public class when_transfering_amount_greater_than_balance_of_the_from_account
  : behaves_like_context_with_from_account_and_to_account
{
  private Exception _exception;

  protected override void Because()
  {
    _exception = ((MethodThatThrows) delegate
    {
      _fromAccount.Transfer(2m, _toAccount);
    })
    .GetException();
  }

  [Observation]
  public void should_not_allow_the_transfer()
  {
    _exception.ShouldNotBeNull();
  }

  [Observation]
  public void should_raise_System_Exception()
  {
    _exception.ShouldBeOfType(typeof(Exception));
  }
}

The Because method contains the code with the behavior we’re interested in testing. The two methods annotated with Observation are the specifications. Notice that the names of the classes and methods are meant to be human readable. The output of running these tests remove underscores and reads like a specification document. It’s all very cool.

What I like about this approach is there’s a crisp focus on having each test class focused on a single behavior, in this case transferring a balance from one account to another. In the past, I might have written something like this as two test methods (which led to duplicating code or putting code in some generic Setup method that seems detached from what I’m trying to test) or as one method with two asserts. This approach helps you think about how to organize tests along the lines of your objects’ responsibilities.

What I don’t like about it, and I admit this is really just a nitpick, is that it looks like someone’s keyboard puked underscores all over the place. I feel like having to encapsulate each observation as a method adds a lot of syntactic overhead when I’m trying to read this class from top to bottom. Maybe that’s just something you get used to.

MSpec example

Switching gears, let’s look at a different example by Aaron Jensen. This is an experiment in which he tried a very different approach. Look at this code sample…

[Description]   
public class Transferring_between_from_account_and_to_account   
{   
  static Account fromAccount;   
  static Account toAccount;   
  
  Context before_each =()=>   
  {   
    fromAccount = new Account {Balance = 1m};   
    toAccount = new Account {Balance = 1m};   
  };   
     
  When the_transfer_is_made =()=>   
  {   
    fromAccount.Transfer(1m, toAccount);   
  };   
      
  It should_debit_the_from_account_by_the_amount_transferred =()=>   
  {   
    fromAccount.Balance.ShouldEqual(0m);   
  };   
  
  It should_credit_the_to_account_by_the_amount_transferred =()=>   
  {   
    toAccount.Balance.ShouldEqual(2m);   
  };   
}  

There’s still the underscore porn, but it does read a little more like prose from top to bottom, if you can get yourself to ignore that funky operator right there. =()=> Whoa!

When I complained to Steve about all the underscores in these various approaches, he suggested that being a fan of the more Zen-like Ruby language, the underscores didn’t bother him. I didn’t buy that as part of the aesthetic of Ruby is its clean DRY minimalism. Yes, it uses underscores, but it doesn’t generally abuse them. Let’s take a look at a BDD example using RSpec and Ruby. This is an example of a spec in progress from Luke Redpath… (forgive the poor syntax highlighting. I need a ruby css stylesheet. :)

context "A user (in general)" do 
  setup do 
    @user = User.new 
  end 

  specify "should be invalid without a username" do 
    @user.should_not_be_valid 
    @user.errors.on(:username).should_equal "is required" 
    @user.username = 'someusername' 
    @user.should_be_valid 
  end 

  specify "should be invalid without an email" do 
    @user.should_not_be_valid 
    @user.errors.on(:email).should_equal "is required" 
    @user.email = 'joe@bloggs.com' 
    @user.should_be_valid 
  end 
end

One thing to notice is that we’re not using separate methods and classes here. Ruby doesn’t force you to put code in classes. You can just execute a script top-to-bottom. In this case, the code sets up a context block and within that block there is a setup block and a couple of specify blocks. There’s no need to factor a specification into multiple classes and methods.

Also notice that the context and specifications are described using strings! Now we’re getting somewhere. If it’s meant to be human readable, why don’t we use strings instead of the underscore porn? On Twitter, many accused the ceremony and vagaries of C# of preventing this approach. While I agree that Ruby has less ceremony than C#, I also think C# doesn’t get its fair shake sometimes. We can certainly take a C# approach down to its bare metal with the least syntactic noise as possible, right?

SubSpec

So in true Program Manager at Microsoft fashion, I spec’d out a rough idea of the syntax I would like to use with BDD. I then showed it to Brad Wilson asking him how can I make this work in xUnit.net. In true Developer fashion, he ran with it and made it actually work. This blog post is the part where I try to take all the credit. That’s what PMs do at Microsoft, write specs, take credit for the hard work the developers do in bringing the specs to life. ;) (I kid, I kid)

Here’s an example using this syntax…

[Specification]
public void PushNullSpecifications()
{
  Stack<string> stack = null;

  "Given a new stack".Context(() => stack = new Stack<string>());

  "with null pushed into it".Do(() => stack.Push(null));

  "the stack is not empty".Assert(() => Assert.False(stack.IsEmpty));
  "the popped value is null".Assert(() => Assert.Null(stack.Pop()));
  "Top returns null".Assert(() => Assert.Null(stack.Top));
}

A few things to notice. First, the entire spec is in a single method, which reduces some of the syntactic noise of splitting the spec into multiple methods. Secondly, we’re using strings here to describe the specification and context, rather than method names with underscores for the human readable part.

Lastly, and most importantly, while it may look like we’re committing the sin of multiple asserts in a single test, this is not the case. Via the power of the xUnit.NET extensibility model, Brad was able to generate a test per assertion. That’s why the Assert method (should it be Observe or Fact?) takes in a lambda. We can return these closures to xUnit.net and it will wrap each one in a separate test. Here’s another look at the same method with some comments to highlight how similar this is to the previous examples. (UPDATE: I also changed the asserts to use the Should style extension methods to demonstrate what it could look like).

[Specification]
public void PushNullSpecifications()
{
  Stack<string> stack = null;
  //equivalent to before-each
  "Given a new stack".Context(() => stack = new Stack<string>());

  //equivalent to Because()
  "with null pushed into it".Do(() => stack.Push(null));

  //Equivalent to [Observation]
  "the stack is not empty".Assert(() => stack.IsEmpty.ShouldBeFalse());
  //Equivalent to [Observation]
  "the popped value is null".Assert(() => stack.Pop().ShouldBeNull());
  //Equivalent to [Observation]
  "Top returns null".Assert(() => stack.Top.ShouldBeNull());
}

Keep in mind, at this point, this is a merely proof-of-concept sample that will be included with the samples project in the next version of xUnit.NET and by the time you read this sentence, it may have changed already. You can download this particular changeset here.

The following is a screenshot of the HTML report generated by xUnit.NET when using this syntax that Brad sent me today.subspec-report

Despite it being a sample, I tried to give it a catchy name in case this is intriguing to others and worth iterating on to make it better (not to mention that I love putting the prefix “Sub” in front of everything.)

Possible next steps would be to add all the Woulda, Coulda, Shoulda extension methods so popular with this style of testing. For example, that would allow you to replace Assert.False(stack.IsEmpty) with stack.IsEmpty.ShouldBeFalse(). For those of you practicing BDD, I’d be interested in hearing your thoughts, objections, etc… concerning this approach.

For completeness sake, here’s another syntax I proposed to Brad. He mentioned it was similar to something else he’s seen which he might port over to xUnit.net.

[Specification]
public void When_Transferring_To_An_Account()
{
  Election e = null;
  Account a = null;
  Account b = null;
 
  Where("both accounts have positive balances", () => {
    a = new Account { Balance = 1 };
    b = new Account { Balance = 2 };
  });
 
  When("transfer is made", () =>
    
    a.Transfer(1, b)
  );
 
  It("debits account by amount transferred", () => a.Balance.ShouldBe(0));
  It("credits account by amount transferred", () => b.Balance.ShouldBe(3));
}

For those of you completely new to BDD, check out Scott Bellware’s Code Magazine article on the subject.

Technorati Tags: tdd,bdd,xunit.net

Found a typo or error? Suggest an edit! If accepted, your contribution is listed automatically here.

Comments

avatar

56 responses

  1. Avatar for Scott Bellware
    Scott Bellware August 24th, 2008

    Phill,
    Good to see you picking up some of the Context/Specification stuff.
    It looks like you've begun to make changes to things that you haven't quite yet got a good understanding of yet.
    Your examples are representative of biases of the Fixture per Class xUnit pattern. You haven't given yourself enough time to see Context/Specification without the powerful influence of these long-healed biases influencing your perception.
    I don't think that it's such a positive thing to express these alternatives yet as your obvious leadership position in the community can be taken by your readers to mean that experience and insight into Context/Specification is in play here.
    I understand that you've stated clearly that you're proposing theoretical syntax and grammars, but having published alternate syntax and grammar as Phill Haack will inevitably mean that others who have not yet invested enough time to grok the reason for the grammar may by diverted from a course of practice that will lead to more readily to understanding.
    Why not practice the forms, gain some fluency in them, and THEN innovate? You don't have to behave like a Microsoft Program Manager all the time :)
    P.S. That RSpec spec is a clusterf*ck. I wouldn't propose it as a good example of Context/Specification as much as it is an example of the RSpec API. It's still legal and functional RSpec, but it's not representative of the intentions of Context/Specification.

  2. Avatar for Matthew Otto
    Matthew Otto August 24th, 2008

    It may be because I'm used to reading specs written using SpecUnit and RSpec, but in the SubSpec example I find it more difficult to quickly pick up the behavior being tested. There is less noise from not having underscores in the method names, but I think once you had a project with a large number of specs you'd lose the the benefits of having the specification defined as strings due to the reduced scanability of the specs.

  3. Avatar for Scott
    Scott August 24th, 2008

    I think the grammar of your first "SubSpec" example is interesting, to be sure, and it certainly shows that Brad has some skills (not that it was ever in doubt), but to me it feels like the specification gets a little more obfuscated in the cleverness, or at least much less scannable.
    When we practice context/specification slash BDD test construction one of the primary concerns is that the test code is scannable and that we have an easily understandable code representation of the English (or your language here) sentences on the story cards. In particular, the double-assert syntax you have here seems to me to hinder that scannability.
    The second grammar is better in that regard.

  4. Avatar for Joe Chung
    Joe Chung August 24th, 2008

    Underscore porn! Ha ha! Good one, Phil. Though I've a feeling you'll be showing up on some bizarre NSFW Google searches for now on because of that. ;)

  5. Avatar for Sean
    Sean August 24th, 2008
    I wouldn't propose it as a good example of Context/Specification


    what would you propose as a good example of Context/Specification, in your opinion?

  6. Avatar for Scott Bellware
    Scott Bellware August 24th, 2008

    Sean,
    I would propose the examples that I have already left in the public record, such as those quoted by Phill above.

  7. Avatar for Mihai
    Mihai August 24th, 2008

    Well, I've only just read that BDD exist yesterday by pure coincidence. And today you happen to write about it :D. Although Scott is pretty rough with you he does have a point, your readers do look up to what you have to say, otherwise they wouldn't read you blog posts. And examples that contradict the "purists" are not very helpful. But I do like what I saw and there where warning signs posted all over in the article in which you specified you are not an expert in any way on the practice of BDD.
    Also the '_' thing might not have been so bad after all, but using "strings" is always better than the first example.
    All in all it's better to see something like your examples ( well Brad Wilson's work >:) ) than the underscore porn as you called it ( =)) so funny ) that we saw at first.

  8. Avatar for Brad Wilson
    Brad Wilson August 24th, 2008

    I'm not a huge fan of the syntax myself, either, but I did it for two reasons:
    1. to test the extensibility of the xUnit.net APIs
    2. to give Phil a starting point to experiment with his own APIs
    I'm not a BDD/Context/Spec tester myself, so I won't make any claims about what's good or bad. This is mostly a learning exercise for me about the limitations of the testing framework.
    I am planning to take the example syntax from Machine.Specifications and see what would be involved in getting something like that to run inside of xUnit.net as well.
    I don't think Jim and I are planning to commit to any one given syntax, and will probably continue to leave examples of everything in the Samples projects rather than integrate it into xUnit.net itself (or as an extension), unless the community makes a very strong statement about wanting it in.
    By the way, Phil, we do have a few of the "should" style extensions available in our xunitext35.dll project. You should take a look at them as your starting point for your should stuff.

  9. Avatar for speedmax
    speedmax August 24th, 2008

    underscore porn, nice put..
    Its something quite a few language suffers with weak FP support..
    Well, i hack together a rspec inspired BDD library in lua.. readable spec with readable string is a pure joy..
    github.com/.../array.lua

  10. Avatar for Colin Jack
    Colin Jack August 24th, 2008

    "the stack is not empty".Assert(() => Assert.False(stack.IsEmpty));
    I like the experimentation but this syntax doesn't seem attractive to me, far too much going on in that one line.
    I'm also with Scott on the fact that to appreciate the context/specification style you need to try it for a while. After a (short) while you realize that its all about exploration/design and results in a much improved experience over the approach where you try to do a lot of things in each specification method.

    "I feel like having to encapsulate each observation as a method adds a lot of syntactic overhead when I’m trying to read this class from top to bottom. Maybe that’s just something you get used to."
    I actually feel the short focussed specification methods are one of the major advantages of BDD as suggested by Astels (http://www.daveastels.com/files/BDD_Intro.pdf).
    Also if its the flow that bothers you you could reorganize, perhaps put the specifications first (saw this on a blog entry recently but haven't tried it yet). This would work with the context/specification approach because the class name tells you the context so you only need to see the setup/because method if you want to understand how you get to that situation.
    I would also encourage anyone looking at BDD to also look at what Dan North has been doing as he was the pioneer of BDD and his style is quite different and (as I see it) more suited to acceptance testing.

  11. Avatar for anon
    anon August 24th, 2008

    Just started out using TDD, and was wondering how to do things well.. something *did* seem out of place in using/understanding TDD (haven't bought a book on it yet), and Dan North's article was very informative, and really good! Thanks! (Next step: read your take on things and all the comments and figure out a bit more)

  12. Avatar for Colin Jack
    Colin Jack August 24th, 2008

    @anon
    Just to be clear, Dan North is talking about something different from this. I mention this not because I think either approach is superior, I actually use both, but because I think recognising the differences is the key to avoiding confusion.
    Anyway to me if an article mentions xBehave/Acceptance Testing then it is talking about the approach Dan North describes, if it discusses TDD/xSpec/context+specification (as here) then we are probaby talking more about the approach Dave Astels (and in .NET land Scott) have been pushing for. As I say I think both are useful.
    You might also want to look at the BDD group: groups.google.com/group/behaviordrivendevelopment

  13. Avatar for Klaus Hebsgaard
    Klaus Hebsgaard August 24th, 2008

    With ironRuby moving on very fastly towards release, why would we want to implement RSpec in C#?
    Should it not be possible to use RSpec through ironRuby and test a .Net application that way around?
    I haven't tried this myself, but it's on my list...

  14. Avatar for Sean Chambers
    Sean Chambers August 24th, 2008

    I have to agree with Scott Reynolds here and say that the second option is alot more descriptive than the first.
    Although, I feel that the BDD type stuff is still evolving and finding its way. I don't really have enough experience with it to have a rock solid opinion, but I still find the SpecUnit stuff still seems to be more indicative of my assertion intent than grouping them under one "Specification" and letting xUnit sort them out. It seems kind of messy to me.
    Like I said, I don't have enough experience yet with BDD to really have an opinion so just ignore me =)

  15. Avatar for Mel Grubb
    Mel Grubb August 24th, 2008

    My problem lately with the traditional BDD-style syntax has been that if your "behaves_like" inheritance goes more than a single layer deep, it starts to become impossible to look at a context class and see what the actual context is. So much stuff is hidden in the base classes that you can't tell what the world looks like anymore without going on a safari through the code. I'm toying with the idea of using a BDD-like syntax, but without and "behaves-like" classes at all. Anything needed to set up the context would go in a single base class as helper methods that get called by each descendent context class. This way, you could look at the "before" method of a context and see everything that's happening. In pseudocode, it might look something like this:
    public class given_a_customer_with_orders
    {
    before_each_spec()
    {
    Customer c = CreateCustomer();
    Order o = CreateOrder(c);
    OrderDetail od = CreateOrderDetail(o);
    }
    ...tests...
    }
    I don't have to keep track of what may or may not have happened in some base class now. I can clearly see what my actual context IS in one place within the context itself. I think it's a lot more readable than the traditional syntax.
    MG2

  16. Avatar for Scott Bellware
    Scott Bellware August 24th, 2008

    Mel,
    The scenarios where you need to lay eyes on object initialization code in set setup are fewer than you might think, and frequently this need is due to a psychological fixation than a technical or cognitive necessity.
    Well-written Context/Specification classes document and describe intent and essence.
    If within a context that describes funds transfers I presented you with the line of code:
    fromAccount.Transfer(2m, toAccount);
    ...you should be able to immediately grok the essence of how the API works.
    This is written for scanning rather than reading. Most of the time, we're scanning code, and only part of the time time we're reading code. Creating an interactive experience that takes advantage of a predisposition to scan is an essential bit of crafting artifacts for usability.
    There's a reason why programmers are often the creators of horrible user experience: programmers believe that people are stopping to read the artifacts that they have beneficently left behind for the world to enjoy.
    I don't really care to "read" all the code I come across in a given work day. I'm more interested in finding the work site where I need to be, and I do that by scanning. When I arrive at the work site, I may then take a detailed read, and I want that experience to be essential and rich in order to speed my understanding first from a general perspective, and then at a more detailed perspective if I choose.
    When we don't code for usability, we're sucking productivity out of our team mates and generating significant waste. It's subtle waste, but it's pervasive and thus - for me - a target for optimization.
    When you need to sit down to work on context code that hides the language ceremony behind a base class, you *may* need to read that base class, but there's not much of a safari hunt for code here. Finding the object initialization code - the little of it that there is - doesn't require much of a user in terms of interactions with a modern editor.
    And ultimately, if you want to show the ceremonial code inline in a context class, there's no reason that you can't, but consider the possibility that our need to see the details is only active because we are presently sitting in that class and focusing on it. At that point in time there are thousands of other classes that we may simply need to scan.
    When object initialization is a key part of what is being documented, I write semantically-rich factory methods that describe this significance better than raw code does in effort to yet again improve the scanability of the code.
    The point is to communicate the essence of the API so that scanning is unencumbered by programming language ceremony and noise that isn't essential to understanding how an API works.
    Bringing usability practices to program code isn't easy, and it's utterly counter-intuitive to most programmers. This issue for me is the next stage of progress in agility, and it means over-coming many of the presumptions that programmers have about what goes into a good user experience - an area where programmers are inherently challenged.

  17. Avatar for haacked
    haacked August 24th, 2008

    @all Ignore the double assert. As Brad mentions, there is a library of the "Should" style extension method asserts in xUnit.NET. I just haven't played with them yet. This is a proposed syntax and we can change the names of any methods. Suggest a better name! :)
    @Scott Bellware do you have an example of a ruby-based context/specification example that you would consider among the best examples out there?
    Regarding my "biases of the Fixture per Class xUnit pattern", to be fair, I think all the C# examples exhibit the bias of assert per method bias. In other words, when you look at the various Ruby implementations, they use blocks rather than methods and classes to delineate specs. It is possible to do something like that with C#. I could have had all my tests in a single method.
    Regarding "I don't think that it's such a positive thing to express these alternatives yet", I understand your opinion, but I completely disagree.
    First of all, a great way to learn a new concept is to dive right in and try to improve it. Sometimes those attempts may be naive, but what better way to understand something than to try and understand both its strengths and weaknesses. I've put the requisite disclaimers in the post, I don't think you should try to quiet my exploration.
    Try to look beyond your own biases. I know you've spent a lot of time with SpecUnit.NET and have a lot invested in this area. Are you suggesting there's no room for improvement? I doubt that fits the Kaizen way.
    Are you suggesting that nothing in my examples (perhaps with a bit of cleanup, renames, etc...) that has any merit?
    If so, I respect your experience in this area and am willing to harder look to see what the shortcomings are. But I would appreciate specifics. You mention my biases, but you don't say why they're necessarily wrong.

  18. Avatar for haacked
    haacked August 24th, 2008

    p.s. In the commented example, I put in the "Should" style methods to clarify what it might look like in practice.

  19. Avatar for davidalpert
    davidalpert August 24th, 2008
    "the stack is not empty".Assert(() => Assert.False(stack.IsEmpty));


    I actually like that syntax; it provides a human readable (and easier to type without all those underscores) explanation on the left followed by a coded execution on the right. There's actually less going on there than it looks like and after you grok that it should be fairly simple to scan either the string descriptions or the execution codes...
    At the same time, i'm not a fan of the Woulda, Coulda, Shoulda extensions. I tried using them in some ASP.NET MVC unit tests and found them less readable; suddenly i couldn't scan for my Assertions because they were all "hidden" and scattered throughout the source masquarading as standard method calls. I went back to Assert. syntax as the standard signatures helped highlight the expected and actual data.
    Perhaps, however, the Woulda, Coulda, Shoulda syntax has a place when writing tests to document syntax as opposed to tests that verify functionality.
    I realize that ideally the same tests may serve both goals, but we're all learning, right?

  20. Avatar for Khalid
    Khalid August 24th, 2008

    I've been using StoryQ, NUnit, and Gallio test runner as my BDD stack. I really like it because it has a fluent interface and Gallio spits out a really nice html output for all you specifications. I have a walkthrough on how to use both. The example might be a little unorthodox, but it drives the point home. So sue me if I watch too many zombie movies.
    monstersgotmy.net/.../...n-Development-Part-I.aspx

  21. Avatar for Colin Jack
    Colin Jack August 24th, 2008

    @Khalid
    Good post.
    You may already know this but StoryQ is heavily influenced by NBehave. However (broken record time) to me thats a different style and has different characteristics. I've actually tried to blog about the differences before as they threw me when I was trying to get my head around BDD:
    colinjack.blogspot.com/.../bdd-two-approaches.html
    This is also highly relevant:
    www.zombiesarecoming.com/.../top-5-reasons-you-...

  22. Avatar for Scott Bellware
    Scott Bellware August 25th, 2008

    Klaus,
    I'm looking forward to using RSpec in .NET, but it's not there yet, and I started doing this stuff in .NET two years ago. The tools we're using now reflect what we have at our disposal now. The tools we'll use later will reflect what's available to us then.

  23. Avatar for tgmdbm
    tgmdbm August 25th, 2008

    Nice, I like the second syntax better. I'm not sure I really understand the objections. I'm all for more human readable and less code.
    Also, do you really need an election to transfer moneyz?

  24. Avatar for tgmdbm
    tgmdbm August 25th, 2008

    @David have you had a look at the NUnit SyntaxHelpers namespace?
    Assert.That(x, Is.EqualTo(y))
    You can't get more human readable?

  25. Avatar for Brad Wilson
    Brad Wilson August 25th, 2008

    @tgmdbm, I find:
    x.ShouldBeEqualTo(y);
    to be preferable to:
    Assert.That(x, Is.EqualTo(y));

  26. Avatar for Scott Bellware
    Scott Bellware August 25th, 2008

    Phil,
    > Try to look beyond your own biases. I know you've
    > spent a lot of time with SpecUnit.NET and have a lot
    > invested in this area. Are you suggesting there's no
    > room for improvement? I doubt that fits the Kaizen way.
    I've got almost nothing invested in SpecUnit.NET and looking beyond my own biases was what I was doing while working with Aaron on the MSpec experience.
    > a great way to learn a new concept is to dive right
    > in and try to improve it.
    Why not just dive right in and learn to swim first rather than assuming that the path to understanding something that you've just connected with is to change it?
    Continuous Improvement is about a pursuit of mastery, not an impetuous indulgence in a drive for immediate cerebral and social gratification. First shu, then ha, then ri.
    There's more to kaizen then learning how to spell it.

  27. Avatar for haacked
    haacked August 25th, 2008

    Once again, you duck answering the relevant questions, instead taking the opportunity to lecture me on what my learning style should be, as if you know how I learn better than I do.
    You ascribe motivations to my experimentations that only reflect your own biases. This is starting to be a pattern I see with you.
    This is an experiment. I haven't changed anything, I've proposed alternative approaches. The feedback from the experiment provides deeper knowledge. While at the same time I continue to dive into the topic. If you think I should keep my experiments to myself, you're entitled to your opinion.
    I feel that publishing on the web offers immediate feedback that provides a diversity of insight I won't get studying on my own. Already I've received good feedback and learned more than from simply reading various posts on the topic and from trying it out on my own.
    Now back to my original questions:
    Are you suggesting there's no room for improvement? Are you saying there's absolutely no merit in anything I've presented here?
    And a new question, What do you see as the weaknesses of the current approaches out there?

  28. Avatar for Scott Bellware
    Scott Bellware August 25th, 2008

    > Are you suggesting there's no room for improvement?
    No, I'm saying there's lots of room for improvement. That's the whole point to the Context/Specification and Solubility efforts, and demonstrably the effort to communicate these improvements over the past couple of years.
    > Are you saying there's absolutely no merit in anything I've
    > presented here?
    I feel that you're doing more harm than good for putting your name behind premature speculation about a practice whose finer points you haven't begun to see yet.
    > What do you see as the weaknesses of the current approaches
    > out there?
    Two weaknesses:
    - Excessive programmer focus on API cleverness rather than a focused study of usability, cognition, and the economics of pervasive waste.
    - Either you've got a good programming language for BDD and a crappy mocking framework, as is the case with Ruby, or a crappy programming language and a good mocking framework, as is the case with C#. Tools are still constraining the practice.

  29. Avatar for Mihai
    Mihai August 25th, 2008

    I've given BDD a try all day long. Reading dan north's thoughts and to be perfectly honest I find the Specification example provided in xUnit to be exquisite. I love it. Also I haven't done BDD before so I don't have any constraints in how it should or shouldn't be. It gets the job done, no porn involved, I don't see anything but benefits.
    What's the problem with API cleverness? Isn't the hole point focused on writing better code? If you can write less and do more I think you're one step forward.
    I'm sure you're more qualified to answer but honestly after trying it what made you so annoyed with it ?
    Phil thank you for your post, it helped!
    Also, I had a lot of "Aha!" moments yesterday, and I find BDD to be exactly what I found missing or poorly explained in TDD.

  30. Avatar for Aybarnt
    Aybarnt August 25th, 2008

    cool example ;)
    _________________________
    http://www.aybardumlu.com

  31. Avatar for Colin Jack
    Colin Jack August 25th, 2008

    @Scott
    Having used xSpec style for a time I agree with most of what you are saying.
    However I do remember in the past you have said that people were not "getting" BDD when they were actually following closely the ideas put forward by Dan North, and that you then said that they shouldn't be expressing their views publicly.
    I know this is a different situation but I thought I should mention that.

    @Phil
    My view is its worth trying to understand the essence of something before trying to change it, especially something that people have put a lot of work into. Maybe you've just picked context/specification up really fast and identified issues with it, in which case great and all power to you.
    However my experience has been that in general good ideas like BDD come out in a blaze of glory but they are then quickly watered down through misunderstandings and re-definition. I think this has held back good approaches in the past, TDD/DDD/REST come to mind, which is a real pity.
    I'm hoping this doesn't happen with BDD but I have little confidence, particularly because it's quite subtle and there is already enough confusion about how to practice it.
    So I do wonder whether yet another approach is a good idea. I guess my question is what do you think BDD is, and what do you think the context/specification style helps with?
    I'd also be interested in knowing whether your ideas are consistent with those of Dave Astels (including his guidelines on the last page of the PDF), if not why do you think we need another approach?

    @Mihai
    If you managed to read Dan North's thoughts and this post and put them together then that's cool. I can't do that, but then I think in general context/spec is quite different from the BDD approach Dan North originally wrote about (as I understand it Dave Astels and Dan North just came to different conclusions as to what BDD is, which has resulted in two different directions).

  32. Avatar for Troy Howard
    Troy Howard August 25th, 2008

    Hmm... I'll preface my comment with the statement that I don't know anything at all about BDD other than what I've read here and at the links presented here...
    That said, I find the discussion between Phil and Scott interesting, and I'm having trouble agreeing or disagreeing with either of them completely.
    I agree with Phil, that I like to learn by diving into something. I also enjoy when newbies propose radical changes to elements of a system that irk them while learning it. I think that's a great way to evolve an established system to be more intuitive and end-user focused.
    I agree with Scott that changes to an established system should be made from a considered standpoint, by someone who understands the full scope of the system, and it's intended use.
    I agree with Scott that famous people can have a greater impact on society than they know and thus must act with a greater level of responsibility.
    I disagree with Scott that Phil is famous enough to worry about.
    I agree with Phil that using his modicum of fame to present these ideas to a wider audience through the process of critical discourse is the best use of said fame.
    He's basically got two great resources: his quick wit and sharp intellect, and his readership that he gained by using the former. I think he's using both of these things in the best way possible to support this new idea of BDD.
    It also occurs to me that what he's doing is exactly the spirit of BDD, since the thing that makes BDD unique is that it focuses on the semantics of expressing a specification vs writing a test. Phil seems to be focused on making sure that the syntax used to express that spec is not destroy the semantic advantage of BDD over TDD.
    It occurs to me that this a good case for a DSL, instead of trying to make various programming languages express something in ways that aren't intuitive to their syntax.
    Anyhow... My opinions about this discussion aren't really significant, since I have no idea what I'm talking about, really.
    BUT...
    With all that in the back of my head, as I read the PDF by Dave Astel, I came across this bit that seemed relevant (top of page 4):
    " So if it's not about testing, what's it about?
    It's about figuring out what you are trying to do before you run off half-cocked to try to do it. "

    I get the feeling that's the gist of Scott's objections.
    So I propose this as homework for Phil... Start a project to write a set of BDD specs for BDD. The spec will describe what a BDD framework's behaviours "should be". Then, using that spec, we can test the existing implementations, including Phil's syntax.
    We can all be part of the creation of that spec, and I'd love to see Scott's input on that.

  33. Avatar for Brian Lowry
    Brian Lowry August 26th, 2008

    I just wanted to chime in and say that I appreciate Phil's post. One of the difficulties of learning less practiced software methodologies is actually finding good resources. Learning C# isn't hard because everyone blogs about it. But I'm willing to bet that 80% of developers have never heard of BDD, and most of them not even TDD.
    Phil has a point. Our profession revolves around the ability to learn and learn quickly. It is discouraging to want to learn TDD/BDD/etc. best practices but not find any good resources easily. Personally, I think the best way to learn something is just as Phil is doing: dive in head first, play around with it, blog it, and follow the advice and links that are given by his fellow readers. As long as he makes it clear that he is no expert in BDD, no one that is truly trying to learn BDD is going to take his word for the gospel.
    What it does do is give me and others a great launching pad to start researching. I now have a list of BDD frameworks discussed by everyone above to start researching. Plus, he has just brought BDD into the community crosshairs to some degree. Isn't that what this is all about? Improving the community?

  34. Avatar for Tom
    Tom August 26th, 2008

    Sorry Scott, anoter one for Phil! I feel like we went through it with Rob and his MVC Storefront series. Give the readers here some credit, when the guy clearly states he is a student and looking for feedback, we get it!

  35. Avatar for Scott Bellware
    Scott Bellware August 26th, 2008

    Mihai,
    > What's the problem with API cleverness? Isn't the hole
    > point focused on writing better code?
    No. It's actually a common antipattern that often leads to an incredible amount of waste.
    > If you can write
    > less and do more I think you're one step forward.
    Only under the right conditions. Reduction of lines of code isn't a stable indicator or cause of productivity or effectiveness.

  36. Avatar for Scott Bellware
    Scott Bellware August 26th, 2008

    Brian,
    > Our profession revolves around the ability to learn
    > and learn quickly.
    Our profession may revolve around the belief that this is a good way to do things, but it's merely a common way to do things... such as a common belief that the world is flat, and the predisposition to hold onto this belief long afer explorers have returned from the new world.
    > It is discouraging to want to learn TDD/BDD/etc. best
    > practices but not find any good resources easily.
    There are different kinds of resources for different kinds of practices. Don't expect to be able to pick up TDD like you can pick up ASP .NET. TDD skill and fluency isn't the same kind of knowledge acquisition.
    TDD is a practice. You have to practice is to understand it. Something like ASP .NET is a framework; a tangible. With something like ASP .NET that is mostly a material concern, you can "pick it up". You can't just expect to "pick up" TDD like you can pick up a framework.
    Understanding first that there are different kinds of knowledge goes a long way for balancing our expectations on how long these different things should take to learn.
    > Personally, I think the best way to learn something is just
    > as Phil is doing: dive in head first, play around with it,
    > blog it, and follow the advice and links that are given by his
    > fellow readers.
    Yes. But it ends there. Phil is indulging a pathological drive to change the subject matter to find his pre-conceptions rather than to give his pre-conceptions an opportunity to be changed by practice.
    > As long as he makes it clear that he is no expert in BDD,
    > no one that is truly trying to learn BDD is going to take
    > his word for the gospel.
    That's true up until the point where he proposes alternatives to a practice that he hasn't assimilated yet.
    If a noname blogger posted proposed alternatives to the syntaxes, then it would likely go nowhere. With these kinds of proposed changes posted by Phil, a younger or intermediate reader will feel more confident in using these alternatives.
    Even through claims are issued with Phil's caveat emptor, the caveat emptor's effectiveness is undone by the weight of Phil's status. That programmer then shares the ideas with other programmers under the aegis of, "I got it from Phil Haack's blog," and then we've got a misrepresentation propagation current to fight while already fighting the pathological resistance to learning practices and technique already rife in .NET community.
    This kind of thing has been a constant thorn in my side for a good number of years in the Microsoft community. It's part of the Microsoft pathology.

  37. Avatar for Scott Bellware
    Scott Bellware August 26th, 2008

    Colin,
    > However I do remember in the past you have said that people
    > were not "getting" BDD when they were actually following
    > closely the ideas put forward by Dan North, and that you
    > then said that they shouldn't be expressing their views publicly.
    My disagreement with Dan North's proposal is in the clear and public. I don't agree with the ceremony of the grammars that he proposed, but I agree with the methodology, expect for the belief that BDD should be restrictively applied at the outer layers of an app.
    I believe that what Dan came up with represents a watershed moment and a tipping point, but I believe that his perspective on specifics in implementation is influenced by an attachment to a particular framework.
    I look forward to talking with Dan in person more about this, and I hope that he makes it to the Continuous Improvement conference and that we get a chance to have a high bandwidth dialog.
    In respect to Dan, I call the specific practice that I'm using and teaching, "Context/Specification" so as to try to not collude the namespace and obstruct learning.

  38. Avatar for Joe Ocampo
    Joe Ocampo August 26th, 2008

    This would be a great discussion to bring to the BDD mailing list.
    groups.google.com/group/behaviordrivendevelopment

  39. Avatar for Colin Jack
    Colin Jack August 26th, 2008

    @Scott
    "I look forward to talking with Dan in person more about this, and I hope that he makes it to the Continuous Improvement conference and that we get a chance to have a high bandwidth dialog."
    If he does you'll have to tape it, will make good viewing. Kinda a pity the discussions on the BDD group have calmed down recently, hopefully it'll all kick off again at some point.

    "In respect to Dan, I call the specific practice that I'm using and teaching, "Context/Specification" so as to try to not collude the namespace and obstruct learning."
    Yeah I like that a lot, makes a big difference.

  40. Avatar for haacked
    haacked August 26th, 2008

    It's too bad when you do a search on Bellware and BDD you find this article (which I referenced in my blog post) www.code-magazine.com/Article.aspx?quickid=0805061. Can you contact Code Magazine and see if they'll change the title so as not to cause confusion?

  41. Avatar for Scott Bellware
    Scott Bellware August 26th, 2008

    Phil,
    > Can you contact Code Magazine and see if they'll change the
    > title so as not to cause confusion?
    I'll be seeing the editor of the magazine this weekend, but before I ask him, do you think that a print magazine with co-publication on the web tend to look favorably on revising web content once it has gone to print?
    This article went to print a few days before I had my conversation with Dan about the namespace, and the differences and similarities in our respective methodologies.

  42. Avatar for Joe Ocampo
    Joe Ocampo August 26th, 2008

    Phil in the NBehave source we have extensions for MbUnit that you can use as a template for xUnit extensions.
    code.google.com/.../Extensions.cs

  43. Avatar for Joe Ocampo
    Joe Ocampo August 26th, 2008

    BTW before you start going to far with the syntax mix in a mocking framework. It changes the heuristics a bit.

  44. Avatar for haacked
    haacked August 26th, 2008

    @Scott I would think they would want to reap the benefits of publishing on the web, which allows them to make corrections and improvements to content. I guess it depends on how old school they are regarding publishing. But consider the fact that their web publication probably has far more reach in the long run than their print publication due to Google.

  45. Avatar for Brian Lowry
    Brian Lowry August 26th, 2008

    @Scott
    Funny thing... I went to your blog just to read up on what you are posting these days, and I realized that you don't allow comments? Maybe I just couldn't find them easily. At any rate, not allowing comments on your blog *combined* with the way you have been coming off on this post presents the notion that you are the authority on X technology (BDD) and that no one knows as much as yourself. I feel as though you want to prevent learning through discussion, and quite honestly it is a big turn off for me personally.
    I know for a fact that you are much more experienced than I in programming as a whole. Instead of blasting others for not understanding the technologies well enough, why not step up to the plate and show us the light. What resources do you recommend for adventurous developers?
    To me, there is no reason that Phil as a Microsoft employee, or Rob Connery, or anyone else considered "famous" shouldn't be allowed to express their ideas freely on the internet. I mean, go back and re-read this post. It is absolutely littered with disclaimers and there are 20+ comments below stating their opinions (disagreements) on his direction.
    I find it ironic that Microsoft is blasted for lack of community involvement when I feel that Phil, Rob, etc. are doing their damnedest to be involved. One of the things that I really dig about these guys is that they are modest and don't claim to be the authority on much really, but rather that they are trying to learn new technologies and methodologies like the rest of us - helping the Microsoft community learn in the process. That is leadership. Banning people from carrying an open discussion on your own blog is not.
    I think we as a community need to find ways to lower the barrier to entry into new methodologies instead of just saying "you can't just 'pick it up'". IMO, blogging about your learning is a logical step. The more blogs about BDD that are out there, the easier it will be for others to learn it. Sure, there are going to be some bad practices blogged about, but typically the comments section of the blog is where you can read the community's thoughts on your views.
    /catches breath
    While I partially understand your point of view about Phil possibly leading others in the wrong direction, I disagree wholeheartedly... and this is why:
    If no-name blogger decides to write a post about BDD and I, average Joe, stumble upon it, odds are he doesn't have much viewership and certainly not many comments on his approach. This may lead me and others I'm close to down the wrong path.
    On the other hand, if Phil writes a blog about the same topic and others disagree, his massive viewership will reflect their disagreement in the comments... you know, offering other view points, other resources, etc.
    Come on man, lighten up. Let's figure out how we, as a community, can move forward in sharing methodologies that make our jobs easier and get us home sooner.

  46. Avatar for Brian Lowry
    Brian Lowry August 26th, 2008

    While I'm killing Phil's bandwidth, I wanted to go ahead and say one more thing to demonstrate how leadership through active involvement helps others learn.
    When MVC's preview was released, I immediately added an RSS feed to iGoogle for the MVC forums on asp.net. A poster above, tgmdbm, has been actively involved in those forums since day one - his name appeared in every other topic I read. He has influenced a lot of my learning of MVC. I can't tell you his first name, where he works, or even provide a blog (which is a shame), but the majority of what he said resonated with me.
    I didn't follow his advice blindly, but rather prototyped a few things he discussed. Through his leadership, I picked up MVC in no time and while I still have many things to learn, his involvement has helped at least one member of the community use better practices.
    He's not famous at all to my knowledge (yet ;) ), but he is an example of what is right with the Microsoft community. It is all about learning and sharing and nothing about status.
    I don't think I'm alone (I hope not), and I know that the majority of the people reading this blog are intelligent enough to understand a disclaimer and not accept everything said as best practice.

  47. Avatar for daniel_auger
    daniel_auger August 27th, 2008
  48. Avatar for Throwspoop
    Throwspoop August 27th, 2008

    LOL...Haacked has been alt.netted!

  49. Avatar for Klaus Hebsgaard
    Klaus Hebsgaard August 30th, 2008

    Scott actually you can use the mini_rspec implementation in ironRuby to test .Net code today.
    I hav an example here:
    khebbie.dk/.../...ronRubys-mini_rspec-library.aspx

  50. Avatar for Kristoffer Ahl
    Kristoffer Ahl November 27th, 2008

    "My disagreement with Dan North's proposal is in the clear and public."
    @Scott
    It would be very helpful if you could provide a link to where these disagreements are published.

  51. Avatar for kazim
    kazim December 16th, 2009


    "Given a new stack".Context(() => stack = new Stack<string>());
    the above syntax generate stylecop warning SA0102. What i did to resolve it put "Given a new stack" in a varible like
    var given="Given a new stack";
    given.Context(() => stack = new Stack<string>()); anyother idea to resolve it ?

  52. Avatar for Quooston
    Quooston January 17th, 2010

    Scott, you must be the most opinionated person I have ever read. The most annoying thing is that you are a smart opinionated person, which means you just keep coming back with more opinion no matter what the reply... you're just making a loud buzzing sound now which is annoying. This short foray out of your ivory tower must have exhausted you by now, so go back there now. Thanks.
    Microsoft is now involved in the community and we love it. There is immense value in what Phil is doing here, it encourages the sort of feedback which is difficult to get going otherwise, and that benefits ALL.

  53. Avatar for cesar
    cesar June 13th, 2010

    What did it happen to SubSpec?

  54. Avatar for fschwiet
    fschwiet December 13th, 2010

    I've been working on an NUnit extension that provides BDD support. Inspired by Jasmine for BDD (as I don't know RSpec) its pretty close to the syntax you proposed to brad. You can have multiple describe()s per test, even nesting them freely. It is pretty solid if you don't mind using NUnit 2.5.7. Support for other versions of NUnit (and xUnit, R#, TD.Net) are things I'd like to do, when there is time :) www.github.com/fschwiet/dreamnjasmine
    If anyone wants to help with this, hollar.
    (here's hoping code in comments aren't mangled)
    public class AccountTransferTests : NJasmineFixture
    {
    public override Tests()
    {
    describe("when a transfer is made", delegate
    {
    var fromAccount = new Account {Balance = 1m};
    var toAccount = new Account {Balance = 1m};
    beforeEach(delegate
    {
    fromAccount.Transfer(1m, toAccount);
    });
    it("should debit from account by the amount transferred", delegate
    {
    fromAccount.Balance.ShouldEqual(0m);
    };

    it("should credit the to account by the amount transferred", delegate
    {
    toAccount.Balance.ShouldEqual(2m);
    };
    }
    }
    }

  55. Avatar for ComeDownFromTheTower
    ComeDownFromTheTower October 29th, 2011

    I came here looking for some BDD guidance. Ironically, I found Scott. Scott is the type of developer I have encountered in the higher levels of development. While he blesses us with his long descent from up-high, when he arrives in our lower-reaches, we learn nothing but: you are not enlightened, you are not ready, you still have much to learn from the master. These people tend to be the roadblocks on projects I work on. You can't work with them.
    Now maybe I can go and find some useful BDD knowledge?

  56. Avatar for Nithya
    Nithya April 5th, 2013

    Hi, How can i download this smole specification and latest version of subspec dll?
    Pls helpme