1

I have done a lot of BDD reading since the beginning of the weekend. At the moment I am reading about the imperative style v the declarative style. The imperative style is often described as an anti pattern like here: http://fasteragile.com/blog/2015/01/19/declarative-user-stories-translate-to-good-cucumber-features/, which says: "Perhaps the easiest way to show a good user story style is by first showing an antipattern. Here is a user story written in an imperative style.". Please consider these scenarios, which are an imperative style:

Given a Person with a gender of male, an age over 18 and age under 21
When I calculate eligibility for loan 
Then eligible for x    

Given a
Person with a gender of male and an age over 21 When I  calculate
eligibility for insurance Then eligible for y

Female scenarios go here.

Here is a declarative style:

Given a Person
When I calculate eligibility for insurance
Then the result should be insurance that the person is eligible for

In all the examples I see that recommend the declarative style; it does not seem to matter what the parameters are. However, in my case above the parameters drive the outcome e.g. a person is eligible for y if they are male and over 21. I guess this is similar to a calculator, which adds numbers.

Therefore I believe the imperative style is more appropriate here. However, I am new to this so wandering what approach is "better" in this specific scenario.

  • 1
    None of those look like good user stories to me. I'm not even sure who the "user" is here - is it the customer, or a customer service person? – Simon B Mar 14 '18 at 9:49
  • @Simon B, it is the customer. Why are they poor scenarios? – w0051977 Mar 14 '18 at 10:24
  • 1
    User stories are normally written from the point-of-view of the user. They describe who the user is, and what they want to do. In the ones above, the customer is "a Person", and "I" seem to be the computer system itself. – Simon B Mar 14 '18 at 18:44
  • 1
    @SimonB Scenarios and user stories aren't the same thing. A user story normally describes who the functionality's for and why it's valuable. A scenario is an example of the user actually using the system. It's frequently the case that there's more than one user, and sometimes more than one person benefiting (think of a person taking cash from the cash machine, and the bank account being debited; it's not for the user's benefit at all). I tend to advise 3rd person if there's more than one stakeholder, but having one in 1st person is fine if it works for you. – Lunivore Mar 16 '18 at 11:27
  • @SimonB Systems as actors is also fine, if something in the system is triggered to do something else... and I've also used "I" or "we" to describe this, especially when doing BDD at a class level. github.com/lunivore/montecarluni/blob/master/src/test/kotlin/… – Lunivore Mar 16 '18 at 11:46
3

Normally when people talk about declarative versus imperative, it's done to avoid overly detailed elements in scenarios which would become hard to maintain.

So for instance, this would definitely be called "imperative":

Given Fred bought a microwave costing £100
And we scanned a 10% discount card
And we scanned his card with number XXXX XXXX XXXX 1234
And we clicked to pay the whole balance with that card
When we scan the receipt  
And click the button "refund"
And click "refund to original card"
Then the card XXXX XXXX XXXX 1234 should get £100 back.

You can see there's a huge amount of detail there! Even if we did this without the clicking of buttons or any other reference to the UI, it would still be too detailed:

Given Fred bought a microwave costing £100
And used a 10% discount card
And he paid with credit card XXXX XXXX XXXX 1234
....

This isn't really the way that anyone would talk about this scenario. Nobody cares about whether the discount was a discount card or a manager-given discount; it doesn't matter. Nobody cares what the number on the card was. Here's the scenario they care about:

Given Fred bought a microwave for £100 with a 10% discount
When he asks for a refund
Then £90 should be refunded to the original card.

It's easy to read and remember and talk about, and it has enough detail in it to be able to see what's going on. Any finer-grained steps can be called from within these larger ones.

Note that this example is still specific, which means it's still able to be parameterized. It doesn't say:

Given a customer bought an item with a discount
When the customer asks for a refund
Then the cost minus the discount should be refunded to the original card.

That's not actually a scenario; that's acceptance criteria in scenario form. It's abstract rather than specific.

Specific vs. abstract is orthogonal to declarative vs. imperative. You want it to be declarative, but specific.

Your first set of scenarios is just fine from that perspective. Your second set is too abstract and not specific enough. Both of them seem declarative to me.

