5
votes

I am a complete newbie to BDD and I would like to understand where does it come into play in a development cycle. In TDD approaches, we would write unit-tests commonly for libraries or apis, we would mock objects and that was great because it could even drive our design. These tests would be written before the actual code which is nice.

I understand that BDD is more about spec/scenario testing and I can see that it is a perfect fit to test a business requirement against the actual code. But what is the best practice for writing these tests? Do we still keep writing individual tests (as in TDD) mocking out dependencies and writing unit-tests for every single thing that could go wrong? Then write our bdd tests? Do we write the bdd tests first? Do we write only bdd tests even against individual components?

I use .NET and usually write asp.net mvc apps but this is more of a theory question and independent of the underlying programming language.

Thanks a lot.

3

3 Answers

6
votes

Don't know about the right way but this is my experience. After analyzing the specification document I try to extract as many different 'stories' and describe them using BDD stories files. As you already know every sentence should start with either one of three keywords given, when and then.

After translating the whole specification to BDD test stories I write a class that implement steps i.e. execute each one of sentences used in stories.

Next step is starting writing an implementation which will be called by methods that execute script sentences by setting initial state (given), state transitions (when) and checking the destination state of the app (then).

Whenever I need to implement an actual class method I use TDD to do a thorough testing in isolation.

Of course, in order to run the test part of the code that is not yet implemented may be temporarily mocked.

1
votes

BDD is a set of patterns around describing and building models of the behaviour of a system (and, at a higher level, a project vision) which can help us to have conversations about that behaviour, for various levels of granularity.

We use conversational patterns like "Given a context, when this event happens then this outcome should occur", and encourage questions like, "Should it? Always? Are there any other contexts we're missing?"

We can do that at a unit level, a scenario level or even into the analysis space.

I tend to work from the highest level inwards. Here's an article I wrote which describes what that looks like, right the way from project vision to unit tests.

The first bit of code I write will be the scenarios. Here are some scenarios written without any BDD frameworks, just plain old NUnit, showing how you can make these English-readable with domain language, etc.

Then I start with the User Interface. This could be a GUI, web-page, or an interface for another system to use my system. When this is done I can get feedback on whether my users like it. I frequently hard-code data, etc., just so that I can get that feedback.

Once I know roughly what my GUI will look like, I can start creating the behaviour behind it. I usually start with the behaviour of the controller. I will write class-level examples which describe the class's behaviour and responsibilities. I use mocks in place of collaborating classes I haven't written yet. This is the equivalent of TDD, but rather than writing tests which pin the code down so that nobody breaks it, I'm writing examples of how you can use my code, which show how it behaves and why it's valuable so that you can change it safely. I also use Given / When / Then for this! But I tend to use more technical language and don't worry about it being English-readable. Frequently my Given / When / Then are just in comments. Here's an example of class behaviour from the same codebase as the scenarios, so you can see what the difference is.

Hope this helps, and good luck with the BDD!

0
votes

You can use it similarly as TDD, unit testing or otherwise. The difference is gonna come from testing "Business Behavior". Spec Flow and Features is one option, unit testing syntax would look something like this

[Given(@"a user exists with username ""(.*)"" and password ""(.*)""")]
public void GivenAUserExistsWithUsernameAdminAndPasswordPassword(string userName, string password) {

}

[Then(@"that user should be able to login using ""(.*)"" and ""(.*)""")]
public void ThenThatUserShouldBeAbleToLoginUsingAdminAndPassword(string userName, string password) {
        Assert.IsTrue(_authService.IsValidLogin(userName, password));
    }