Introduction to TDD and BDD using python
Thu March 31 2016
John Roa
Full Stack Developer and Tech Lead
Associate.io
TDD
(Test Driven Deveopment)
"approach to development which combines test-first development where you write a test before you write just enough production code to fulfill that test and refactoring.
“The act of writing a unit test is more an act of design than of verification. It is also more an act of documentation than of verification. The act of writing a unit test closes a remarkable number of feedback loops, the least of which is the one pertaining to verification of function” - Robert C. Martin
Traditional software process
Design
Implement
Test
Traditional software process
Issues
- Long phase execution
- Manual testing
- Lost or regression bugs
- The bigger the codebase the longer the time to test and more probability to break things
TDD Flow
Test / Design
Implement
Benefits
- Much less regression test bugs
- Drastically reduced time to identify issues
- Easy refactoring verification.
- Better software design.
Python testing tools
Unittest
Doctest
py.test
Nose
Tox
Unittest2
Mock
Lets see some code
import unittest
from operations.operations import factorial, summation
class TddInPythonExample(unittest.TestCase):
def test_factorial_operation_returns_correct_result(self):
result = factorial(2)
self.assertEqual(2, result)
def test_summation_operation_returns_correct_result(self):
result = summation(2)
self.assertEqual(3, result)
test_operations.py
# coding=utf-8
def factorial(number):
return 0
def summation(number):
return 0
operations.py
/usr/bin/python /Applications/PyCharm.app/Contents/helpers/pydev/pydevd.py --multiproc
--qt-support --client 127.0.0.1 --port 64753 --file /Applications/PyCharm.app/Contents
/helpers/pycharm/utrunner.py /Users/jhonjairoscalablepath/PycharmProjects/
python-lettuce-sample-2/tests/test_operations.py::TddInPythonExample::
test_summation_operation_returns_correct_result true
Testing started at 4:42 PM ...
pydev debugger: process 55353 is connecting
Connected to pydev debugger (build 143.1919)
Failure
Traceback (most recent call last):
File "/Users/jhonjairoscalablepath/PycharmProjects/python-lettuce-sample-2/tests
/test_operations.py", line 13, in test_summation_operation_returns_correct_result
self.assertEqual(3, result)
AssertionError: 3 != 0
Process finished with exit code 0
Test fail !!! :(
Don't be sad!
Now you have things to do :D
operations.py
# coding=utf-8
def factorial(number):
number = int(number)
if (number == 0) or (number == 1):
return 1
else:
return number*factorial(number-1)
def summation(number):
number = int(number)
if number == 0:
return 0
else:
return number+summation(number-1)
/usr/bin/python /Applications/PyCharm.app/Contents/helpers/pydev/pydevd.py --multiproc
--qt-support --client 127.0.0.1 --port 64816 --file /Applications/PyCharm.app/
Contents/helpers/pycharm/utrunner.py /Users/jhonjairoscalablepath/PycharmProjects/
python-lettuce-sample-2/tests/test_operations.py::TddInPythonExample::
test_summation_operation_returns_correct_result true
Testing started at 4:45 PM ...
pydev debugger: process 55376 is connecting
Connected to pydev debugger (build 143.1919)
Process finished with exit code 0
Test pass !!! :'D
Source code
ATDD
(Acceptance Test Driven Development)
is a communication tool between the customer, developer, and tester to ensure that the requirements are well-defined
"Customer"
or
Product Owner
Tester
Developer
requirements written as acceptance tests
focus on writing acceptance tests before developers begin coding
"the product owner, customer or domain expert is able to specify new functionality by writing new acceptance tests or test cases, without needing to consult developers"
BDD
(Behavior Driven Deveopment)
"is a process designed to aid the management and the delivery of software development projects by improving communication between engineers and business professionals."
BDD: Two parts
- using examples written in ubiquitous language to illustrate behaviors (how users will interact with the product).
- Using those examples as the basis of automated tests.
- Checking functionality for the user.
- Ensures the system works as defined by the business.
"tests of any unit of software should be specified in terms of the desired behavior of the unit"
"business analysts and developers should collaborate in this area and should specify behavior in terms of user stories"
Traditional development process
1. Chris tells a business analyst how he would like the feature to work.
2. The business analyst translates Chris’s requests into a set of requirements for the developers, describing what the software should do. These requirements are written in English and stored in a Microsoft Word document.
3. The developer translates the requirements into code and unit tests—written in Java, C#, or some other programming language—in order to implement the new feature.
Traditional development process
4. The tester translates the requirements in the Word document into test cases, and uses them to verify that the new feature meets the requirements.
5. Documentation engineers then translate the working software and code back into plain English technical and functional documentation.
Doing BDD...
How do I do that?
Writing stories
'Each feature is captured as a “story”, which defines the scope of the feature along with its acceptance criteria'
Title (one line describing the story)
Narrative:
As a [role]
I want [feature]
So that [benefit]
Acceptance Criteria: (presented as Scenarios)
Scenario 1: Title
Given [context]
And [some more context]...
When [event]
Then [outcome]
And [another outcome]...
Scenario 2: ...
Gherkin language
"lets you describe software’s behavior without detailing how is implemented."
Gherkin language purposes
- Documentation
- Automated tests.
Gherkin language source file
1: Feature: Some terse yet descriptive text of what is desired
2: Textual description of the business value of this feature
3: Business rules that govern the scope of the feature
4: Any additional information that will make the feature easier to understand
5:
6: Scenario: Some determinable business situation
7: Given some precondition
8: And some other precondition
9: When some action by the actor
10: And some other action
11: And yet another action
12: Then some testable outcome is achieved
13: And something else we can check happens too
14:
15: Scenario: A different situation
16: ...
Example: Gherkin language source file
Story: Account Holder withdraws cash
As an Account Holder
I want to withdraw cash from an ATM
So that I can get money when the bank is closed
Scenario 1: Account has sufficient funds
Given the account balance is \$100
And the card is valid
And the machine contains enough money
When the Account Holder requests \$20
Then the ATM should dispense \$20
And the account balance should be \$80
And the card should be returned
Scenario 2: Account has insufficient funds
Given the account balance is \$10
And the card is valid
And the machine contains enough money
When the Account Holder requests \$20
Then the ATM should not dispense any money
And the ATM should say there are insufficient funds
And the account balance should be \$20
And the card should be returned
...
Example: Gherkin language source file
Story: Account Holder withdraws cash
As an Account Holder
I want to withdraw cash from an ATM
So that I can get money when the bank is closed
....
Scenario 3: Card has been disabled
Given the card is disabled
When the Account Holder requests \$20
Then the ATM should retain the card
And the ATM should say the card has been retained
Scenario 4: The ATM has insufficient funds
...
'Behaviour-driven development is an “outside-in” methodology. It starts at the outside by identifying business outcomes, and then drills down into the feature set that will achieve those outcomes.'
BDD: Activities and outcomes
"Executable specifications are about communication as much as they are about validation"
don’t write unit tests, write low-level specifications
Unittest
Doctest
py.test
Nose
Tox
Unittest2
Mock
steps.py
transfer.feature
Benefits
MUCH BETTER COMMUNICATION WITH BUSINESS PEOPLE!!!
- Reduced waste
- Reduced costs
- Easier and safer changes
- Faster releases
Challenges
- High bussiness engagement
- BDD works best in agile contexts
- Poorly written tests can lead to higher test-maintenance costs
Python BDD tools
Lettuce
Behave
Let's see some code...
Project structure
factorial.feature
Feature: Compute factorial
In order to play with Lettuce
As beginners
We'll implement factorial
Scenario: Factorial of 0
Given I have the number 0
When I compute its factorial
Then I see the number 1
Scenario: Factorial of 1
Given I have the number 1
When I compute its factorial
Then I see the number 1
Scenario: Factorial of 2
Given I have the number 2
When I compute its factorial
Then I see the number 2
Scenario: Factorial of 3
Given I have the number 3
When I compute its factorial
Then I see the number 6
Scenario: Factorial of 4
Given I have the number 4
When I compute its factorial
Then I see the number 24
steps.py
# coding=utf-8
from lettuce import world, step
from operations.operations import factorial, summation
@step('I have the number (\d+)')
def have_the_number(step, number):
world.number = int(number)
@step('I compute its factorial')
def compute_its_factorial(step):
world.number = factorial(world.number)
@step('I compute its summation')
def compute_its_factorial(step):
world.number = summation(world.number)
@step('I see the number (\d+)')
def check_number(step, expected):
expected = int(expected)
assert world.number == expected, \
"Got %d" % world.number
operations.py
# coding=utf-8
def factorial(number):
number = int(number)
if (number == 0) or (number == 1):
return 1
else:
return number*factorial(number-1)
def summation(number):
number = int(number)
if number == 0:
return 0
else:
return number+summation(number-1)
Source code
TDD vs BDD
TDD
Product Owner
Tester
Developer
TDD
"We have a coverage of 95% of the code!!!"
Emmm ok, cool.
BDD
Product Owner
Tester
Developer
BDD
"We have completed 95% of the features!!!"
THAT'S AWESOME!!!!!
Yes, I can notice that.
"Not only test your code at the granular level with unit tests, but also test your application end to end, using acceptance tests"
TDD
"the unit tests of a class"
"the specifications of the behavior of the class"
BDD
TDD
"focussed on developers and testers"
"focused on customer"
BDD
TDD
"focussed on implementation"
"focused on behavior"
BDD
TDD
"test code blocks"
"test what customer expects from the platform"
BDD
Resources
More resources
http://inviqa.com/insights/bdd-guide
http://dannorth.net/introducing-bdd/
http://dannorth.net/whats-in-a-story/
http://pythonhosted.org/behave/philosophy.html
BDD Testing a Restful Web Application in Python
http://www.slideshare.net/Siddhi/test-driven-development-with-python
http://chrismdp.com/2013/01/bdd-is-not-cucumber/
http://lizkeogh.com/2015/12/14/bdd-a-three-headed-monster/
https://www.toptal.com/freelance/your-boss-won-t-appreciate-tdd-try-bdd
Thanks!!!
Q & A
Introduction to TDD and BDD using python
By Jhon Jairo Roa
Introduction to TDD and BDD using python
Review of TDD and BDD main characteristics , how do they get along and how they are implemented in python
- 4,027