Commit ccef2eb5 by Gabriel Falcão

Merge pull request #225 from benoitbryon/doc-dev

Doc dev
parents e26559ff 30cb6319
.. _contents:
==============================
##############################
Lettuce documentation contents
==============================
##############################
.. toctree::
:maxdepth: 3
......@@ -24,8 +24,9 @@ Lettuce documentation contents
recipes/django-lxml
dev/index
****************************
Indices, glossary and tables
============================
****************************
* :ref:`genindex`
* :ref:`modindex`
......@@ -101,29 +101,67 @@ On pages which are quite long, use links and references footnotes with the
This :doc:`documentation` page uses this syntax.
*******
Recipes
*******
**************
Install Sphinx
==============
**************
`Python-sphinx`_ installation is covered in :doc:`/dev/install`.
In other cases, please refer to `Python-sphinx`_ documentation.
****************************
Export documentation to HTML
============================
****************************
.. highlight:: sh
* Install `Python-sphinx`_.
* Make sure sphinx-build is in your shell's $PATH. If you are using virtualenv
as told in :doc:`/dev/install`, then **activate your virtual environment**.
* Go to lettuce folder and use the provided Makefile:
.. highlight:: sh
::
make documentation
* HTML documentation is exported to docs/_build/html/.
*************
Use doctests!
*************
This documentation uses the `Sphinx's doctest extension`_.
Write doctests
==============
Here is a RST code sample to write doctests. You can find some doctests in
:doc:`/reference/terrain`.
.. highlight:: rst
::
cd docs/
make html
cd ..
.. highlight:: python
.. doctest::
>>> print "Hello world!"
Hello world!
See `Sphinx's doctest extension`_ and `Python's doctest`_ documentations for
details.
Run doctests
============
Go to lettuce folder and use the provided Makefile:
.. highlight:: sh
::
HTML documentation is exported to docs/_build/html/.
make doctests
**********
References
......@@ -133,3 +171,5 @@ References
.. _`Python-sphinx`: http://sphinx.pocoo.org/
.. _`reStructuredText`: http://docutils.sourceforge.net/rst.html
.. _`Sphinx's doctest extension`: http://sphinx.pocoo.org/ext/doctest.html#module-sphinx.ext.doctest
.. _`Python's doctest`: http://docs.python.org/library/doctest.html
......@@ -2,8 +2,9 @@
Development guidelines
######################
********
Synopsis
========
********
1. fork and clone the project: see `lettuce repository at github.com`_
2. :doc:`/dev/install`
......@@ -12,8 +13,9 @@ Synopsis
5. commit, push, etc...
6. send a pull request
*****************
Table of contents
=================
*****************
.. toctree::
:maxdepth: 3
......@@ -22,8 +24,9 @@ Table of contents
testing
documentation
************
Keep in mind
============
************
.. image:: http://farm3.static.flickr.com/2248/2282734669_a7f431e660_o.jpg
:alt: your lack of tests if disturbing the force
......@@ -31,8 +34,9 @@ Keep in mind
**that lettuce is a testing software, patches and pull requests must come with
automated tests, and if suitable, with proper documentation.**
**********
References
==========
**********
.. target-notes::
......
......@@ -5,8 +5,9 @@ Installation on Debian Squeeze
Recipe to get a development environment for lettuce in a fresh install of
Debian Squeeze.
*********
Variables
=========
*********
The following values are used below. You may customize them depending on your
needs.
......@@ -25,8 +26,9 @@ needs.
# System's package manager.
system-install() { su -c "aptitude install ${*}" }
***************************
Install system dependencies
===========================
***************************
Execute the following commands:
......@@ -36,8 +38,9 @@ Execute the following commands:
system-install python-dev python-virtualenv git libxml2-dev libxslt-dev
***********
Get sources
===========
***********
.. highlight:: bash
......@@ -48,8 +51,9 @@ Get sources
cd $lettuce_dir
git remote add upstream $upstream_url
*****************
Create virtualenv
=================
*****************
.. highlight:: bash
......@@ -60,8 +64,9 @@ Create virtualenv
cd $lettuce_dir
pip install -r requirements.txt
*******************************
Install lettuce in develop mode
===============================
*******************************
.. highlight:: bash
......@@ -69,8 +74,9 @@ Install lettuce in develop mode
python setup.py develop
******************
Check installation
==================
******************
You should be able to run lettuce and tests.
......@@ -80,7 +86,8 @@ You should be able to run lettuce and tests.
lettuce --help
*****
Done!
=====
*****
Go back to :doc:`/dev/index` and learn about :doc:`/dev/testing`.
.. _glossary:
========
########
Glossary
========
########
.. glossary::
......@@ -78,4 +78,4 @@ Glossary
See :ref:`topics-templates`.
view
A function responsible for rending a page.
\ No newline at end of file
A function responsible for rending a page.
.. _index:
.. rubric:: All you need to know, from leaves to root
########
nutshell
========
########
**install it**
......@@ -56,8 +57,9 @@ nutshell
user@machine:~/Projects/my-project$ lettuce features/
##################
getting involved !
==================
##################
**github project page**
......@@ -83,15 +85,17 @@ Fork it, propose features, explore the code
`support lettuce development <http://pledgie.com/campaigns/10604>`_
#########
hands on!
=========
#########
Is this your first experience with Lettuce ?!?
So, why don't you go straight to the :ref:`quick start tutorial <tutorial-simple>` ?!
############
introduction
============
############
**what is Lettuce, and what it does**
......@@ -99,12 +103,13 @@ introduction
* :ref:`installation <intro-install>`
what the feature ?!
-------------------
*******************
* :ref:`understand the terms behind Lettuce <intro-wtf>`
###########
walkthrough
===========
###########
* :ref:`write your first feature <tutorial-simple>`
* :ref:`handling data with tables <tutorial-tables>`
......@@ -112,13 +117,15 @@ walkthrough
* :ref:`don't repeat yourself, meet scenario outlines <tutorial-scenario-outlines>`
* :ref:`clean up your spec definitions, calling one step from another <tutorial-steps-from-step-definitions>`
##########
integrate!
==========
##########
* :ref:`Lettuce and Django <recipes-django-lxml>`, for the sake of web development fun
###########
furthermore
===========
###########
**reference and concepts**
......@@ -127,8 +134,9 @@ furthermore
* :ref:`terrain, world and hooks <reference-terrain>`, stuff about setting up a environment for lettuce
* :ref:`language support <reference-languages>`
#######
recipes
=======
#######
**make your own salad**
......
.. _intro-install:
==================
##################
Installing Lettuce
==================
##################
**************
Stable release
==============
**************
You can install the latest stable release with pip
......@@ -15,9 +16,9 @@ You can install the latest stable release with pip
user@machine:~$ [sudo] pip install lettuce
****************************
Using control version's HEAD
============================
****************************
Otherwise, if you're a more adventurous developer, you can use the
bleeding edge version of Lettuce by taking the git HEAD
......@@ -25,7 +26,7 @@ bleeding edge version of Lettuce by taking the git HEAD
If you want so, you have basically 2 options:
Build and install the egg from sources
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
======================================
Good for those that just want to use the latest features
......@@ -36,7 +37,7 @@ Good for those that just want to use the latest features
user@machine:~/Downloads/lettuce$ sudo python setup.py install
Use the latest code to contribute with lettuce's codebase
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
=========================================================
If it is your case, I strongly recommend a sandbox:
......
.. _intro-overview:
========
########
Overview
========
########
******
On BDD
======
******
Behaviour-driven development is a very good approach for maintaining
the workflow plain, so you only spend time with what really matters:
......@@ -31,8 +32,9 @@ outside-in testing development. With this approach you can build your
software starting with the most external layer, and go deeper until
reach unitary tests.
*******************
Introducing Lettuce
===================
*******************
Lettuce is a very simple BDD tool based on the Cucumber, which
currently has many more features than Lettuce.
......@@ -40,16 +42,18 @@ currently has many more features than Lettuce.
Lettuce aims the most common tasks on BDD and it focus specially on
those that make BDD so fun :)
**************
Lettuce pragma
==============
**************
Provide to the developers the ability of describing :ref:`features <intro-wtf>` in a natural language, by creating one or more scenarios
Each scenario has one possible behaviour of the feature you want to implement.
To make the scenarios run python code, it is necessary to define :ref:`steps <reference-features>`.
*********
Hands on!
=========
*********
This documentation will drive you through all the Lettuce features.
When you feel a bit comfortable, go to the :ref:`first part of the tutorial <tutorial-simple>`, or go further on the :ref:`reference <reference-features>`.
.. _intro-wtf:
=====================
#####################
What the f** eature ?
=====================
#####################
Unless you are used to Cucumber_ nomenclature, you may be wondering
about the terms that surround Lettuce concepts.
......@@ -10,8 +10,9 @@ about the terms that surround Lettuce concepts.
If this is your case, this introduction will guide you through the
very basic keywords that cover Lettuce.
********
Features
========
********
Since Lettuce is used to test the behavior of a project, the behavior is broken
up in to features of the system.
......@@ -84,14 +85,15 @@ In the feature above we can notice a few elements, for instance:
When I save the data
Then I get the error: "000 is a invalid phone number"
*********
Scenarios
=========
*********
One or more scenarios compose a feature. There are two kinds of
scenarios:
Simple
~~~~~~
======
The simple scenarios are composed by steps, no matter if they are
simple or tabulated steps.
......@@ -99,7 +101,7 @@ simple or tabulated steps.
The feature above is composed by two simple scenarios.
Outlined
~~~~~~~~
========
Outlined scenarios are very handy because they help you to avoid
repetition.
......@@ -168,13 +170,14 @@ bellow
As you can notice, scenario outlines are very useful and help you on
avoiding text and code repetition
*************************
Steps and its definitions
=========================
*************************
Comparable with Scenarios, Steps comes in two kinds:
Simple steps
~~~~~~~~~~~~
============
Simple steps are actually simple and they are related to the step
definitions inside the scenarios.
......@@ -188,7 +191,7 @@ For instance, a simple step may look like this::
Given I go to the conference website
Tabular steps
~~~~~~~~~~~~~
=============
Analog to Outlined Scenarios, the tabular steps are very useful, and
avoid repetition of text.
......
.. _recipes-django-lxml:
###########################################
Web development fun with Lettuce and Django
===========================================
###########################################
Django_ is a awesome web framework, very mature, aims for simplicity
and the best of all: it's fun to use it.
To make it even more fun, lettuce has built-in support for Django.
***************
Getting started
~~~~~~~~~~~~~~~
***************
1. install the lettuce django app
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
=================================
Pick up any Django project, and add ``lettuce.django`` in its
``settings.py`` configuration file:
......@@ -34,7 +36,7 @@ Considering the configuration above, let's say we want to write tests
for the ``my_app`` django application.
2. create the feature directories
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
=================================
Lettuce will look for a ``features`` folder inside every installed app:
......@@ -59,7 +61,7 @@ Lettuce will look for a ``features`` folder inside every installed app:
- many_steps.py
3. write your first feature
^^^^^^^^^^^^^^^^^^^^^^^^^^^
===========================
``@index.feature``:
......@@ -104,7 +106,7 @@ Lettuce will look for a ``features`` folder inside every installed app:
assert header.text == text
4. run the tests
^^^^^^^^^^^^^^^^
================
Once you install the ``lettuce.django`` app, the command ``harvest`` will be available:
......@@ -115,7 +117,7 @@ Once you install the ``lettuce.django`` app, the command ``harvest`` will be ava
user@machine:~projects/djangoproject $ python manage.py harvest
5. specifying feature files
^^^^^^^^^^^^^^^^^^^^^^^^^^^
===========================
The ``harvest`` command accepts a path to feature files, in order to run
only the features you want.
......@@ -129,7 +131,7 @@ Example:
user@machine:~projects/djangoproject $ python manage.py harvest path/to/my-test.feature
6. grab actual example code
^^^^^^^^^^^^^^^^^^^^^^^^^^^
===========================
In order to assure that lettuce integrate well with Django, it have a
set of integration tests, there are a actual Django project running
......@@ -137,14 +139,15 @@ with lettuce.
You can grab the code at the alfaces_ folder of lettuce git repository
*****************
Technical details
=================
*****************
If you want to write acceptance tests that run with web browsers, you
can user tools like twill_, selenium_, webdriver_ and windmill_
red-tape-less builtin server
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
============================
Lettuce cleverly runs an instance of the built-in Django HTTP server in
the background. It tries to bind the HTTP server at ``localhost:8000``
......@@ -169,7 +172,7 @@ access Django.
issue. If it can possibly bring any errors, be warned.
figure out django urls
~~~~~~~~~~~~~~~~~~~~~~
======================
As the Django HTTP server can be running in any port within the range
8000 - 65535, it could be hard to figure out the correct URL for your
......@@ -194,7 +197,7 @@ Lettuce is here for you. Within your steps you can use the
what does ``django_url`` do ?!?
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-------------------------------
It prepends a Django-internal URL with the HTTP server address.
......@@ -217,7 +220,7 @@ It returns:
"http://localhost:9090/admin/login"
terrain also available in django projects
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
=========================================
At this point you probably know how :ref:`terrain-py` works, and it
also works with Django projects.
......@@ -254,7 +257,7 @@ populate the :ref:`lettuce-world` and organize your features and steps
with it :)
Running without HTTP server
~~~~~~~~~~~~~~~~~~~~~~~~~~~
===========================
Sometimes you may just do not want to run Django's built-in HTTP server
running in background, in those cases all you need to do is run the
......@@ -270,7 +273,7 @@ Example:
python manage.py harvest -S
running the HTTP server in other port than 8000
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
===============================================
If you face the problem of having lettuce running on port 8000, you
can change that behaviour.
......@@ -290,7 +293,7 @@ for example.
running the HTTP server with settings.DEBUG=True
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
================================================
In order to run tests against the nearest configuration of production,
lettuce sets up settings.DEBUG=False
......@@ -306,7 +309,7 @@ For those cases lettuce provides the ``--debug-mode`` or ``-d`` option.
python manage.py harvest -d
running only the specified scenarios
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
====================================
You can also specify the index of the scenarios you want to run
through the command line, to do so, run with ``--scenarios`` or ``-s``
......@@ -322,12 +325,12 @@ For example, let's say you want to run the scenarios 4, 7, 8 and 10:
python manage.py harvest -s 4,7,8,10
to run or not to run? That is the question!
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
===========================================
During your development workflow you may face two situations:
running tests from just certain apps
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
------------------------------------
Lettuce takes a comma-separated list of app names to run tests against.
......@@ -364,7 +367,7 @@ You can also specify it at ``settings.py`` so that you won't need to type the sa
running tests from all apps, except by some
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-------------------------------------------
Lettuce takes a comma-separated list of app names which tests must NOT be ran.
......
.. _recipes-nose:
################################################
Lettuce recipe: Using nose for pretty assertions
================================================
################################################
Lettuce uses python's builtin exception :exc:`AssertionError` to mark
tests as failed.
......
.. _reference-cli:
################
the command line
================
################
Lettuce is used as a command line utility, it means that currently the
only way to use it is through a shell.
......@@ -18,8 +19,9 @@ somewhere in your project
The difference between them is that within Django you have more
options, but both ways have these common options:
*******************************
running a specific feature file
-------------------------------
*******************************
.. highlight:: bash
......@@ -30,8 +32,9 @@ running a specific feature file
With this option, your feature can even be out of the default ``features`` folder.
******************************************************
running only some scenarios of a specific feature file
------------------------------------------------------
******************************************************
.. highlight:: bash
......@@ -42,8 +45,9 @@ running only some scenarios of a specific feature file
This will run the scenarios 3, 5 and 9 from file ``path/to/some/file.feature``
*********************************************
running only some scenarios all feature files
---------------------------------------------
*********************************************
Maybe you can find it senseless, but it works like that, and does not hurt so far :)
......@@ -58,11 +62,10 @@ Yeah, guess what?
This command will run the scenarios 3, 5 and 9 of all feature files living on ``myproj/features`` folder.
verbosity levels
----------------
================
level 1 - dots for each feature
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-------------------------------
.. highlight:: bash
......@@ -100,7 +103,7 @@ The output will be:
3 steps (3 passed)
level 2 - scenario names
~~~~~~~~~~~~~~~~~~~~~~~~
------------------------
.. highlight:: bash
......@@ -142,7 +145,7 @@ The output will be:
5 steps (4 passed)
level 3 - full feature print, but colorless
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-------------------------------------------
.. highlight:: bash
......@@ -203,7 +206,7 @@ Your output will look like:
assert False, 'This step must be implemented'
level 4 - full feature print, but colorful
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
------------------------------------------
This mode is almost **exactly** the same of level 3, the difference is
that it's colorful.
......@@ -218,7 +221,7 @@ that it's colorful.
levels 1, 2 or 3, so that the output won't look messy.
getting help from shell
-----------------------
=======================
.. highlight:: bash
......
.. _reference-features:
#######################################
features, scenarios and steps reference
=======================================
#######################################
Features, scenarios and steps are python objects within lettuce's
feature engine.
......@@ -33,11 +34,12 @@ consider that there is a feature in a file called ``some.feature``
.. _feature-class:
*******
Feature
~~~~~~~
*******
Feature.name
^^^^^^^^^^^^
============
A string containing the name of the feature
......@@ -48,7 +50,7 @@ A string containing the name of the feature
feature.name == 'some feature'
Feature.scenarios
^^^^^^^^^^^^^^^^^
=================
A list of scenario objects
......@@ -61,7 +63,7 @@ The attribute ``scenarios`` could be used as follows
feature.scenarios[0].name == 'try out something'
Feature.described_at
^^^^^^^^^^^^^^^^^^^^
====================
A FeatureDescription object, has the file and line which the feature
was described. Lettuce uses it to output those metadata.
......@@ -81,7 +83,7 @@ The attribute ``described_at`` could be used as follows
feature.described_at.description_at == (6, 7, 8)
Feature.max_length
^^^^^^^^^^^^^^^^^^
==================
A property that calculates the maximum length of all lines that built
the feature.
......@@ -96,7 +98,7 @@ Example:
feature.max_length == 21
Feature.get_head
^^^^^^^^^^^^^^^^
================
Does represent the feature with its first representation in current
language followed by a colon and the feature name.
......@@ -133,46 +135,48 @@ Then, ``Feature.get_head()`` would give:
.. _total-result:
***********
TotalResult
~~~~~~~~~~~
***********
TotalResult.features_ran
^^^^^^^^^^^^^^^^^^^^^^^^
========================
Integer, the total of features ran
TotalResult.features_passed
^^^^^^^^^^^^^^^^^^^^^^^^^^^
===========================
Integer, the total of features passed
TotalResult.scenarios_ran
^^^^^^^^^^^^^^^^^^^^^^^^^
=========================
Integer, the total of scenarios ran
TotalResult.scenarios_passed
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
============================
Integer, the total of scenarios passed
TotalResult.steps
^^^^^^^^^^^^^^^^^
=================
Integer, the number of steps that were supposed to run
TotalResult.proposed_definitions
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
================================
A list of :ref:`step-class` that have no :ref:`step-definition`
.. _scenario-class:
********
Scenario
~~~~~~~~
********
Scenario.steps
^^^^^^^^^^^^^^
==============
A list of scenario objects
......@@ -186,11 +190,12 @@ The attribute ``scenarios`` could be used as follows
.. _step-class:
****
Step
~~~~
****
Step.sentence
^^^^^^^^^^^^^
=============
The string that represents the step
......@@ -203,7 +208,7 @@ The string that represents the step
.. _step-definition:
step definition
~~~~~~~~~~~~~~~
===============
A decorator that can be used on any python function, takes a regex string as parameter, so that the function can me matched against steps.
......
.. _reference-languages:
################
language support
================
################
Lettuce currently supports two languages:
......@@ -11,8 +12,9 @@ Lettuce currently supports two languages:
Although it's only about writing tests since the current version
does output only in English.
***************************************
writing features in a specific language
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
***************************************
You can tell lettuce the language of a feature file through adding a comment in the first line of the file, using the following syntax:
......@@ -23,7 +25,7 @@ You can tell lettuce the language of a feature file through adding a comment in
# language: <code>
english example
^^^^^^^^^^^^^^^
===============
.. highlight:: ruby
......@@ -36,7 +38,7 @@ english example
Then it must be parsed with proper english keywords
brazilian portuguese example
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
============================
.. highlight:: ruby
......@@ -48,14 +50,15 @@ brazilian portuguese example
Dado que eu crio um arquivo que começa com "# language: pt-br"
Então ele deve ser interpretado com as devidas palavras-chave brasileiras
*********************************
adding support to other languages
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*********************************
We love contribution, so if you want to bring lettuce to your native
language there is a single and simple way.
fetch the code
^^^^^^^^^^^^^^
==============
First of all, you must have git_ control version installed in your machine.
......@@ -117,7 +120,7 @@ Instead of::
| Mary | 53 |
add your translation
^^^^^^^^^^^^^^^^^^^^
====================
Now you can add your own language to lettuce, save the ``languages.py`` file and commit in the source control with.
......
.. _reference-terrain:
#############
the "terrain"
=============
#############
Terrain is a "pun" with lettuce and its "living place", its about
setup and teardown, and general hacking on your lettuce tests.
.. _terrain-py:
**********
terrain.py
~~~~~~~~~~
**********
By convention lettuce tries do load a file called ``terrain.py`` located
at the current directory.
......@@ -25,7 +27,7 @@ hooks, and put things into lettuce "world".
:ref:`the-django-command`.
in practice
^^^^^^^^^^^
===========
Try out this file layout:
......@@ -52,8 +54,9 @@ And notice ``terrain.py`` will be loaded before anything
.. _lettuce-world:
*****
world
~~~~~
*****
For the sake of turning easier and funnier to write tests, lettuce
"violates" some principles of good design in python, such as avoiding
......@@ -62,7 +65,7 @@ implicity and using global stuff.
The "world" concept of lettuce is mostly about "global stuff".
in practice
^^^^^^^^^^^
===========
Imagine a file located somewhere that will be imported by your
application before lettuce start running tests:
......@@ -98,7 +101,7 @@ And the feature could have something like:
When I exemplify "world" by seeing that some variable contains "yay!"
world.absorb
^^^^^^^^^^^^
============
It can be really useful to put functions and/or classes in **lettuce.world**
......@@ -163,7 +166,7 @@ And even with lambdas, **but in this case you need to name it**
assert world.optimist_function() == 'yeah'
world.spew
^^^^^^^^^^
==========
Well, if you read the topic above, you may be guessing: "if I keep
stashing things in lettuce.world, it may bloat it sometime, or confuse
......@@ -187,8 +190,9 @@ For those cases after **"absorbing"** something, world can also **"spew"** it.
assert not hasattr(world, 'generic_function')
*****
hooks
~~~~~
*****
Lettuce has hooks that are called sequentially before and after each
action
......@@ -202,7 +206,7 @@ anything you want, for example
Let's see it from outside in
@before.all
^^^^^^^^^^^
===========
This hook is ran before lettuce look for and load feature files
......@@ -220,7 +224,7 @@ The decorated function takes **NO** parameters
print "Lettuce will start to run tests right now..."
@after.all
^^^^^^^^^^
==========
This hook is ran after lettuce run all features, scenarios and
steps
......@@ -243,7 +247,7 @@ that you can use the result statistics somehow
print "Goodbye!"
@before.each_feature
^^^^^^^^^^^^^^^^^^^^
====================
This hook is ran before lettuce run each feature
......@@ -265,7 +269,7 @@ that you can use it to fetch scenarios and steps inside.
)
@after.each_feature
^^^^^^^^^^^^^^^^^^^
===================
This hooks behaves in the same way @before.each_feature does, except
by the fact that its ran *after* lettuce run the feature.
......@@ -281,7 +285,7 @@ by the fact that its ran *after* lettuce run the feature.
print "The feature %r just has just ran" % feature.name
@before.each_scenario
^^^^^^^^^^^^^^^^^^^^^
=====================
This hook is ran before lettuce run each scenario
......@@ -301,7 +305,7 @@ that you can use it to fetch steps inside.
populate_test_database()
@after.each_scenario
^^^^^^^^^^^^^^^^^^^^
====================
This hooks behaves in the same way @before.each_scenario does, except
by the fact that its ran *after* lettuce run the scenario.
......@@ -317,7 +321,7 @@ by the fact that its ran *after* lettuce run the scenario.
models.reset_all_data()
@before.each_step
^^^^^^^^^^^^^^^^^
=================
This hook is ran before lettuce run each step
......@@ -354,13 +358,14 @@ by the fact that its ran *after* lettuce run the step.
if not step.hashes:
print "no tables in the step"
*********************
django-specific hooks
~~~~~~~~~~~~~~~~~~~~~
*********************
Since lettuce officially supports Django_, there are a few specific hooks that help on setting up your test suite on it.
@before.harvest
^^^^^^^^^^^^^^^
===============
This hook is ran before lettuce start harvesting your Django tests. It
can be very useful for setting up browser drivers (such as selenium),
......@@ -382,7 +387,7 @@ the ``harvest`` management command.
world.browser.start()
@after.harvest
^^^^^^^^^^^^^^
==============
This hook is ran right after lettuce finish harvesting your Django
tests. It can be very useful for shutting down previously started
......@@ -399,7 +404,7 @@ The decorated function takes a list of :ref:`total-result` objects.
world.browser.stop()
@before.each_app
^^^^^^^^^^^^^^^^
================
This hook is ran before lettuce run each Django_ app.
......@@ -416,7 +421,7 @@ The decorated function takes the python module that corresponds to the current a
Post.objects.create(title='Nice example', body='I like writting!')
@after.each_app
^^^^^^^^^^^^^^^
===============
This hook is ran after lettuce run each Django_ app.
......@@ -439,7 +444,7 @@ The decorated function takes two arguments:
Post.objects.all()
@before.runserver and @after.runserver
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
======================================
These hooks are ran right before, and after lettuce starts up the built-in http server.
......@@ -462,7 +467,7 @@ The decorated function takes a ``lettuce.django.server.ThreadedServer`` object.
print "goodbye, see you soon"
@before.handle_request and @after.handle_request
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
================================================
These hooks are ran right before, and after lettuce's built-in HTTP server responds to a request.
......
.. _tool-comparisons:
################
Tool comparisons
################
This is not the first time I have written a tool for
behaviour-driven development. I worked on Pyccuracy_ which is an
awesome tool for testing websites.
......
.. _tutorial-django:
####################
Django, meet lettuce
====================
####################
:)
.. _the-django-command:
******************
the django command
~~~~~~~~~~~~~~~~~~
******************
.. _tutorial-multiline:
##################
multi-line strings
===========================
##################
Now imagine you are writing an application which manipulates
strings. When writing the tests, you may find yourself wanting to put
......
.. _tutorial-scenario-outlines:
#################
scenario outlines
=================
#################
On our :ref:`first description file<tutorial-simple>`, ``zero.feature``, all scenarios were
similar. This made us repeat most of the text again and again.
......
.. _tutorial-simple:
############
introduction
============
############
Lettuce_ is an extremely useful and charming tool for BDD_ (Behavior
Driven Development). It can execute plain-text functional descriptions
......@@ -16,8 +17,9 @@ its development.
.. image:: ./flow.png
***********
get lettuce
===========
***********
Make sure you've got Python installed and then run from the terminal:
......@@ -27,8 +29,9 @@ Make sure you've got Python installed and then run from the terminal:
user@machine:~$ [sudo] pip install lettuce
****************
define a problem
================
****************
Let's choose a problem to lettuce:
**Given a number, what is its factorial?**
......@@ -39,8 +42,9 @@ Let's choose a problem to lettuce:
product of all positive integers less than or equal to n. The
factorial of 0 is 1
*****************
project structure
=================
*****************
Build the directory tree bellow such as the files ``zero.feature`` and ``steps.py`` are empty.
......@@ -54,17 +58,18 @@ Build the directory tree bellow such as the files ``zero.feature`` and ``steps.p
- zero.feature
- steps.py
***********
lettuce it!
===========
***********
Lets begin to describe and solve our problem...
first round
-----------
===========
[a] describe behaviour
~~~~~~~~~~~~~~~~~~~~~~
----------------------
Start describing the expected behaviour of factorial in ``zero.feature`` using English:
......@@ -88,7 +93,7 @@ Start describing the expected behaviour of factorial in ``zero.feature`` using E
be .feature. However, you're free to choose its name.
[b] define steps in python
~~~~~~~~~~~~~~~~~~~~~~~~~~
--------------------------
Now let's define the steps of the scenario, so Lettuce can
understand the behaviour description. Create the ``steps.py`` file which will contain
......@@ -133,7 +138,7 @@ the idea of how to use Lettuce.
**Notice that, until now, we haven't defined the factorial function (it's returning -1).**
[c] run and watch it fail
~~~~~~~~~~~~~~~~~~~~~~~~~
-------------------------
Go to the tests directory and run from the terminal:
......@@ -152,7 +157,7 @@ Our only scenario failed :(
Let's solve it...
[d] write code to make it pass
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
------------------------------
Well, by definition, we know that the factorial of 0 is 1. As our only
feature is this... we could force factorial to return 1.
......@@ -181,7 +186,7 @@ feature is this... we could force factorial to return 1.
return 1
[e] run again and watch it pass
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-------------------------------
Again, run from the terminal:
......@@ -200,15 +205,14 @@ Great! :)
However, one test is not enough for checking the quality of our
solution... So let's lettuce it again!
second round
------------
============
Let's provide more tests so our problem is better described, and so we
provide a more accurate implementation of factorial:
[a] describe behaviour
~~~~~~~~~~~~~~~~~~~~~~
----------------------
Let's provide two new scenarios, for numbers 1 and 2:
......@@ -237,13 +241,13 @@ Let's provide two new scenarios, for numbers 1 and 2:
Then I see the number 2
[b] define steps in python
~~~~~~~~~~~~~~~~~~~~~~~~~~
--------------------------
As we haven't changed the definition, no need to make changes on this
step.
[c] run and watch it fail
~~~~~~~~~~~~~~~~~~~~~~~~~
-------------------------
.. highlight:: bash
......@@ -259,7 +263,7 @@ fails. :(
.. image:: ./screenshot3.png
[d] write code to make it pass
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
------------------------------
Let's provide a solution so we get the right factorial for all
scenarios, specially for number 2:
......@@ -292,7 +296,7 @@ scenarios, specially for number 2:
return number
[e] run again and watch it pass
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-------------------------------
.. highlight:: bash
......@@ -305,13 +309,13 @@ scenarios, specially for number 2:
Great! Three scenarios described and they are alright!
third round
-----------
===========
Let's provide more tests so our problem is better described and we get
new errors so we'll be able to solve them.
[a] describe behaviour
~~~~~~~~~~~~~~~~~~~~~~
----------------------
.. highlight:: ruby
......@@ -348,13 +352,13 @@ new errors so we'll be able to solve them.
Then I see the number 24
[b] define steps in python
~~~~~~~~~~~~~~~~~~~~~~~~~~
--------------------------
As we haven't changed the definition, no need to make changes on this
step.
[c] run and watch it fail
~~~~~~~~~~~~~~~~~~~~~~~~~
-------------------------
.. highlight:: bash
......@@ -365,7 +369,7 @@ step.
.. image:: ./screenshot5.png
[d] write code to make it pass
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
------------------------------
.. highlight:: python
......@@ -395,7 +399,7 @@ step.
return number*factorial(number-1)
[e] run again and watch it pass
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-------------------------------
.. highlight:: bash
......@@ -406,7 +410,7 @@ step.
.. image:: ./screenshot6.png
forth round
-----------
===========
All steps should be repeated as long as you can keep doing them - the
quality of your software depends on these.
......
.. _tutorial-steps-from-step-definitions:
###################################
calling steps from step definitions
===================================
###################################
Our tests should be as expressive as possible. However, we also want to re-use steps that we've seen before. With the tools we've used so far, you could end up with seriously long step definitions.
......@@ -39,9 +40,10 @@ Lettuce affords you the ability to write such a "step of steps" with a set of he
step.given('I go to the home page')
step.given('I click the login button')
# ... and so on.
***********************
running blocks of steps
-----------------------
***********************
It is sometimes even desirable to run blocks of steps, copy-and-pasted directly from Feature specifications. The ``Step.behave_as`` method lets you do this, and you can use ``str.format`` to fill in parameters dynamically. For example, we can write the above step definition like so:
......
.. _tutorial-tables:
#########################
handling data with tables
=========================
#########################
Let's imagine writing a MVC application. While writing the tests
you will stumble in to a situation where there is a few models
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment