Commit ccef2eb5 by Gabriel Falcão

Merge pull request #225 from benoitbryon/doc-dev

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