Giter Site home page Giter Site logo

gabrielfalcao / lettuce Goto Github PK

View Code? Open in Web Editor NEW
1.3K 51.0 324.0 14.77 MB

Behavior-driven-development tool for python, inspired by Cucumber for Ruby ⛺

Home Page: http://lettuce.it

License: GNU General Public License v3.0

CSS 1.46% JavaScript 1.48% Ruby 0.01% Python 93.02% Shell 0.06% Makefile 0.08% HTML 3.51% Gherkin 0.25% Batchfile 0.01% Roff 0.13% TSQL 0.01%
python bdd behavior-driven-development

lettuce's Issues

Can define callbacks to run before and after all

It can be defined in any file that will be imported by lettuce.

But lettuce documentation should tell to use it at terrain.py

examples:
from lettuce.terrain import before
from lettuce.terrain import after

@before.all
def populate_database(scenario):
    from my_models import Person
    Person(name="John Doe").save()

@after.all
def reset_database(scenario):
    from my_models import Person
    Person.delete_all()

Can define callbacks to run before and after each feature

It can be defined in any file that will be imported by lettuce.

But lettuce documentation should tell to use it at terrain.py

examples:
from lettuce.terrain import before
from lettuce.terrain import after

@before.each_feature
def populate_database(scenario):
    from my_models import Person
    Person(name="John Doe").save()

@after.each_feature
def reset_database(scenario):
    from my_models import Person
    Person.delete_all()

Environment should be easy to set

Environment (setup, teardown and global scope)

** AKA thread-local stuff **

A global python file will be imported, maybe something like:

terrain.py

which contains stuff like:

from lettuce.terrain import before_each_scenario
from lettuce.terrain import after_each_scenario
@before_each_scenario
def populate_database(scenario):
    from my_models import Person
    Person(name="John Doe").save()

@after_each_scenario
def reset_database(scenario):
    from my_models import Person
    Person.delete_all()

And maybe, something that make easy stuff like, creating a single instance of a browser driver.
from lettuce.terrain import world
from webdriver_firefox.webdriver import WebDriver

world.browser = WebDriver()

So that, when and where ever I decide to use the browser driver, I do not need to instantiate it again, just do:

from lettuce.terrain import world
@step(u'I go to google home page')
def browse_google(context):
    world.browser.get("http://google.com")

And so on

Lettuce always try to load a environment file

Lettuce always try to load terrain.py which can be located ONLY in the dir which lettuce runs

Example:
gabriel@durga:~/Projects/my-project$ lettuce features

Will try to import: ~/Projects/my-project/terrain.py

Language error

Here is my languages.py code - http://pastebin.com/k7FEnkCL

Example scenario

language: pl

Właściwość: Wyszukiwanie

Scenariusz: Znajdywanie wpisów, wydarzeń, miejsc, grup i filmów o cesarskim cięciu
Zakładając że jestem na stronie głównej
Jeżeli wpisze w wyszukiwarke: "cesarskie ciecie"
Wtedy otrzymam "20" ostatnich wpisów, wydarzeń, miejsc, grup, filmów zawierających frazę: "cesarskie cięcie"

And exception

tests$ lettuce

Traceback (most recent call last):
File "/usr/bin/lettuce", line 5, in
pkg_resources.run_script('lettuce==0.1rc12', 'lettuce')
File "/usr/lib/python2.5/site-packages/pkg_resources.py", line 448, in run_script
self.require(requires)[0].run_script(script_name, ns)
File "/usr/lib/python2.5/site-packages/pkg_resources.py", line 1166, in run_script
execfile(script_filename, namespace, namespace)
File "/usr/lib/python2.5/site-packages/lettuce-0.1rc12-py2.5.egg/EGG-INFO/scripts/lettuce", line 53, in
main()
File "/usr/lib/python2.5/site-packages/lettuce-0.1rc12-py2.5.egg/EGG-INFO/scripts/lettuce", line 48, in main
result = runner.run()
File "/usr/lib/python2.5/site-packages/lettuce-0.1rc12-py2.5.egg/lettuce/init.py", line 109, in run
results.append(feature.run())
File "/usr/lib/python2.5/site-packages/lettuce-0.1rc12-py2.5.egg/lettuce/core.py", line 706, in run
callback(self)
File "/usr/lib/python2.5/site-packages/lettuce-0.1rc12-py2.5.egg/lettuce/plugins/colored_shell_output.py", line 154, in print_feature_running
write_out("\033[1;37m%s\n" % line)
File "/usr/lib/python2.5/site-packages/lettuce-0.1rc12-py2.5.egg/lettuce/plugins/colored_shell_output.py", line 47, in write_out
wrt(wp(what))
File "/usr/lib/python2.5/site-packages/lettuce-0.1rc12-py2.5.egg/lettuce/plugins/colored_shell_output.py", line 26, in wrt
sys.stdout.write(what)
UnicodeEncodeError: 'ascii' codec can't encode character u'\u0142' in position 8: ordinal not in range(128)

