1

There are TDD automation scripts ready and running. TDD tests are written in granular level(class, functions, module) and BDD is written in Behavior level. Is it feasible convert this TDD script to BDD ? Or the question makes no sense ?

4
  • 1
    Sharing your research helps everyone. Tell us what you've tried and why it didn't meet your needs. This demonstrates that you've taken the time to try to help yourself, it saves us from reiterating obvious answers, and most of all it helps you get a more specific and relevant answer. Also see How to Ask
    – gnat
    Nov 6 '19 at 11:21
  • 1
    Related, but I'm not sure if it qualifies as a duplicate: How to use unit tests when using BDD?. Nov 6 '19 at 12:03
  • Can you post an example of a "TDD" script and what it might look like as a "BDD" script? Nov 6 '19 at 12:47
  • 1
    What problem are you trying to solve by converting those scripts?
    – Doc Brown
    Nov 6 '19 at 12:54
6

In practice, you can´t, because the concepts of TDD and BDD are different. Although both test behavior, when you use TDD you create low-level testing to ensure your methods/function is working as expected. TDD is a tool to support your development process. On the flip side, BDD tests the behavior of the system at a high level through the stories and scenários. They complement each other.

If you have a feature were given a user that adds items into a cart and when he click on the 'Buy with one click' button then items should be shipped, the BDD will test this scenários and the TDD will test the methods of each class that implement it.

3
  • 10
    The difference between TDD and BDD is this. TDD ensures the electrical cord for a toaster can hold the specified amount of electric current. BDD ensures that when you put bread in the toaster and push the lever down you get toast. Nov 6 '19 at 12:03
  • I enjoyed the metaphor @GregBurghardt
    – Edu Costa
    Nov 6 '19 at 12:18
  • In other words. They are not mutually exclusive. If we follow the pyramid test, there's room for both.
    – Laiv
    Nov 6 '19 at 13:52
1

Test Driven Development ensures the low level components are working when isolated from the rest of the system, or it ensures that two different components interact properly (again, when isolated from the rest of the system). Let's take, for example, a unit test that sums the total of all items in a shopping cart:

[TestClass]
public class ShoppingCartTests
{
    [TestMethod]
    public void SumTotalOfItems()
    {
        // Arrange
        var user = new RegisteredUser("Jane", "Doe", "jdoe");
        var shoppingCart = new ShoppingCart(user);
        var hammer = new Product("Hammer", 12.99m);
        var pencils = new Product("No. 2 Pencils", 1.25m);

        // Act
        shoppingCart.AddProduct(hammer);
        shoppingCart.AddProduct(pencils);

        var sumTotal = shoppingCart.CalculateTotal();

        // Assert
        Assert.AreEqual(14.24m, sumTotal);
    }
}

You have a registered user, shopping cart and two products with prices. You add the two products to the shopping cart and get the total, then compare it to the expected total (I'm using C# if it helps).

You could certainly write a BDD scenario for this:

Feature: Shopping Cart
    In order to keep track of products I would like to purchase
    As a registered user
    I want to view information about my shopping cart

Scenario: Sum total of items
    # Arrange
    Given a registered user exists
    And the registered user is shopping
    And a product named "Hammer" exists costing $12.99
    And a product named "No. 2 Pencils" exists costing $1.25

    # Act
    When they add the following products to their shopping cart:
        | Product       |
        | Hammer        |
        | No. 2 Pencils |

    # Assert
    Then the sum total of their shopping cart should be $14.24

This reads very nicely. You could even send this to an end user and they would be able to follow this just fine. But now let's look at the implementation of this test (using SpecFlow and MSTest):

Steps for registered users

[Binding]
public class RegisteredUserSteps
{
    private readonly ScenarioContext scenario;

    public RegisteredUserSteps(ScenarioContext scenario)
    {
        this.scenario = scenario;
    }

    [Given(@"a registered user exists")]
    public void GivenIsAUserRegisteredAs()
    {
        scenario["user"] = RegisteredUser("Jane", "Doe", "jdoe");
    }
}

Steps for products

[Binding]
public class ProductSteps
{
    private readonly ScenarioContext scenario;

    public ProductSteps(ScenarioContext scenario)
    {
        this.scenario = scenario;
    }

    [Given(@"a producted named ""(.*)"" exists costing \$(\d+\.\d{2})")]
    public void AProductNamedExistsCosting(string name, decimal price)
    {
        scenario["Product." + name] = new Product(name, price);
    }
}

Steps for shopping carts

[Binding]
public class ShoppingCartSteps
{
    private readonly ScenarioContext scenario;

    public ShoppingCartSteps(ScenarioContext scenario)
    {
        this.scenario = scenario;
    }

    [Given(@"the registered user is shopping")]
    public void GivenTheRegisteredUserIsShopping(string name)
    {
        var user = (RegisteredUser)scenario["user"];
        scenario["shoppingCart"] = new ShoppingCart(user);
    }

    [When(@"they add the following products to their shopping cart:")]
    public void WhenTheyAddTheFollowingProductsToTheirShoppingCart(Table table)
    {
        var shoppingCart = (ShoppingCart)scenario["shoppingCart"];

        foreach (var row in table.Rows)
        {
            var product = (Product)scenario["Product." + row["Product"]];

            shoppingCart.AddProduct(product);
        }
    }

    [Then(@"the sum total of their shopping cart should be \$(\d+\.\d{2})")]
    public TheSumTotalOfTheirShoppingCartShouldBe(decimal expectedTotal)
    {
        var shoppingCart = (ShoppingCart)scenario["shoppingCart"];
        var actualTotal = shoppingCart.CalculateTotal();

        Assert.AreEqual(expectedTotal, actualTotal);
    }
}

Ick! I wouldn't want to maintain this as a developer. The extra mental burden of mapping steps to step definitions, and then sharing data between steps outweighs the benefit you gain from writing this test as a behavioral test. It is much easier to read as a plain old unit test.

Can you convert "TDD" tests to "BDD" tests? Most likely the answer is "Yes". Should you? No. It is too cumbersome to maintain as a developer. This is why most BDD tests are also full integration tests. When testing all components together in an isolated system (as opposed to all components isolated from the system) then the cost of maintaining these step definitions and additional levels of indirection is worth the benefit you get from behavior driven tests.

3
  • BDD and TDD complement each other. BDD: Building the right thing, TDD: Building the thing right. Just because we can correlate "behavior" more easily with BDD doesn't mean our unit test shouldn't test behavior too. After all, why are we using OOP and DDD if not to make our code speak a ubiquitous language? Kent Beck said: Tests should be coupled to the behavior of code and decoupled from the structure of code. Uncle Bob said: Remember, you don’t test code, you test application behavior. Nov 14 '19 at 16:37
  • You said: "The extra mental burden...outweighs the benefit.." that can be resolved by refactoring your step definitions code. An example of such a refactor can be towards creating a "support code" with the extra benefit that you can have multiple implementations of the "wolrd" you test against. ... continued in next comment... Nov 14 '19 at 16:55
  • that way your step definition code is not only more easy to read and maintain but gives you the benefit of being able to have your tests exercise the system at a subcutaneous level (by running against your DDD model) and another implementation of the abstracted support code that works as integration tests by exercising the system at UI level. Find more about this approach in chapter 8 of this book pragprog.com/book/hwcuc2/the-cucumber-book-second-edition (there is a version for java and another version for ruby) I found the java one very useful since I work with C# and Specflow Nov 14 '19 at 16:56

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.