for "Behavior Driven Development" (BDD) -- a client-facing scripting language to put the squeeze on all your features
Project description
Morelia viridis is a Python Behavior Driven Development platform, conceptually derived from Ruby’s Cucumber Framework.
It is available both at the cheeseshop and GitHub.
Mascot:
Install it with:
sudo pip install Morelia
To use it, first write a project.feature file, in ordinary prose, like this:
Feature: Addition
In order to avoid silly mistakes
As a math idiot
I want to be told the sum of two numbers
Scenario: Add two numbers
Given I have entered 50 into the calculator
And I have entered 70 into the calculator
When I press add
Then the result should be 120 on the screen
Note that “In order”, “As a”, and “I want” are not Morelia keywords. They are part of Feature’s “predicate”; its text payload.
“Given”, “And”, “When” and “Then” are keywords. The words following them are executable test specifications.
Now create a standard PythonUnit test suite, like this:
class MoreliaTest(TestCase):
def setUp(self):
self.stack = []
def step_I_have_entered_a_number_into_the_calculator(self, number):
r'I have entered (\d+) into the calculator'
self.stack.append(int(number))
def step_I_press_add(self): # matched by method name
self.result = sum(self.stack)
def step_the_result_should_be_on_the_screen(self, number):
"the result should be (\d+) on the screen"
assert int(number) == self.result
Note that Morelia does not waste anyone’s time inventing a new testing back-end just to add a layer of literacy over our testage. Steps are miniature TestCases. Your onsite customer need never know, and your unit tests and customer tests can share their support methods. The same one test button can run all TDD and BDD tests.
Next, note that Morelia matches Steps in your Feature file to either the names or doc-strings of step_ methods in your test case. And it expands regular expressions, such as (d+), into step arguments, such as number. Remember to use tight expressions, such as (d+), not loosey-goose expressions like (d*) or (.*), to validate your input.
When you run your TestCase, hook into all your feature files, like this:
def test_evaluate_file(self):
from morelia import Parser
Parser().parse_file('tests/morelia.feature').evaluate(self)
The passing steps will appear as passing test cases in your test run.
And note that Morelia calls setUp() and tearDown() around your Scenario. Each step calls within one TestCase, so self can store variables between each step.
Tables
To DRY up a series of redundant scenarios, varying by only “payload” variables, roll the Scenarios up into a table, using <angles> around the payload variable names:
Scenario: orders above $100.00 to the continental US get free ground shipping
When we send an order totaling $<total>, with a 12345 SKU, to our warehouse
And the order will ship to <destination>
Then the ground shipping cost is $<cost>
And <rapid> delivery might be available
| total | destination | cost | rapid |
| 98.00 | Rhode Island | 8.25 | yes |
| 101.00 | Rhode Island | 0.00 | yes |
| 99.00 | Kansas | 8.25 | yes |
| 101.00 | Kansas | 0.00 | yes |
| 99.00 | Hawaii | 8.25 | yes |
| 101.00 | Hawaii | 8.25 | yes |
| 101.00 | Alaska | 8.25 | yes |
| 99.00 | Ontario, Canada | 40.00 | no |
| 99.00 | Brisbane, Australia | 55.00 | no |
| 99.00 | London, United Kingdom | 55.00 | no |
| 99.00 | Kuantan, Malaysia | 55.00 | no |
| 101.00 | Tierra del Fuego | 55.00 | no |
That Scenario will unroll into a series of scenarios, each with one value from the table inserted into their placeholders <total>, <destination>, and <rapid>. So this step method will receive each line in the “destination” column:
def step_the_order_will_ship_to_(self, location):
r'the order will ship to (.*)'
(And observe that naming the placeholder the same as the method argument is a reeeally good idea, but naturally unenforceable.)
MV will take each line of the table, and construct a complete test case out of the Scenario steps, running setUp() and tearDown() around them.
When
The other step keywords (Given, And, Then, etc.) are cosmetic, to permit good grammar. They are all aliases for Step. The committee may eventually find specific uses for them.
The When keyword, however, is special. When a Scenario contains more than one When, Morelia splits it up into one Scenario for each When block, and runs each one separately. So the following two Feature details are equivalent…
Scenario: Split When Blocks
Given some setup
And some condition
When a first trigger occurs
Then something good happens
Scenario: Split When Blocks again
Given some setup
And some condition
When another trigger occurs
Then something else happens
…and…
Scenario: Split When Blocks, and again
Given some setup
And some condition
When a first trigger occurs
Then something good happens
When another trigger occurs
Then something else happens
The second version DRYs the setup conditions.
The committee does not yet know what happens if a multi-When Scenario also contains a table, so please don’t rely on whatever the current behavior is!
Here’s another sneaky snake, which might also be a Green Tree Python (a Morelia viridis):
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
File details
Details for the file Morelia-0.2.1.tar.gz
.
File metadata
- Download URL: Morelia-0.2.1.tar.gz
- Upload date:
- Size: 28.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 4064934cb1f5b629f4b73304d7726b30e1ba87e7b1ad56b238d9c1274c2cb9f3 |
|
MD5 | c75e079baa59e907d61021e3c5a5339b |
|
BLAKE2b-256 | 25f9406d65c4cce0f924438fb41492a35ee11d868581b53b0c73d3af9c6ab344 |
File details
Details for the file Morelia-0.2.1-py2.py3-none-any.whl
.
File metadata
- Download URL: Morelia-0.2.1-py2.py3-none-any.whl
- Upload date:
- Size: 29.8 kB
- Tags: Python 2, Python 3
- Uploaded using Trusted Publishing? No
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 65bccef3f5519649a0306a558c35136aad7cecbd66fc9ea045d2603a3e4ce073 |
|
MD5 | f5b4a93a808ec517ecd071460c3395c5 |
|
BLAKE2b-256 | a0b264ca37341c7dd80e93eb4fe4cc8607b4408b5f4120cf10288902a82713e8 |