Best regards,
PS

Support for tags

Tagging is cool, I can run scenarios that suit different ocasions

Tagging
Running

Create a django app within lettuce, to manage lettuce within django :)

In a few words, the programmer will be able to do something like:

settings.py:

...
INSTALLED_APPS = (
    ...
    "lettuce.django"
    ...
)

It will give us:

python manage.py lettuce

that runs lettuce within python, so that we will be able to use django models within lettuce steps:

from lettuce import step
from myapp.models import Poll

@step("Given I have the following polls:")
def have_items(step):
    for poll in step.data_list:
        Poll.objects.create(name=poll['name'])

Lettuce may also put Django's builtin server running at 0.0.0.0:9000, in a thread, so that lettuce users will be able to use browser test tools such as selenium, webdriver, windmill and so on

lettuce should find step definitions even without __init__.py file within step_definitions folder

Why ?

It will be a python kick-ass feature.

Mostly python libraries and programs at all have this issue.
It is not a big problem, since it suits python's zen that says: "Explicit is better than implicit"

Althrough, programmers use to forget to create init.py files within dirs, and I've seen so many programmers (specially rookies) loosing half an hour, and even hours debugging after this simple problem.

How to ?

Quite simple:
Lettuce will create a empty init.py file within step_definitions folder under any dir that contains *.feature files.

The init.py file created by lettuce must contain:

# -*- coding: utf-8 -*-
# This file was automatically created by lettuce
# http://github.com/gabrielfalcao/lettuce/

AttributeError: 'thread._local' object has no attribute <attr here>

I have two features. So, before implement the second, the global variable world runs fine. But, when implement the second feature (only add @step(r'desc') def ...) the lettuce raise this exception.

In the first feature I have a attribute world.username. This works fine. Implement the second feature, raise AttributeError: 'thread._local' object has no attribute 'username'

Steps should be aware of its definitions

This ticket is a child of #8

A step must be aware of its definition.

Example:
step.defined_at.file == "/full/path/to/step_definitions/my_steps.py"
steo.defined_at.line == 1

Can define callbacks to run before and after each scenario

It can be defined in any file that will be imported by lettuce.

But lettuce documentation should tell to use it at terrain.py

examples:
from lettuce.terrain import before
from lettuce.terrain import after

@before.each_scenario
def populate_database(scenario):
    from my_models import Person
    Person(name="John Doe").save()

@after.each_scenario
def reset_database(scenario):
    from my_models import Person
    Person.delete_all()

Support for step transforms

It allows tranforming matched group strings into any kind of object.
The description at cucumber's wiki is here

Example:

from sure import that
from lettuce import step, transform
from django.contrib.auth.models import User

@transform(r'the user "(.*)"')
def transform_user(username):
    user_object = User.objects.get(username=username)
    return user_object

@step(r'I clone permissions from the user "(.*)" to the user "(.*)"'):
def clone_permissions_from_to(step, one, two):
    assert that(one).is_a(User)
    assert that(two).is_a(User)

    two.clone_permissions_from(one)

Handle KeyboardInterruption

Lettuce should show the current test results already ran when user does a control-c or something that raises KeyboardInterruption.

It is so cool, developer will be able to cancel the whole feature set to run when some fail

Refactor lettuce.plugins.shell_output and lettuce.plugins.colored_shell_output

Those modules must be refactored to use couleur.

shell_output must print with colored markup, something like:

sys.stdout.write("{red}1 failed")

and shell_output will setup couleur to ignore those markups:

couleur.stdout_filter.setup(ignore_markups=True)

thus colored_shell_output will do:

  1. import shell_output plugin

  2. setup couleur to process stdout markups:

    couleur.stdout_filter.setup(ignore_markups=False)

Step definitions should receive matched groups as params

And must work for both named and unnamed groups.

Example with unnamed groups:

