When you are working for the company where every single mistake you make can cost the company hundreds, thousands or even a millions of euros or dollars then your process of developing applications for those companies must be test driven. This is especially important in the companies that have poor deployment automation process, where QA is done manually or even not existing and in companies that have huge project that are consisting of many smaller project and the fact that your small project is working doesn’t mean that the whole project is also bug-free.
But there is also one more problem that can cost companies money. Developers often make mistakes because they misunderstand the business requirements and these “bugs” don’t get discovered until software is in production and reworking and re-deploying it with correct requirements can be very costly and time consuming process.
This is where Behavior Driven Development or BDD comes into play.
What is BDD?
BDD is neither Test Driven Development (TDD) nor Acceptance Test Driven Development (ATDD), but it’s a combination of those two. You can even say that it brings those two together. But it’s also a powerful approach that can remove miscommunication between developers and customers. It uses an common vocabulary (also referred to as a Ubiquitous Language). It’s very much compliant with agile-driven development process. BDD main “mantra” is not to find problems in code, but to prevent them.
Let’s see an example of one Behavior driven test.
Feature: Pay with Credit Card As a User I want to be able to pay with valid credit card Scenario: Successful payment with valid credit card Given User is on credit card payment page When User enters valid credit card number And User enters valid expiration date And User enters valid CVV number And User submits the form Then User should be charged the amount of product from credit card And User should be returned to successful payment page
As you can see with this approach there is a clear path to every feature and ambiguity is lost. This feature can be extended even more. For example let’s say that credit card number field has to first be validated by our own CreditCardValidation class.
So here is the scenario
Scenario: Refuse credit card if user enters invalid number Given User is on credit card payment page When User enters credit card number "4111 1111 1111 1112" Then validation should fail with message "Credit card number is wrong"
And here is implementation
use Behat\Behat\Context\Context; class CreditCardContext implements Context { private $session; private $creditCard; public function __construct() { $this->session = new \Behat\Mink\Session(new GoutteDriver()); $this->session->start(); $this->creditCard = new CreditCard(); } /** @Given User is on credit card payment page **/ public function userIsOnCreditCardPaymentPage() { $this->session->visit('https://example.com/payment-page'); $currentUrl = $this->session->getCurrentUrl(); $expectedUrl = 'https://example.com/payment-page'; PHPUnit_Framework_Assert::assertEquals($expectedUrl, $currentUrl); } /** @When User enters credit card number :creditCardNumber **/ public function userEntersCreditCardNumber($creditCardNumber) { $this->creditCard->setValue($creditCardNumber); } /** @Then validation should fail with message :message **/ public function validationShouldFailWithMessage($message) { $creditCardValidator = new CreditCardValidator(); $response = $creditCardValidator->validate($this->creditCard); PHPUnit_Framework_Assert::assertFalse($response->status); PHPUnit_Framework_Assert::assertEquals($message, $response->message); } }
From this we can conclude that BDD focuses on the behavioral aspect of the system and TDD focuses more on the implementation aspect of the system. You can always combine the two and that is the best approach one developer can do. That way you will always have clear understanding what the system should do using BDD with you customers, but also using TDD you will have clean code that is decoupled and that is well defended from rotting.
0 comments