For more information and suggestions on getting this right, see Dan North's original articles on this; "What's in a story?" and "Whose domain is it anyway?"

  • Thanks. +1 for the reference to specific and abstract. I think that this answer nicely complements your answer here: softwareengineering.stackexchange.com/questions/360957/…. I do have one question though about the Honeycomb approach before I accept. In your other answer you say: "BDD started as a replacement" when referring to the Honeycomb video hyperlink. If you use Honeycomb then do you also use TDD at the lower level (domain level) or does Honeycomb mean that you also use BDD at the lower levels? Thanks again. – w0051977 Mar 19 '18 at 9:49
  • @w0051977 I thought you were referring to a piece of software but now I see you're referring to Aslak's Honeycomb pattern! I've edited my answer on your other question that you've linked here, since it's more related to the levels of BDD than it is to declarative vs. imperative - hope it suits. – Lunivore Mar 19 '18 at 15:12
3

To answer your question, you have to ask who expects to see the results of the test. We use it as a form of acceptance testing. BDD is intended to provide a bridge between what your customer asks for and what programmers need to satisfy. Taken the simple statement:

Given a Person
When I calculate eligibility for insurance
Then the result should be insurance that the person is eligible for

The language is very concise and clear. This is something your client can read and understand, and when they see a passing mark for that statement they know what that means. It also works to limit scope creep, since the client isn't inventing new cases that didn't exist before.

The imperative form reads like how a programmer thinks. This is very different from how a business person thinks. Essentially you are writing your application 2 times. Once in a BDD-like structure, and once in code. This doesn't help anyone. It's tedious to read, tedious to write, and confusing to your client. The worst case scenario is that you write your imperative BDD so restrictively that you can't change the structure of your code because your BDD tests are too tightly coupled. Don't do that.

As a programmer, you have to define in the code that maps to the BDD statement insurance that the person is eligible for. Given any insurance product and person combination, that same test can be run to determine the Boolean of whether or not the combination is valid. Applying that to a set of products to make sure all products returned are valid for a person is trivial. In fact, you probably have defined this function in your source code already.

  • If you use Honeycomb then do you also use TDD at the lower level (domain level) or does Honeycomb mean that you also use BDD at the lower levels as well? See here for a description of Honeycomb: skillsmatter.com/skillscasts/…. +1. – w0051977 Mar 19 '18 at 12:49
  • I'm not familiar enough with honeycomb to answer that confidently. Based on the video, at least what I could hear/see, you have 2 modes. The "fast" mode is all your testing (TDD/BDD) has no I/O. The "complete" mode will include the I/O related tests. – Berin Loritsch Mar 19 '18 at 13:50
  • I think you are saying that if you run the fast tests and the slow test then you have unit tests and acceptance tests i.e. you do not need a separate project for the unit tests. Have I understood you correctly? – w0051977 Mar 19 '18 at 14:04
  • You will still have the BDD/TDD for your project. You just divide them between "fast" and "slow. The distinction isn't BDD/TDD, the distinction is I/O bound and not I/O bound. The fast tests are there to give you a good feeling about correctness, and the slow tests are there to really put everything through the ringer. The idea is that while you are developing you need near instant (subsecond) feedback from your tests. You also need to make sure things work well together before you deliver. – Berin Loritsch Mar 19 '18 at 14:23
  • I am trying to establish whether I need two projects (one for acceptance tests and the other for unit tests) or whether one project run in fast mode and slow mode will cover both unit tests and acceptance tests. Does that make sense? – w0051977 Mar 19 '18 at 14:59
1

The point that the article is making relates to the idea that user stories should deal with what the feature is, not how it should be implemented. Thus a story that talks in terms of "and the user clicks enter" etc is a bad story. It's too proscriptive. It should be more declarative, as per the examples in that article, so it focuses on what's needed, not how it's to be implemented.

So in your case, whether your story should talk of a male over 21 being eligible for specified products all depends on where such business rules are defined. If they are hard-coded into the app with the understanding that if the rules change, the app changes, then they are part of the requirements and they should thus form part of that test. So they go in the story and are specifically tested for.

If though, the rules are configurable via eg the database, then they absolutely should not be part of the requirements. In such a case, then the story should indeed talk in terms of "Then the result should be insurance that the person is eligible for".

  • The business logic is in the domain model rather than the database. On that basis I believe you are advocating an imperative style? Is that right? – w0051977 Mar 13 '18 at 20:22
  • @w0051977, no I'm saying that male and 21 etc are no more imperative in this instance than "home page" or "admin" in the article's declarative example. – David Arno Mar 13 '18 at 21:08
  • If you use Honeycomb then do you also use TDD at the lower level (domain level) or does Honeycomb mean that you also use BDD at the lower levels as well? See here for a description of Honeycomb: skillsmatter.com/skillscasts/…. +1. – w0051977 Mar 19 '18 at 12:49
  • @w0051977, sorry, I have no idea. I've no experience of Honeycomb. – David Arno Mar 19 '18 at 13:15

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.