from lettuce import step
@step(r'Given I match this group "(.*)"')
def given_unnamed(group):
    pass

Example with named groups:

from lettuce import step
@step(r'Given I match this group "(?P<foobar>.*)"')
def given_unnamed(foobar):
    pass

Example with both:

from lettuce import step
@step(r'Given I (match|search) this group "(?P<name>.*)"')
def given_unnamed(action, name):
    pass

Can't install in Python 2.5

pip install lettuce works correctly on Python 2.6, but doesn't on Python 2.5. Apparently this is due to a known bug in distutils that mishandles unicode strings. In this case, it's your name, Gabriel Falcão, that triggers the problem.

A way to work this around would be explicitly encoding the string as follows:

author=u'Gabriel Falcão'.encode("UTF-8")

Not sure if this has side effects though. Any ideas?

Features should have description

They must be parsed from the feature, it must be tested in a full-featured feature, example:

Feature: Do many things at once
    In order to automate tests
    As a automation freaky
    I want to use scenario outlines

    Scenario Outline: Add two numbers
        Given I have entered <input_1> into the calculator
        And I have entered <input_2> into the calculator
        When I press <button>
        Then the result should be <output> on the screen

    Examples:
        | input_1 | input_2 | button | output |
        | 20      | 30      | add    | 50     |
        | 2       | 5       | add    | 7      |
        | 0       | 40      | add    | 40     |

bold output strings that match groups

lettuce should identify parts of strings that matches regex groups at step definitions, and output it as bold.

for example:

Given I fill textbox "username" with "gabriel"

and the step definition:

@step('I fill textbox "(.*)" with "(.*)"')
def fill_txtbox(step, name, value):
    pass

it should output like this;

Given I fill textbox "username" with "gabriel"
there is a discussion about it at #3

Mode to print a summary like the following:

Mode to print a summary like the following:
"passed X tests out of Y" (if all pass) - exiting with the return code 0
if a test fails:
"passed X tests out of Y, test Z failed" - exiting with return code 1
if multiple tests fail:
"passed X tests out of Y, tests Z,P failed" - exiting with return code 1

The output needs to be on one line - this is required for use in nagios.

Documentation!

Lettuce should have a awesome documentation, inspired on Django's.

Would be awesome to put the documentation available on github too

Can define callbacks to run before and after each step

It can be defined in any file that will be imported by lettuce.

But lettuce documentation should tell to use it at terrain.py

examples:
from lettuce.terrain import before
from lettuce.terrain import after

@before.each_step
def populate_database(scenario):
    from my_models import Person
    Person(name="John Doe").save()

@after.each_step
def reset_database(scenario):
    from my_models import Person
    Person.delete_all()

Unicode error on python setup.py install

pats@patrycjuszszydlo:~/Pulpit/Pobieranie/lettuce$ sudo python setup.py install
running install
running bdist_egg
running egg_info
creating lettuce.egg-info
writing lettuce.egg-info/PKG-INFO
Traceback (most recent call last):
  File "setup.py", line 38, in 
    packages=get_packages()
  File "/usr/lib/python2.5/distutils/core.py", line 151, in setup
    dist.run_commands()
  File "/usr/lib/python2.5/distutils/dist.py", line 974, in run_commands
    self.run_command(cmd)
  File "/usr/lib/python2.5/distutils/dist.py", line 994, in run_command
    cmd_obj.run()
  File "/usr/lib/python2.5/site-packages/setuptools/command/install.py", line 76, in run
    self.do_egg_install()
  File "/usr/lib/python2.5/site-packages/setuptools/command/install.py", line 96, in do_egg_install
    self.run_command('bdist_egg')
  File "/usr/lib/python2.5/distutils/cmd.py", line 333, in run_command
    self.distribution.run_command(command)
  File "/usr/lib/python2.5/distutils/dist.py", line 994, in run_command
    cmd_obj.run()
  File "/usr/lib/python2.5/site-packages/setuptools/command/bdist_egg.py", line 167, in run
    self.run_command("egg_info")
  File "/usr/lib/python2.5/distutils/cmd.py", line 333, in run_command
    self.distribution.run_command(command)
  File "/usr/lib/python2.5/distutils/dist.py", line 994, in run_command
    cmd_obj.run()
  File "/usr/lib/python2.5/site-packages/setuptools/command/egg_info.py", line 170, in run
    writer(self, ep.name, os.path.join(self.egg_info,ep.name))
  File "/usr/lib/python2.5/site-packages/setuptools/command/egg_info.py", line 379, in write_pkg_info
    metadata.write_pkg_info(cmd.egg_info)
  File "/usr/lib/python2.5/distutils/dist.py", line 1076, in write_pkg_info
    self.write_pkg_file(pkg_info)
  File "/usr/lib/python2.5/distutils/dist.py", line 1094, in write_pkg_file
    file.write('Author: %s\n' % self.get_contact() )
