pea is a minimal BDD framework for python, in the style of ruby's cucumber and python's lettuce. It aims to help you write the same kind of tests - but in straight-up python code, without all the parsing and indirection and other hoops to jump through. It's a lot like ruby's coulda.
Benefits of cucumber-style testing include:
- You write your tests in clear, english language without inline code
- Your tests are human-readable, and hopefully human-editable
- You can re-use steps with confidence, because they all do exactly what they say on the tin
Benefits of pea
over lettuce
, cucumber
, etc:
- It's a really trivial library (thus the name). It doesn't do very much, so it probably doesn't have many bugs
- Your features are just python code:
- No "BDD language parser" needed
- No regular expressions
- Stack traces make sense
- Syntax highlighting
- You can use ctags to jump between test & implementation, as well as for method completion
- Managing and renaming functions is much easier than managing regexes
- You can use whatever abstractions you like
- You can use rich python objects as arguments, instead of parsing strings
- It doesn't need its own test runner; so you can just use nose to run it alongside your unit tests
Here's a minimal example:
from pea import * @step def I_go_to_the_store(): world.location='store' world.cart = [] @step def I_buy_some(item): world.cart.append(item) @step def I_go_home(): world.location = 'home' @step def I_have_some_delicious(item): assert item in world.cart world.assertEquals(world.location, 'home') # -------------------- class TestShopping(TestCase): def test_buying_some_peas(self): Given.I_go_to_the_store() When.I_buy_some('peas') And.I_go_home() Then.I_have_some_delicious('peas')
... and when you run it (with nosetests, in verbose mode):
Typically you would put your steps in a separate python module (or many), but it's your choice.
@step
adds your function to pea's registry of steps, which allows them to be called viaGiven
,When
,And
, andThen
.- To re-use a step from inside another step, just call the function!
- Make sure you inherit from
pea.TestCase
(and callsuper
fromsetUp
/tearDown
), as it takes care of resetting theworld
between tests. - You can use
TestCase
assertion methods on the world, too - e.g.world.assertEquals(expected, actual)
Pea works well with rednose