Commit 4539b446 by Antti Kaihola

Merge remote-tracking branch 'gabrielfalcao/master'

parents 74037a1e 36ffa108
language: python
python:
- "2.5"
- "2.6"
- "2.7"
# command to install dependencies
......
# Contributing
1. fork and clone the project
2. install the dependencies above
3. run the tests with make:
> make unit functional integration doctest
4. hack at will
5. commit, push etc
6. send a pull request
## keep in mind
![your lack of tests if disturbing the force](http://farm3.static.flickr.com/2248/2282734669_a7f431e660_o.jpg)
### that lettuce is a testing software, patches and pull requests must come with automated tests, and if suitable, with proper documentation.
# lettuce
> Version 0.2.8 - kryptonite
> Version 0.2.10 - kryptonite
## On release names
......@@ -51,22 +51,6 @@ all them are used within lettuce tests
* [django](http://djangoproject.com/)
> [sudo] pip install django
# Contributing
1. fork and clone the project
2. install the dependencies above
3. run the tests with make:
> make unit functional integration doctest
4. hack at will
5. commit, push etc
6. send a pull request
## keep in mind
![your lack of tests if disturbing the force](http://farm3.static.flickr.com/2248/2282734669_a7f431e660_o.jpg)
### that lettuce is a testing software, patches and pull requests must come with automated tests, and if suitable, with proper documentation.
# mailing list
## for users
......
......@@ -15,14 +15,20 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
version = '0.2.8'
version = '0.2.10'
release = 'kryptonite'
import os
import sys
import traceback
from imp import reload
try:
from imp import reload
except ImportError:
# python 2.5 fallback
pass
from datetime import datetime
import random
from lettuce.core import Feature, TotalResult
......@@ -76,7 +82,7 @@ class Runner(object):
Takes a base path as parameter (string), so that it can look for
features and step definitions on there.
"""
def __init__(self, base_path, scenarios=None, verbosity=0,
def __init__(self, base_path, scenarios=None, verbosity=0, random=False,
enable_xunit=False, xunit_filename=None, tags=None):
""" lettuce.Runner will try to find a terrain.py file and
import it from within `base_path`
......@@ -107,6 +113,8 @@ class Runner(object):
else:
from lettuce.plugins import colored_shell_output as output
self.random = random
if enable_xunit:
xunit_output.enable(filename=xunit_filename)
......@@ -132,6 +140,8 @@ class Runner(object):
features_files = [self.single_feature]
else:
features_files = self.loader.find_feature_files()
if self.random:
random.shuffle(features_files)
if not features_files:
self.output.print_no_features_found(self.loader.base_dir)
......@@ -142,7 +152,7 @@ class Runner(object):
for filename in features_files:
feature = Feature.from_file(filename)
results.append(
feature.run(self.scenarios, tags=self.tags))
feature.run(self.scenarios, tags=self.tags, random=self.random))
except exceptions.LettuceSyntaxError, e:
sys.stderr.write(e.msg)
......
......@@ -47,6 +47,12 @@ def main(args=sys.argv[1:]):
'(prefixing tags with "-" will exclude them and '
'prefixing with "~" will match approximate words)')
parser.add_option("-r", "--random",
dest="random",
action="store_true",
default=False,
help="Run scenarios in a more random order to avoid interference")
parser.add_option("--with-xunit",
dest="enable_xunit",
action="store_true",
......@@ -60,7 +66,7 @@ def main(args=sys.argv[1:]):
help='Write JUnit XML to this file. Defaults to '
'lettucetests.xml')
options, args = parser.parse_args()
options, args = parser.parse_args(args)
if args:
base_path = os.path.abspath(args[0])
......@@ -73,6 +79,7 @@ def main(args=sys.argv[1:]):
base_path,
scenarios=options.scenarios,
verbosity=options.verbosity,
random=options.random,
enable_xunit=options.enable_xunit,
xunit_filename=options.xunit_file,
tags=options.tags,
......
......@@ -37,7 +37,10 @@ class ReasonToFail(object):
"""
def __init__(self, exc):
self.exception = exc
self.cause = unicode(exc)
if isinstance(exc.message, unicode):
self.cause = unicode(exc)
elif isinstance(exc.message, str):
self.cause = str(exc)
self.traceback = traceback.format_exc(exc)
......
......@@ -24,6 +24,7 @@ LANGUAGES = {
'scenario': u'Scenario',
'scenario_outline': u'Scenario Outline',
'scenario_separator': u'(Scenario Outline|Scenario)',
'background': u'(?:Background)',
},
'pt-br': {
'examples': u'Exemplos|Cenários',
......@@ -33,6 +34,7 @@ LANGUAGES = {
'scenario': u'Cenário|Cenario',
'scenario_outline': u'Esquema do Cenário|Esquema do Cenario',
'scenario_separator': u'(Esquema do Cenário|Esquema do Cenario|Cenario|Cenário)',
'background': u'(?:Contexto|Considerações)',
},
'pl': {
'examples': u'Przykład',
......@@ -42,6 +44,7 @@ LANGUAGES = {
'scenario': u'Scenariusz',
'scenario_outline': u'Zarys Scenariusza',
'scenario_separator': u'(Zarys Scenariusza|Scenariusz)',
'background': u'(?:Background)',
},
'ca': {
'examples': u'Exemples',
......@@ -51,6 +54,7 @@ LANGUAGES = {
'scenario': u'Escenari',
'scenario_outline': u"Esquema d'Escenari",
'scenario_separator': u"(Esquema d'Escenari|Escenari)",
'background': u'(?:Background)',
},
'es': {
'examples': u'Ejemplos',
......@@ -60,6 +64,7 @@ LANGUAGES = {
'scenario': u'Escenario',
'scenario_outline': u'Esquema de Escenario',
'scenario_separator': u'(Esquema de Escenario|Escenario)',
'background': u'(?:Contexto|Consideraciones)',
},
'hu': {
'examples': u'Példák',
......@@ -69,6 +74,7 @@ LANGUAGES = {
'scenario': u'Forgatókönyv',
'scenario_outline': u'Forgatókönyv vázlat',
'scenario_separator': u'(Forgatókönyv|Forgatókönyv vázlat)',
'background': u'(?:Background)',
},
'fr': {
'examples': u'Exemples|Scénarios',
......@@ -78,6 +84,7 @@ LANGUAGES = {
'scenario': u'Scénario',
'scenario_outline': u'Plan de Scénario|Plan du Scénario',
'scenario_separator': u'(Plan de Scénario|Plan du Scénario|Scénario)',
'background': u'(?:Background)',
},
'de': {
'examples': u'Beispiele|Szenarios',
......@@ -87,6 +94,7 @@ LANGUAGES = {
'scenario': u'Szenario',
'scenario_outline': u'Szenario-Zusammenfassung|Zusammenfassung',
'scenario_separator': u'(Szenario-Zusammenfassung|Zusammenfassung)',
'background': u'(?:Background)',
},
'ja': {
'examples': u'例',
......@@ -96,6 +104,7 @@ LANGUAGES = {
'scenario': u'シナリオ',
'scenario_outline': u'シナリオアウトライン|シナリオテンプレート|テンプレ|シナリオテンプレ',
'scenario_separator': u'(シナリオ|シナリオアウトライン|シナリオテンプレート|テンプレ|シナリオテンプレ)',
'background': u'(?:Background)',
},
'tr': {
'examples': u'Örnekler',
......@@ -105,6 +114,7 @@ LANGUAGES = {
'scenario': u'Senaryo',
'scenario_outline': u'Senaryo taslağı|Senaryo Taslağı',
'scenario_separator': u'(Senaryo taslağı|Senaryo Taslağı|Senaryo)',
'background': u'(?:Background)',
},
'zh-CN': {
'examples': u'例如|场景集',
......@@ -114,6 +124,7 @@ LANGUAGES = {
'scenario': u'场景',
'scenario_outline': u'场景模板',
'scenario_separator': u'(场景模板|场景)',
'background': u'(?:背景)',
},
'zh-TW': {
'examples': u'例如|場景集',
......@@ -123,6 +134,7 @@ LANGUAGES = {
'scenario': u'場景',
'scenario_outline': u'場景模板',
'scenario_separator': u'(場景模板|場景)',
'background': u'(?:背景)',
},
'ru': {
'examples': u'Примеры|Сценарии',
......@@ -132,6 +144,7 @@ LANGUAGES = {
'scenario': u'Сценарий',
'scenario_outline': u'Структура сценария',
'scenario_separator': u'(Структура сценария|Сценарий)',
'background': u'(?:Background)',
},
'uk': {
'examples': u'Приклади|Сценарії',
......@@ -141,6 +154,7 @@ LANGUAGES = {
'scenario': u'Сценарій',
'scenario_outline': u'Структура сценарію',
'scenario_separator': u'(Структура сценарію|Сценарій)',
'background': u'(?:Background)',
},
'it': {
'examples': u'Esempi|Scenari|Scenarii',
......@@ -150,6 +164,7 @@ LANGUAGES = {
'scenario': u'Scenario',
'scenario_outline': u'Schema di Scenario|Piano di Scenario',
'scenario_separator': u'(Schema di Scenario|Piano di Scenario|Scenario)',
'background': u'(?:Background)',
},
'no': {
'examples': u'Eksempler',
......@@ -159,5 +174,6 @@ LANGUAGES = {
'scenario': u'Situasjon',
'scenario_outline': u'Situasjon Oversikt',
'scenario_separator': u'(Situasjon Oversikt|Situasjon)',
'background': u'(?:Background)',
}
}
......@@ -27,7 +27,9 @@ from lettuce.terrain import before
def wrt(what):
sys.stdout.write(what.encode('utf-8'))
if isinstance(what, unicode):
what = what.encode('utf-8')
sys.stdout.write(what)
def wrap_file_and_line(string, start, end):
......@@ -60,7 +62,7 @@ def print_step_running(step):
color = '\033[1;30m'
if step.scenario.outlines:
if step.scenario and step.scenario.outlines:
color = '\033[0;36m'
string = step.represent_string(step.original_sentence)
......@@ -73,7 +75,7 @@ def print_step_running(step):
@after.each_step
def print_step_ran(step):
if step.scenario.outlines:
if step.scenario and step.scenario.outlines:
return
if step.hashes and step.defined_at:
......@@ -248,3 +250,11 @@ def print_no_features_found(where):
write_out(
'\033[1;37mcould not find features at '
'\033[1;33m%s\033[0m\n' % where)
@before.each_background
def print_background_running(background):
wrt('\n')
wrt('\033[1;37m')
wrt(background.represented())
wrt('\033[0m\n')
......@@ -24,8 +24,10 @@ failed_scenarios = []
scenarios_and_its_fails = {}
def wrt(string):
sys.stdout.write(string)
def wrt(what):
if isinstance(what, unicode):
what = what.encode('utf-8')
sys.stdout.write(what)
@after.each_step
......
......@@ -25,8 +25,10 @@ failed_scenarios = []
scenarios_and_its_fails = {}
def wrt(string):
sys.stdout.write(string.encode('utf-8'))
def wrt(what):
if isinstance(what, unicode):
what = what.encode('utf-8')
sys.stdout.write(what)
@before.each_scenario
......
......@@ -24,7 +24,9 @@ from lettuce.terrain import before
def wrt(what):
sys.stdout.write(what.encode('utf-8'))
if isinstance(what, unicode):
what = what.encode('utf-8')
sys.stdout.write(what)
@after.each_step
......@@ -50,6 +52,13 @@ def print_scenario_running(scenario):
wrt(scenario.represented())
@before.each_background
def print_background_running(background):
wrt('\n')
wrt(background.represented())
wrt('\n')
@after.outline
def print_outline(scenario, order, outline, reasons_to_fail):
table = strings.dicts_to_string(scenario.outlines, scenario.keys)
......
......@@ -23,7 +23,10 @@ from xml.dom import minidom
def wrt_output(filename, content):
f = open(filename, "w")
f.write(content.encode('utf-8'))
if isinstance(content, unicode):
content = content.encode('utf-8')
f.write(content)
f.close()
......@@ -48,13 +51,13 @@ def enable(filename=None):
def create_test_case_step(step):
if step.scenario.outlines:
return
classname = "%s : %s" % (step.scenario.feature.name, step.scenario.name)
tc = doc.createElement("testcase")
tc.setAttribute("classname", classname)
tc.setAttribute("name", step.sentence)
tc.setAttribute("time", str(total_seconds((datetime.now() - step.started))))
if not step.ran:
skip=doc.createElement("skipped")
tc.appendChild(skip)
......@@ -68,12 +71,12 @@ def enable(filename=None):
tc.appendChild(failure)
root.appendChild(tc)
@before.outline
def time_outline(scenario, order, outline, reasons_to_fail):
scenario.outline_started = datetime.now()
pass
@after.outline
def create_test_case_outline(scenario, order, outline, reasons_to_fail):
classname = "%s : %s" % (scenario.feature.name, scenario.name)
......
......@@ -14,7 +14,6 @@
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import sys
import os
import threading
import traceback
......@@ -55,6 +54,10 @@ CALLBACK_REGISTRY = CallbackDict(
'after_each': [],
'outline': [],
},
'background': {
'before_each': [],
'after_each': [],
},
'feature': {
'before_each': [],
'after_each': [],
......@@ -84,9 +87,10 @@ def call_hook(situation, kind, *args, **kw):
try:
callback(*args, **kw)
except Exception, e:
print "=" * 1000
traceback.print_exc(e)
print
raise SystemExit(2)
raise
def clear():
......
......@@ -96,7 +96,7 @@ def getlen(string):
def dicts_to_string(dicts, order):
escape = "#{%s}" % str(time.time())
escape = "#{%s}" % unicode(time.time())
def enline(line):
return unicode(line).replace("|", escape)
......@@ -133,7 +133,7 @@ def dicts_to_string(dicts, order):
def parse_hashes(lines):
escape = "#{%s}" % str(time.time())
escape = "#{%s}" % unicode(time.time())
def enline(line):
return unicode(line.replace("\\|", escape)).strip()
......
......@@ -54,6 +54,7 @@ for name, where, when in (
('all', 'all', '%(0)s'),
('each_step', 'step', '%(0)s_each'),
('each_scenario', 'scenario', '%(0)s_each'),
('each_background', 'background', '%(0)s_each'),
('each_feature', 'feature', '%(0)s_each'),
('harvest', 'harvest', '%(0)s'),
('each_app', 'app', '%(0)s_each'),
......
......@@ -7,12 +7,10 @@ cssselect==0.7.1
distribute==0.6.27
docutils==0.9.1
fuzzywuzzy==0.1
ipdb==0.7
ipython==0.13
lxml==3.0alpha2
lxml
mock==1.0b1
mox==0.5.3
nose==1.1.2
sure==1.0.5
sure==1.0.6
tornado==2.3
wsgiref==0.1.2
tox==1.4.2
......@@ -39,7 +39,7 @@ if os.name.lower() == 'nt':
setup(
name='lettuce',
version='0.2.8',
version='0.2.10',
description='Behaviour Driven Development for python',
author=u'Gabriel Falcao',
author_email='gabriel@nacaolivre.org',
......
......@@ -35,15 +35,37 @@ def prepare_stderr():
std = StringIO()
sys.stderr = std
def assert_lines(original, expected):
original = original.decode('utf-8') if isinstance(original, basestring) else original
assert_lines_unicode(original, expected)
def assert_lines_unicode(original, expected):
if isinstance(expected, unicode):
expected = expected.encode('utf-8')
if isinstance(original, unicode):
original = original.encode('utf-8')
expected_lines = expected.splitlines(1)
original_lines = original.splitlines(1)
if original != expected:
diff = ''.join(list(Differ().compare(expected.splitlines(1), original.splitlines(1))))
raise AssertionError, 'Output differed as follows:\n' + diff + "\nOutput was:\n" + original +"\nExpected was:\n"+expected
assert_equals(len(expected), len(original), 'Output appears equal, but of different lengths.')
comparison = Differ().compare(expected_lines, original_lines)
if isinstance(comparison, unicode):
expected = expected.encode('utf-8')
diff = u''.encode('utf-8').join(comparison)
msg = (u'Output differed as follows:\n{0}\n'
'Output was:\n{1}\nExpected was:\n{2}'.encode('utf-8'))
raise AssertionError(repr(msg.format(diff, original, expected)).replace(r'\n', '\n'))
assert_equals(
len(expected), len(original),
u'Output appears equal, but of different lengths.')
def assert_lines_with_traceback(one, other):
lines_one = one.splitlines()
......@@ -64,6 +86,7 @@ def assert_lines_with_traceback(one, other):
assert_unicode_equals(len(lines_one), len(lines_other))
def assert_unicode_equals(original, expected):
if isinstance(original, basestring):
original = original.decode('utf-8')
......@@ -89,4 +112,3 @@ def assert_stdout_lines_with_traceback(other):
def assert_stderr_lines_with_traceback(other):
assert_lines_with_traceback(sys.stderr.getvalue(), other)
Feature: With Header
In order to test backgrounds
As lettuce maintainer
I want to make sure it works with headers
Background:
Given the variable "X" holds 2
Scenario: multiplication changing the value
Given the variable "X" is equal to 2
When the variable "X" holds 10
Then the variable "X" times 5 is equal to 50
And the variable "X" is equal to 10
Scenario: multiplication with value set from background
Given the variable "X" is equal to 2
Then the variable "X" times 5 is equal to 10
And the variable "X" is equal to 2
Feature: Without Header
Background:
Given the variable "X" holds 2
Scenario: multiplication changing the value
Given the variable "X" is equal to 2
When the variable "X" holds 10
Then the variable "X" times 5 is equal to 50
And the variable "X" is equal to 10
Scenario: multiplication with value set from background
Given the variable "X" is equal to 2
Then the variable "X" times 5 is equal to 10
And the variable "X" is equal to 2
Feature: Simple and successful
As the Lettuce maintainer
In order to make sure the output is pretty
I want to automate its test
Background:
Given the variable "X" holds 2
Scenario: multiplication changing the value
Given the variable "X" is equal to 2
# -*- coding: utf-8 -*-
from lettuce import step
@step(u'Given the variable "([^"]*)" is equal to 2')
def given_the_variable_group1_is_equal_to_2(step, group1):
pass
@step(u'When the variable "([^"]*)" holds 10')
def when_the_variable_group1_holds_10(step, group1):
pass
@step(u'Then the variable "([^"]*)" times 5 is equal to 50')
def then_the_variable_group1_times_5_is_equal_to_50(step, group1):
pass
@step(u'And the variable "([^"]*)" is equal to 10')
def and_the_variable_group1_is_equal_to_10(step, group1):
pass
@step(u'Then the variable "([^"]*)" times 5 is equal to 10')
def then_the_variable_group1_times_5_is_equal_to_10(step, group1):
pass
@step(u'And the variable "([^"]*)" is equal to 2')
def and_the_variable_group1_is_equal_to_2(step, group1):
pass
# -*- coding: utf-8 -*-
# language: fr
Fonctionnalité: Test complet
En tant que programmeur
Je veux valider les tests
Scénario: On ne fait rien
Quand je ne fait rien
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from lettuce import step
@step(u'Quand Je ne fait rien')
def quand_je_ne_fait_rien(step):
pass
# -*- coding: utf-8 -*-
# language: fr
Fonctionnalité: Plan de scénario en français
En tant que programmeur
Je veux tester les plans de scénario
Et surtout les sorties
Plan du Scénario: Faire la sieste
Soit un après midi de <mois>
Quand je veux faire la sieste
Je peux aller <lieux>
Exemples:
| mois | lieux |
| janvier | près de la cheminé|
| aôut | dans le transat |
| octobre | dans le canapé |
# -*- coding: utf-8 -*-
# language: fr
Fonction: Plan de scénario en français
En tant que programmeur
Je veux tester les plans de scénario
Et surtout les sorties
Plan du Scénario: Faire la sieste
Soit un après midi de <mois>
Quand je veux faire la sieste
Je peux aller <lieux>
Exemples:
| mois | lieux |
| janvier | près de la cheminé|
| aôut | dans le transat |
| octobre | dans le canapé |
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from lettuce import step
def assert_in(dado, possibilidades):
assert dado in possibilidades, \
u"%r deveria estar nas possibilidades: %r" % (
dado, possibilidades
)
@step(u'un après midi de (.*)')
def un_apres_midi(step, groupe):
possibilites = [
u'janvier',
u'aôut',
u'octobre'
]
assert_in(groupe, possibilites)
@step(u'je veux faire la sieste')
def je_veux_dormir(step):
pass
@step(u'je peux aller (.*)')
def lieux_de_sieste(step, groupe):
possibilites = [
u'près de la cheminé',
u'dans le transat',
u'dans le canapé'
]
assert_in(groupe, possibilites)
@step(u'fico feliz em ver (.*)')
def fico_feliz_em_ver(step, grupo):
possibilidades = [
'funcional',
u'também',
'com unicode !'
]
assert_in(grupo, possibilidades)
# -*- coding: utf-8 -*-
# language: fr
Fonctionnalité: Test des sorties, avec table
En tant que programmeur
Je veux tester les sorties de scénario avec table
Scénario: NE rien faire, mais avec des tables
Soit les éléments suivant
| id | élément |
| 50 | Un |
| 59 | 42 |
| 29 | sieste |
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from lettuce import step
@step(u'Soit les éléments suivant')
def brinco_com_os_seguintes_itens(step):
pass
# -*- coding: utf-8 -*-
# <Lettuce - Behaviour Driven Development for python>
# Copyright (C) <2010-2012> Gabriel Falcão <gabriel@nacaolivre.org>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from os.path import dirname, abspath, join
from nose.tools import with_setup
from tests.asserts import prepare_stdout
from tests.asserts import assert_stdout_lines
from lettuce import Runner
current_dir = abspath(dirname(__file__))
join_path = lambda *x: join(current_dir, *x)
@with_setup(prepare_stdout)
def test_output_with_success_colorless():
"Language: fr -> sucess colorless"
runner = Runner(join_path('fr', 'success', 'dumb.feature'), verbosity=3)
runner.run()
assert_stdout_lines(
u"\n"
u"Fonctionnalité: Test complet # tests/functional/language_specific_features/fr/success/dumb.feature:3\n"
u" En tant que programmeur # tests/functional/language_specific_features/fr/success/dumb.feature:4\n"
u" Je veux valider les tests # tests/functional/language_specific_features/fr/success/dumb.feature:5\n"
u"\n"
u" Scénario: On ne fait rien # tests/functional/language_specific_features/fr/success/dumb.feature:7\n"
u" Quand je ne fait rien # tests/functional/language_specific_features/fr/success/dumb_steps.py:6\n"
u"\n"
u"1 feature (1 passed)\n"
u"1 scenario (1 passed)\n"
u"1 step (1 passed)\n"
)
@with_setup(prepare_stdout)
def test_output_of_table_with_success_colorless():
"Language: fr -> sucess table colorless"
runner = Runner(join_path('fr', 'success', 'table.feature'), verbosity=3)
runner.run()
assert_stdout_lines(
u"\n"
u"Fonctionnalité: Test des sorties, avec table # tests/functional/language_specific_features/fr/success/table.feature:4\n"
u" En tant que programmeur # tests/functional/language_specific_features/fr/success/table.feature:5\n"
u" Je veux tester les sorties de scénario avec table # tests/functional/language_specific_features/fr/success/table.feature:6\n"
u"\n"
u" Scénario: NE rien faire, mais avec des tables # tests/functional/language_specific_features/fr/success/table.feature:8\n"
u" Soit les éléments suivant # tests/functional/language_specific_features/fr/success/table_steps.py:6\n"
u" | id | élément |\n"
u" | 50 | Un |\n"
u" | 59 | 42 |\n"
u" | 29 | sieste |\n"
u"\n"
u"1 feature (1 passed)\n"
u"1 scenario (1 passed)\n"
u"1 step (1 passed)\n"
)
@with_setup(prepare_stdout)
def test_output_outlines_success_colorless():
"Language: fr -> sucess outlines colorless"
runner = Runner(join_path('fr', 'success', 'outlines.feature'), verbosity=3)
runner.run()
assert_stdout_lines(
u'\n'
u'Fonctionnalité: Plan de scénario en français # tests/functional/language_specific_features/fr/success/outlines.feature:4\n'
u' En tant que programmeur # tests/functional/language_specific_features/fr/success/outlines.feature:5\n'
u' Je veux tester les plans de scénario # tests/functional/language_specific_features/fr/success/outlines.feature:6\n'
u' Et surtout les sorties # tests/functional/language_specific_features/fr/success/outlines.feature:7\n'
u'\n'
u' Plan de Scénario: Faire la sieste # tests/functional/language_specific_features/fr/success/outlines.feature:9\n'
u' Soit un après midi de <mois> # tests/functional/language_specific_features/fr/success/outlines_steps.py:13\n'
u' Quand je veux faire la sieste # tests/functional/language_specific_features/fr/success/outlines_steps.py:22\n'
u' Je peux aller <lieux> # tests/functional/language_specific_features/fr/success/outlines_steps.py:26\n'
u'\n'
u' Exemples:\n'
u' | mois | lieux |\n'
u' | janvier | près de la cheminé |\n'
u' | aôut | dans le transat |\n'
u' | octobre | dans le canapé |\n'
u'\n'
u'1 feature (1 passed)\n'
u'3 scenarios (3 passed)\n'
u'9 steps (9 passed)\n'
)
@with_setup(prepare_stdout)
def test_output_outlines_success_colorful():
"Language: fr -> sucess outlines colorful"
runner = Runner(join_path('fr', 'success', 'outlines.feature'), verbosity=4)
runner.run()
assert_stdout_lines(
u'\n'
u'\033[1;37mFonctionnalité: Plan de scénario en français \033[1;30m# tests/functional/language_specific_features/fr/success/outlines.feature:4\033[0m\n'
u'\033[1;37m En tant que programmeur \033[1;30m# tests/functional/language_specific_features/fr/success/outlines.feature:5\033[0m\n'
u'\033[1;37m Je veux tester les plans de scénario \033[1;30m# tests/functional/language_specific_features/fr/success/outlines.feature:6\033[0m\n'
u'\033[1;37m Et surtout les sorties \033[1;30m# tests/functional/language_specific_features/fr/success/outlines.feature:7\033[0m\n'
u'\n'
u'\033[1;37m Plan de Scénario: Faire la sieste \033[1;30m# tests/functional/language_specific_features/fr/success/outlines.feature:9\033[0m\n'
u'\033[0;36m Soit un après midi de <mois> \033[1;30m# tests/functional/language_specific_features/fr/success/outlines_steps.py:13\033[0m\n'
u'\033[0;36m Quand je veux faire la sieste \033[1;30m# tests/functional/language_specific_features/fr/success/outlines_steps.py:22\033[0m\n'
u'\033[0;36m Je peux aller <lieux> \033[1;30m# tests/functional/language_specific_features/fr/success/outlines_steps.py:26\033[0m\n'
u'\n'
u'\033[1;37m Exemples:\033[0m\n'
u'\033[0;36m \033[1;37m |\033[0;36m mois \033[1;37m |\033[0;36m lieux \033[1;37m |\033[0;36m\033[0m\n'
u'\033[1;32m \033[1;37m |\033[1;32m janvier\033[1;37m |\033[1;32m près de la cheminé\033[1;37m |\033[1;32m\033[0m\n'
u'\033[1;32m \033[1;37m |\033[1;32m aôut \033[1;37m |\033[1;32m dans le transat \033[1;37m |\033[1;32m\033[0m\n'
u'\033[1;32m \033[1;37m |\033[1;32m octobre\033[1;37m |\033[1;32m dans le canapé \033[1;37m |\033[1;32m\033[0m\n'
u'\n'
u'\033[1;37m1 feature (\033[1;32m1 passed\033[1;37m)\033[0m\n'
u'\033[1;37m3 scenarios (\033[1;32m3 passed\033[1;37m)\033[0m\n'
u'\033[1;37m9 steps (\033[1;32m9 passed\033[1;37m)\033[0m\n'
)
@with_setup(prepare_stdout)
def test_output_outlines2_success_colorful():
"Language: fr -> sucess outlines colorful, alternate name"
runner = Runner(join_path('fr', 'success', 'outlines2.feature'), verbosity=4)
runner.run()
assert_stdout_lines(
u'\n'
u'\033[1;37mFonctionnalité: Plan de scénario en français \033[1;30m# tests/functional/language_specific_features/fr/success/outlines2.feature:4\033[0m\n'
u'\033[1;37m En tant que programmeur \033[1;30m# tests/functional/language_specific_features/fr/success/outlines2.feature:5\033[0m\n'
u'\033[1;37m Je veux tester les plans de scénario \033[1;30m# tests/functional/language_specific_features/fr/success/outlines2.feature:6\033[0m\n'
u'\033[1;37m Et surtout les sorties \033[1;30m# tests/functional/language_specific_features/fr/success/outlines2.feature:7\033[0m\n'
u'\n'
u'\033[1;37m Plan de Scénario: Faire la sieste \033[1;30m# tests/functional/language_specific_features/fr/success/outlines2.feature:9\033[0m\n'
u'\033[0;36m Soit un après midi de <mois> \033[1;30m# tests/functional/language_specific_features/fr/success/outlines_steps.py:13\033[0m\n'
u'\033[0;36m Quand je veux faire la sieste \033[1;30m# tests/functional/language_specific_features/fr/success/outlines_steps.py:22\033[0m\n'
u'\033[0;36m Je peux aller <lieux> \033[1;30m# tests/functional/language_specific_features/fr/success/outlines_steps.py:26\033[0m\n'
u'\n'
u'\033[1;37m Exemples:\033[0m\n'
u'\033[0;36m \033[1;37m |\033[0;36m mois \033[1;37m |\033[0;36m lieux \033[1;37m |\033[0;36m\033[0m\n'
u'\033[1;32m \033[1;37m |\033[1;32m janvier\033[1;37m |\033[1;32m près de la cheminé\033[1;37m |\033[1;32m\033[0m\n'
u'\033[1;32m \033[1;37m |\033[1;32m aôut \033[1;37m |\033[1;32m dans le transat \033[1;37m |\033[1;32m\033[0m\n'
u'\033[1;32m \033[1;37m |\033[1;32m octobre\033[1;37m |\033[1;32m dans le canapé \033[1;37m |\033[1;32m\033[0m\n'
u'\n'
u'\033[1;37m1 feature (\033[1;32m1 passed\033[1;37m)\033[0m\n'
u'\033[1;37m3 scenarios (\033[1;32m3 passed\033[1;37m)\033[0m\n'
u'\033[1;37m9 steps (\033[1;32m9 passed\033[1;37m)\033[0m\n'
)
Feature: Failful Scenario Outline
As lettuce author
In order to finish the first release
I want to make scenario outlines work :)
I want to make scenario outlines work
Scenario Outline: fill a web form
Given I open browser at "http://www.my-website.com/"
......
Feature: Table Fail
Scenario: See it fail
Given I have a dumb step that passes
Given I have a dumb step that passes
And this one fails
......
Feature: Successful Scenario Outline
As lettuce author
In order to finish the first release
I want to make scenario outlines work :)
I want to make scenario outlines work
Scenario Outline: fill a web form
Given I open browser at "http://www.my-website.com/"
......
Feature: Table Success
Scenario: Add two numbers
Scenario: Add two numbers
Given I have 0 bucks
And that I have these items:
......
......@@ -14,16 +14,16 @@
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from lettuce import core
from sure import expect
from nose.tools import assert_equals
from nose.tools import assert_not_equals
STEP_WITH_TABLE = u'''
Given I have the following items in my shelf:
| name | description |
| Glass | a nice glass to drink grape juice |
| Pasta | a pasta to cook and eat with grape juice in the glass |
| name | description |
| Glass | a nice glass to drink grape juice |
| Pasta | a pasta to cook and eat with grape juice in the glass |
'''
......
......@@ -14,10 +14,12 @@
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from sure import that
from sure import that, expect
from lettuce import step
from lettuce.core import Scenario
from lettuce.core import Feature
from lettuce.core import Background
from lettuce.core import HashList
from nose.tools import assert_equals
FEATURE1 = """
......@@ -330,6 +332,48 @@ Feature: Redis database server
And M2 contains database 3
"""
FEATURE16 = """
Feature: Movie rental
As a rental store owner
I want to keep track of my clients
So that I can manage my business better
Background:
Given I have the following movies in my database:
| Name | Rating | New | Available |
| Matrix Revolutions | 4 stars | no | 6 |
| Iron Man 2 | 5 stars | yes | 11 |
And the following clients:
| Name |
| John Doe |
| Foo Bar |
Scenario: Renting a featured movie
Given the client 'John Doe' rents 'Iron Man 2'
Then there are 10 more left
Scenario: Renting an old movie
Given the client 'Foo Bar' rents 'Matrix Revolutions'
Then there are 5 more left
"""
FEATURE17 = """
Feature: Movie rental without MMF
Background:
Given I have the following movies in my database:
| Name | Rating | New | Available |
| Matrix Revolutions | 4 stars | no | 6 |
| Iron Man 2 | 5 stars | yes | 11 |
And the following clients:
| Name |
| John Doe |
| Foo Bar |
Scenario: Renting a featured movie
Given the client 'John Doe' rents 'Iron Man 2'
Then there are 10 more left
"""
def test_feature_has_repr():
"Feature implements __repr__ nicely"
......@@ -569,6 +613,7 @@ def test_scenarios_with_extra_whitespace():
def test_scenarios_parsing():
"Tags are parsed correctly"
feature = Feature.from_string(FEATURE15)
scenarios_and_tags = [(s.name, s.tags) for s in feature.scenarios]
......@@ -591,3 +636,75 @@ def test_scenarios_parsing():
('Slave -> Master promotion', []),
('Restart farm', [u'restart_farm']),
])
def test_background_parsing_with_mmf():
feature = Feature.from_string(FEATURE16)
expect(feature.description).to.equal(
"As a rental store owner\n"
"I want to keep track of my clients\n"
"So that I can manage my business better"
)
expect(feature).to.have.property('background').being.a(Background)
expect(feature.background).to.have.property('steps')
expect(feature.background.steps).to.have.length_of(2)
step1, step2 = feature.background.steps
step1.sentence.should.equal(
'Given I have the following movies in my database:')
step1.hashes.should.equal(HashList(step1, [
{
u'Available': u'6',
u'Rating': u'4 stars',
u'Name': u'Matrix Revolutions',
u'New': u'no',
},
{
u'Available': u'11',
u'Rating': u'5 stars',
u'Name': u'Iron Man 2',
u'New': u'yes',
},
]))
step2.sentence.should.equal(
'And the following clients:')
step2.hashes.should.equal(HashList(step2, [
{u'Name': u'John Doe'},
{u'Name': u'Foo Bar'},
]))
def test_background_parsing_without_mmf():
feature = Feature.from_string(FEATURE17)
expect(feature.description).to.be.empty
expect(feature).to.have.property('background').being.a(Background)
expect(feature.background).to.have.property('steps')
expect(feature.background.steps).to.have.length_of(2)
step1, step2 = feature.background.steps
step1.sentence.should.equal(
'Given I have the following movies in my database:')
step1.hashes.should.equal(HashList(step1, [
{
u'Available': u'6',
u'Rating': u'4 stars',
u'Name': u'Matrix Revolutions',
u'New': u'no',
},
{
u'Available': u'11',
u'Rating': u'5 stars',
u'Name': u'Iron Man 2',
u'New': u'yes',
},
]))
step2.sentence.should.equal(
'And the following clients:')
step2.hashes.should.equal(HashList(step2, [
{u'Name': u'John Doe'},
{u'Name': u'Foo Bar'},
]))
......@@ -22,7 +22,7 @@ from mox import Mox
def test_has_version():
"A nice python module is supposed to have a version"
assert_equals(lettuce.version, '0.2.8')
assert_equals(lettuce.version, '0.2.10')
def test_has_release():
......
......@@ -14,6 +14,7 @@
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import sys
from mox import Mox
from nose.tools import assert_equals
......@@ -229,10 +230,14 @@ def test_world_should_be_able_to_absorb_classs():
u"world should be able to absorb class"
assert not hasattr(world, 'MyClass')
@world.absorb
if sys.version_info < (2, 6):
return
class MyClass:
pass
world.absorb(MyClass)
assert hasattr(world, 'MyClass')
assert_equals(world.MyClass, MyClass)
......
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