In this chapter, we will cover:
doctest
documentsdoctest
doctest
Behavior Driven Development (BDD) was created as a response to Test Driven Development (TDD) by Dan North. It focuses on writing automated tests in a natural language that non-programmers can read.
Programmers wanted to know where to start, what to test and what not to test, how much to test in one go, what to call their tests, and how to understand why a test fails.
The deeper I got into TDD, the more I felt that my own journey had been less of a wax-on, wax-off process of gradual mastery than a series of blind alleys. I remember thinking, 'If only someone had told me that!' far more often than I thought, 'Wow, a door has opened.' I decided it must be possible to present TDD in a way that gets straight to the good stuff and avoids all the pitfalls—Dan North.
To discover more about Dan North please visit: http://blog.dannorth.net/introducing-bdd.
The tests that we have written in prior unittest recipes had a style of testThis
and testThat
. BDD takes the approach of getting out of speaking programmer-ese and instead shifting to a more customer-oriented perspective.
Dan North goes on to point out how Chris Stevenson wrote a specialized test runner for Java's JUnit that printed test results in a different way. Let's take a look at the following test code:
public class FooTest extends TestCase { public void testIsASingleton() {} public void testAReallyLongNameIsAGoodThing() {} }
This code when run through AgileDox (http://agiledox.sourceforge.net/) will print out in the following format:
Foo - is a singleton - a really long name is a good thing
AgileDox does several things:
Test
droppedtest
prefix from each test methodAgileDox is a Java tool, so we won't be exploring it in this chapter. But there are many Python tools available, and we will look at some including doctest, voidspace mock, mockito, and Lettuce. All of these tools give us the means to write tests in a more natural language and empower customers, QA, and test teams to develop story-based tests.
For this chapter, let's use the same shopping cart application for each recipe. Create a file called cart.py
and add the following code.
class ShoppingCart(object): def __init__(self): self.items = [] def add(self, item, price): for cart_item in self.items: # Since we found the item, we increment # instead of append if cart_item.item == item: cart_item.q += 1 return self # If we didn't find, then we append self.items.append(Item(item, price)) return self def item(self, index): return self.items[index-1].item def price(self, index): return self.items[index-1].price * self.items[index-1].q def total(self, sales_tax): sum_price = sum([item.price*item.q for item in self.items]) return sum_price*(1.0 + sales_tax/100.0) def __len__(self): return sum([item.q for item in self.items]) class Item(object): def __init__(self, item, price, q=1): self.item = item self.price = price self.q = q
This shopping cart:
1
] not [0
]This application isn't complex. Instead, it provides us opportunities throughout this chapter to test various customer stories and scenarios that aren't necessarily confined to simple unit testing.
18.227.134.154