UnicodeEncodeError: 'ascii' codec can't encode character u'\xe3' in position 20: ordinal not in range(128)
pats@patrycjuszszydlo:~/Pulpit/Pobieranie/lettuce$

Best regards,
PS

Scenario outlines does not work within a feature

Example:

Feature: Do many things at once
    In order to automate tests
    As a automation freaky
    I want to use scenario outlines

    Scenario Outline: Add two numbers
        Given I have entered <input_1> into the calculator
        And I have entered <input_2> into the calculator
        When I press <button>
        Then the result should be <output> on the screen

    Examples:
        | input_1 | input_2 | button | output |
        | 20      | 30      | add    | 50     |
        | 2       | 5       | add    | 7      |
        | 0       | 40      | add    | 40     |

Self documenting would be AWESOME!

What if at command line I could type something like:

gabriel@durga:~/Projects/my-project$ lettuce harvest
Steps defined here:
    /the client '(.*)' rents '(.*)'/
    Step example:
        "When the client 'John Doe' rents 'Iron man 2"
    Defined At:
        features/step_definitions/movie_rental_steps.py:14

It could be done by simply doing at features/step_definitions/movie_rental_steps.py:
from lettuce import step
@step(r"the client '(.)' rents '(.)'")
def client_rents(self, client, movie):
"When the client 'John Doe' rents 'Iron man 2"
pass

mailing list?

do you have a mailing list to communicate on yet? or a google groups?

Features, Scenarios and Steps must know about its definitions

Features, Scenarios and Steps must know the file path and line numbers that implement them.

Features:
feature.described_at.file == "/full/path/to/definition.feature"
feature.described_at.line == 17

Scenarios:
scenario.described_at.file == "/full/path/to/definition.feature"
scenario.described_at.line == 30

Step:
step.described_at.file == "/full/path/to/definition.feature"
steo.described_at.line == 25
step.defined_at.file == "step_definitions/my_steps.py"
steo.defined_at.line == 2

It should show output as in cucumber

Colored output on shell

Feature description is WHITE
Step currently running is GRAY
Steps that have failed, get RED
Steps that have passed, get GREEN as Lettuce leaves
Steps not yet defined, get YELLOW

Important

It is very useful to show the referenced python file of each step, referencing the line number. Exactly as in Cucumber example

Can define callbacks to run before and after all

It can be defined in any file that will be imported by lettuce.

But lettuce documentation should tell to use it at terrain.py

examples:
from lettuce.terrain import before
from lettuce.terrain import after

@before.all
def populate_database(scenario):
    from my_models import Person
    Person(name="John Doe").save()

@after.all
def reset_database(scenario):
    from my_models import Person
    Person.delete_all()

It should be simple to define steps

A python file that has methods with @lettuce.step decorator:

from lettuce import *
@step(u'I have the following tables:')
def have_following_tables(context, dicts):
    assert {"Item": "Value"} in dicts

And assertion errors must be enough to fail steps, as well

world should have immutable attributes

If set some unexistent attribute in world, and it starts with _, the it must become immutable
lettuce will use it to store its global stuff:

world._runner
world._shell

Changing them must raise a exception like:
AttributeError('lettuce.world attributes starting with "_" are immutable')

hooks for django

before and after apps:

@before.each_app
def do_something_before(app_module):
    pass

@after.each_app
def do_something_after(app_module):
    pass

before and after the "harvest"

@before.harvest
def do_something_before(dict_of_local_variables):
    pass

@after.harvest
def do_something_after(list_of_results):
    pass

before and after runserver

@before.runserver
def do_something_before(server_instance):
    pass

@after.runserver
def do_something_before(server_instance):)
    pass

threading support

handling request

@before.handle_request
def something_before(httpd):
    pass

@after.handle_request
def something_after(httpd):
    pass

running server

@before.within_runserver
def something_before(thread_instance):
    pass

@after.within_runserver
def something_after(thread_instance):
    pass

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.