Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
L
lettuce
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
edx
lettuce
Commits
89e345a4
Commit
89e345a4
authored
Sep 21, 2012
by
Gabriel Falcao
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
starting to implement background
parent
95574fd4
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
116 additions
and
10 deletions
+116
-10
lettuce/core.py
+61
-9
lettuce/languages.py
+16
-0
tests/unit/test_feature_parser.py
+39
-1
No files found.
lettuce/core.py
View file @
89e345a4
...
@@ -88,6 +88,7 @@ class Language(object):
...
@@ -88,6 +88,7 @@ class Language(object):
examples
=
'Examples|Scenarios'
examples
=
'Examples|Scenarios'
scenario_outline
=
'Scenario Outline'
scenario_outline
=
'Scenario Outline'
scenario_separator
=
'Scenario( Outline)?'
scenario_separator
=
'Scenario( Outline)?'
background
=
"Background"
def
__init__
(
self
,
code
=
u'en'
):
def
__init__
(
self
,
code
=
u'en'
):
self
.
code
=
code
self
.
code
=
code
...
@@ -832,6 +833,31 @@ class Scenario(object):
...
@@ -832,6 +833,31 @@ class Scenario(object):
return
scenario
return
scenario
class
Background
(
object
):
def
__init__
(
self
,
lines
,
feature
,
with_file
=
None
,
original_string
=
None
,
language
=
None
):
self
.
steps
=
Step
.
many_from_lines
(
lines
,
with_file
,
original_string
)
self
.
feature
=
feature
self
.
original_string
=
original_string
self
.
language
=
language
@classmethod
def
from_string
(
new_background
,
lines
,
feature
,
with_file
=
None
,
original_string
=
None
,
language
=
None
):
return
new_background
(
lines
,
feature
,
with_file
=
with_file
,
original_string
=
original_string
,
language
=
language
)
class
Feature
(
object
):
class
Feature
(
object
):
""" Object that represents a feature."""
""" Object that represents a feature."""
described_at
=
None
described_at
=
None
...
@@ -845,7 +871,9 @@ class Feature(object):
...
@@ -845,7 +871,9 @@ class Feature(object):
self
.
name
=
name
self
.
name
=
name
self
.
language
=
language
self
.
language
=
language
self
.
scenarios
,
self
.
description
=
self
.
_parse_remaining_lines
(
(
self
.
background
,
self
.
scenarios
,
self
.
description
)
=
self
.
_parse_remaining_lines
(
remaining_lines
,
remaining_lines
,
original_string
,
original_string
,
with_file
)
with_file
)
...
@@ -863,10 +891,13 @@ class Feature(object):
...
@@ -863,10 +891,13 @@ class Feature(object):
@property
@property
def
max_length
(
self
):
def
max_length
(
self
):
max_length
=
strings
.
column_width
(
u"
%
s:
%
s"
%
(
self
.
language
.
first_of_feature
,
self
.
name
))
max_length
=
strings
.
column_width
(
u"
%
s:
%
s"
%
(
self
.
language
.
first_of_feature
,
self
.
name
))
if
max_length
==
0
:
if
max_length
==
0
:
# in case feature has two keywords
# in case feature has two keywords
max_length
=
strings
.
column_width
(
u"
%
s:
%
s"
%
(
self
.
language
.
last_of_feature
,
self
.
name
))
max_length
=
strings
.
column_width
(
u"
%
s:
%
s"
%
(
self
.
language
.
last_of_feature
,
self
.
name
))
for
line
in
self
.
description
.
splitlines
():
for
line
in
self
.
description
.
splitlines
():
length
=
strings
.
column_width
(
line
.
strip
())
+
Scenario
.
indentation
length
=
strings
.
column_width
(
line
.
strip
())
+
Scenario
.
indentation
...
@@ -894,9 +925,12 @@ class Feature(object):
...
@@ -894,9 +925,12 @@ class Feature(object):
filename
=
self
.
described_at
.
file
filename
=
self
.
described_at
.
file
line
=
self
.
described_at
.
line
line
=
self
.
described_at
.
line
head
=
strings
.
rfill
(
self
.
get_head
(),
length
,
append
=
u"#
%
s:
%
d
\n
"
%
(
filename
,
line
))
head
=
strings
.
rfill
(
self
.
get_head
(),
length
,
for
description
,
line
in
zip
(
self
.
description
.
splitlines
(),
self
.
described_at
.
description_at
):
append
=
u"#
%
s:
%
d
\n
"
%
(
filename
,
line
))
head
+=
strings
.
rfill
(
u"
%
s"
%
description
,
length
,
append
=
u"#
%
s:
%
d
\n
"
%
(
filename
,
line
))
for
description
,
line
in
zip
(
self
.
description
.
splitlines
(),
self
.
described_at
.
description_at
):
head
+=
strings
.
rfill
(
u"
%
s"
%
description
,
length
,
append
=
u"#
%
s:
%
d
\n
"
%
(
filename
,
line
))
return
head
return
head
...
@@ -949,9 +983,19 @@ class Feature(object):
...
@@ -949,9 +983,19 @@ class Feature(object):
stripped
=
REP
.
tag_strip_regex
.
sub
(
''
,
string
)
stripped
=
REP
.
tag_strip_regex
.
sub
(
''
,
string
)
return
stripped
return
stripped
def
_extract_desc_and_bg
(
self
,
joined
):
if
not
re
.
search
(
self
.
language
.
background
,
joined
):
return
joined
,
None
parts
=
strings
.
split_wisely
(
joined
,
self
.
language
.
background
)
description
=
parts
.
pop
(
0
)
return
description
,
parts
def
_parse_remaining_lines
(
self
,
lines
,
original_string
,
with_file
=
None
):
def
_parse_remaining_lines
(
self
,
lines
,
original_string
,
with_file
=
None
):
# replacing occurrences of Scenario Outline, with just "Scenario"
joined
=
u"
\n
"
.
join
(
lines
[
1
:])
joined
=
u"
\n
"
.
join
(
lines
[
1
:])
# replacing occurrences of Scenario Outline, with just "Scenario"
scenario_prefix
=
u'
%
s:'
%
self
.
language
.
first_of_scenario
scenario_prefix
=
u'
%
s:'
%
self
.
language
.
first_of_scenario
regex
=
re
.
compile
(
regex
=
re
.
compile
(
u"
%
s:
\
s"
%
self
.
language
.
scenario_separator
,
re
.
U
|
re
.
I
|
re
.
DOTALL
)
u"
%
s:
\
s"
%
self
.
language
.
scenario_separator
,
re
.
U
|
re
.
I
|
re
.
DOTALL
)
...
@@ -961,9 +1005,17 @@ class Feature(object):
...
@@ -961,9 +1005,17 @@ class Feature(object):
parts
=
strings
.
split_wisely
(
joined
,
scenario_prefix
)
parts
=
strings
.
split_wisely
(
joined
,
scenario_prefix
)
description
=
u""
description
=
u""
background
=
None
if
not
re
.
search
(
"^"
+
scenario_prefix
,
joined
):
if
not
re
.
search
(
"^"
+
scenario_prefix
,
joined
):
description
=
parts
[
0
]
description
,
background_lines
=
self
.
_extract_desc_and_bg
(
parts
[
0
])
background
=
background_lines
and
Background
.
from_string
(
background_lines
,
self
,
with_file
=
with_file
,
original_string
=
original_string
,
language
=
self
.
language
,
)
or
None
parts
.
pop
(
0
)
parts
.
pop
(
0
)
prefix
=
self
.
language
.
first_of_scenario
prefix
=
self
.
language
.
first_of_scenario
...
@@ -994,7 +1046,7 @@ class Feature(object):
...
@@ -994,7 +1046,7 @@ class Feature(object):
current_scenario
=
Scenario
.
from_string
(
current
,
**
params
)
current_scenario
=
Scenario
.
from_string
(
current
,
**
params
)
scenarios
.
append
(
current_scenario
)
scenarios
.
append
(
current_scenario
)
return
scenarios
,
description
return
background
,
scenarios
,
description
def
run
(
self
,
scenarios
=
None
,
ignore_case
=
True
,
tags
=
None
,
random
=
False
):
def
run
(
self
,
scenarios
=
None
,
ignore_case
=
True
,
tags
=
None
,
random
=
False
):
call_hook
(
'before_each'
,
'feature'
,
self
)
call_hook
(
'before_each'
,
'feature'
,
self
)
...
...
lettuce/languages.py
View file @
89e345a4
...
@@ -24,6 +24,7 @@ LANGUAGES = {
...
@@ -24,6 +24,7 @@ LANGUAGES = {
'scenario'
:
u'Scenario'
,
'scenario'
:
u'Scenario'
,
'scenario_outline'
:
u'Scenario Outline'
,
'scenario_outline'
:
u'Scenario Outline'
,
'scenario_separator'
:
u'(Scenario Outline|Scenario)'
,
'scenario_separator'
:
u'(Scenario Outline|Scenario)'
,
'background'
:
u'(?:Background)'
,
},
},
'pt-br'
:
{
'pt-br'
:
{
'examples'
:
u'Exemplos|Cenários'
,
'examples'
:
u'Exemplos|Cenários'
,
...
@@ -33,6 +34,7 @@ LANGUAGES = {
...
@@ -33,6 +34,7 @@ LANGUAGES = {
'scenario'
:
u'Cenário|Cenario'
,
'scenario'
:
u'Cenário|Cenario'
,
'scenario_outline'
:
u'Esquema do Cenário|Esquema do Cenario'
,
'scenario_outline'
:
u'Esquema do Cenário|Esquema do Cenario'
,
'scenario_separator'
:
u'(Esquema do Cenário|Esquema do Cenario|Cenario|Cenário)'
,
'scenario_separator'
:
u'(Esquema do Cenário|Esquema do Cenario|Cenario|Cenário)'
,
'background'
:
u'(?:Contexto|Considerações)'
,
},
},
'pl'
:
{
'pl'
:
{
'examples'
:
u'Przykład'
,
'examples'
:
u'Przykład'
,
...
@@ -42,6 +44,7 @@ LANGUAGES = {
...
@@ -42,6 +44,7 @@ LANGUAGES = {
'scenario'
:
u'Scenariusz'
,
'scenario'
:
u'Scenariusz'
,
'scenario_outline'
:
u'Zarys Scenariusza'
,
'scenario_outline'
:
u'Zarys Scenariusza'
,
'scenario_separator'
:
u'(Zarys Scenariusza|Scenariusz)'
,
'scenario_separator'
:
u'(Zarys Scenariusza|Scenariusz)'
,
'background'
:
u'(?:Background)'
,
},
},
'ca'
:
{
'ca'
:
{
'examples'
:
u'Exemples'
,
'examples'
:
u'Exemples'
,
...
@@ -51,6 +54,7 @@ LANGUAGES = {
...
@@ -51,6 +54,7 @@ LANGUAGES = {
'scenario'
:
u'Escenari'
,
'scenario'
:
u'Escenari'
,
'scenario_outline'
:
u"Esquema d'Escenari"
,
'scenario_outline'
:
u"Esquema d'Escenari"
,
'scenario_separator'
:
u"(Esquema d'Escenari|Escenari)"
,
'scenario_separator'
:
u"(Esquema d'Escenari|Escenari)"
,
'background'
:
u'(?:Background)'
,
},
},
'es'
:
{
'es'
:
{
'examples'
:
u'Ejemplos'
,
'examples'
:
u'Ejemplos'
,
...
@@ -60,6 +64,7 @@ LANGUAGES = {
...
@@ -60,6 +64,7 @@ LANGUAGES = {
'scenario'
:
u'Escenario'
,
'scenario'
:
u'Escenario'
,
'scenario_outline'
:
u'Esquema de Escenario'
,
'scenario_outline'
:
u'Esquema de Escenario'
,
'scenario_separator'
:
u'(Esquema de Escenario|Escenario)'
,
'scenario_separator'
:
u'(Esquema de Escenario|Escenario)'
,
'background'
:
u'(?:Contexto|Consideraciones)'
,
},
},
'hu'
:
{
'hu'
:
{
'examples'
:
u'Példák'
,
'examples'
:
u'Példák'
,
...
@@ -69,6 +74,7 @@ LANGUAGES = {
...
@@ -69,6 +74,7 @@ LANGUAGES = {
'scenario'
:
u'Forgatókönyv'
,
'scenario'
:
u'Forgatókönyv'
,
'scenario_outline'
:
u'Forgatókönyv vázlat'
,
'scenario_outline'
:
u'Forgatókönyv vázlat'
,
'scenario_separator'
:
u'(Forgatókönyv|Forgatókönyv vázlat)'
,
'scenario_separator'
:
u'(Forgatókönyv|Forgatókönyv vázlat)'
,
'background'
:
u'(?:Background)'
,
},
},
'fr'
:
{
'fr'
:
{
'examples'
:
u'Exemples|Scénarios'
,
'examples'
:
u'Exemples|Scénarios'
,
...
@@ -78,6 +84,7 @@ LANGUAGES = {
...
@@ -78,6 +84,7 @@ LANGUAGES = {
'scenario'
:
u'Scénario'
,
'scenario'
:
u'Scénario'
,
'scenario_outline'
:
u'Plan de Scénario|Plan du 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)'
,
'scenario_separator'
:
u'(Plan de Scénario|Plan du Scénario|Scénario)'
,
'background'
:
u'(?:Background)'
,
},
},
'de'
:
{
'de'
:
{
'examples'
:
u'Beispiele|Szenarios'
,
'examples'
:
u'Beispiele|Szenarios'
,
...
@@ -87,6 +94,7 @@ LANGUAGES = {
...
@@ -87,6 +94,7 @@ LANGUAGES = {
'scenario'
:
u'Szenario'
,
'scenario'
:
u'Szenario'
,
'scenario_outline'
:
u'Szenario-Zusammenfassung|Zusammenfassung'
,
'scenario_outline'
:
u'Szenario-Zusammenfassung|Zusammenfassung'
,
'scenario_separator'
:
u'(Szenario-Zusammenfassung|Zusammenfassung)'
,
'scenario_separator'
:
u'(Szenario-Zusammenfassung|Zusammenfassung)'
,
'background'
:
u'(?:Background)'
,
},
},
'ja'
:
{
'ja'
:
{
'examples'
:
u'例'
,
'examples'
:
u'例'
,
...
@@ -96,6 +104,7 @@ LANGUAGES = {
...
@@ -96,6 +104,7 @@ LANGUAGES = {
'scenario'
:
u'シナリオ'
,
'scenario'
:
u'シナリオ'
,
'scenario_outline'
:
u'シナリオアウトライン|シナリオテンプレート|テンプレ|シナリオテンプレ'
,
'scenario_outline'
:
u'シナリオアウトライン|シナリオテンプレート|テンプレ|シナリオテンプレ'
,
'scenario_separator'
:
u'(シナリオ|シナリオアウトライン|シナリオテンプレート|テンプレ|シナリオテンプレ)'
,
'scenario_separator'
:
u'(シナリオ|シナリオアウトライン|シナリオテンプレート|テンプレ|シナリオテンプレ)'
,
'background'
:
u'(?:Background)'
,
},
},
'tr'
:
{
'tr'
:
{
'examples'
:
u'Örnekler'
,
'examples'
:
u'Örnekler'
,
...
@@ -105,6 +114,7 @@ LANGUAGES = {
...
@@ -105,6 +114,7 @@ LANGUAGES = {
'scenario'
:
u'Senaryo'
,
'scenario'
:
u'Senaryo'
,
'scenario_outline'
:
u'Senaryo taslağı|Senaryo Taslağı'
,
'scenario_outline'
:
u'Senaryo taslağı|Senaryo Taslağı'
,
'scenario_separator'
:
u'(Senaryo taslağı|Senaryo Taslağı|Senaryo)'
,
'scenario_separator'
:
u'(Senaryo taslağı|Senaryo Taslağı|Senaryo)'
,
'background'
:
u'(?:Background)'
,
},
},
'zh-CN'
:
{
'zh-CN'
:
{
'examples'
:
u'例如|场景集'
,
'examples'
:
u'例如|场景集'
,
...
@@ -114,6 +124,7 @@ LANGUAGES = {
...
@@ -114,6 +124,7 @@ LANGUAGES = {
'scenario'
:
u'场景'
,
'scenario'
:
u'场景'
,
'scenario_outline'
:
u'场景模板'
,
'scenario_outline'
:
u'场景模板'
,
'scenario_separator'
:
u'(场景模板|场景)'
,
'scenario_separator'
:
u'(场景模板|场景)'
,
'background'
:
u'(?:背景)'
,
},
},
'zh-TW'
:
{
'zh-TW'
:
{
'examples'
:
u'例如|場景集'
,
'examples'
:
u'例如|場景集'
,
...
@@ -123,6 +134,7 @@ LANGUAGES = {
...
@@ -123,6 +134,7 @@ LANGUAGES = {
'scenario'
:
u'場景'
,
'scenario'
:
u'場景'
,
'scenario_outline'
:
u'場景模板'
,
'scenario_outline'
:
u'場景模板'
,
'scenario_separator'
:
u'(場景模板|場景)'
,
'scenario_separator'
:
u'(場景模板|場景)'
,
'background'
:
u'(?:背景)'
,
},
},
'ru'
:
{
'ru'
:
{
'examples'
:
u'Примеры|Сценарии'
,
'examples'
:
u'Примеры|Сценарии'
,
...
@@ -132,6 +144,7 @@ LANGUAGES = {
...
@@ -132,6 +144,7 @@ LANGUAGES = {
'scenario'
:
u'Сценарий'
,
'scenario'
:
u'Сценарий'
,
'scenario_outline'
:
u'Структура сценария'
,
'scenario_outline'
:
u'Структура сценария'
,
'scenario_separator'
:
u'(Структура сценария|Сценарий)'
,
'scenario_separator'
:
u'(Структура сценария|Сценарий)'
,
'background'
:
u'(?:Background)'
,
},
},
'uk'
:
{
'uk'
:
{
'examples'
:
u'Приклади|Сценарії'
,
'examples'
:
u'Приклади|Сценарії'
,
...
@@ -141,6 +154,7 @@ LANGUAGES = {
...
@@ -141,6 +154,7 @@ LANGUAGES = {
'scenario'
:
u'Сценарій'
,
'scenario'
:
u'Сценарій'
,
'scenario_outline'
:
u'Структура сценарію'
,
'scenario_outline'
:
u'Структура сценарію'
,
'scenario_separator'
:
u'(Структура сценарію|Сценарій)'
,
'scenario_separator'
:
u'(Структура сценарію|Сценарій)'
,
'background'
:
u'(?:Background)'
,
},
},
'it'
:
{
'it'
:
{
'examples'
:
u'Esempi|Scenari|Scenarii'
,
'examples'
:
u'Esempi|Scenari|Scenarii'
,
...
@@ -150,6 +164,7 @@ LANGUAGES = {
...
@@ -150,6 +164,7 @@ LANGUAGES = {
'scenario'
:
u'Scenario'
,
'scenario'
:
u'Scenario'
,
'scenario_outline'
:
u'Schema di Scenario|Piano di Scenario'
,
'scenario_outline'
:
u'Schema di Scenario|Piano di Scenario'
,
'scenario_separator'
:
u'(Schema di Scenario|Piano di Scenario|Scenario)'
,
'scenario_separator'
:
u'(Schema di Scenario|Piano di Scenario|Scenario)'
,
'background'
:
u'(?:Background)'
,
},
},
'no'
:
{
'no'
:
{
'examples'
:
u'Eksempler'
,
'examples'
:
u'Eksempler'
,
...
@@ -159,5 +174,6 @@ LANGUAGES = {
...
@@ -159,5 +174,6 @@ LANGUAGES = {
'scenario'
:
u'Situasjon'
,
'scenario'
:
u'Situasjon'
,
'scenario_outline'
:
u'Situasjon Oversikt'
,
'scenario_outline'
:
u'Situasjon Oversikt'
,
'scenario_separator'
:
u'(Situasjon Oversikt|Situasjon)'
,
'scenario_separator'
:
u'(Situasjon Oversikt|Situasjon)'
,
'background'
:
u'(?:Background)'
,
}
}
}
}
tests/unit/test_feature_parser.py
View file @
89e345a4
...
@@ -14,10 +14,11 @@
...
@@ -14,10 +14,11 @@
#
#
# You should have received a copy of the GNU General Public License
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# 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
import
step
from
lettuce.core
import
Scenario
from
lettuce.core
import
Scenario
from
lettuce.core
import
Feature
from
lettuce.core
import
Feature
from
lettuce.core
import
Background
from
nose.tools
import
assert_equals
from
nose.tools
import
assert_equals
FEATURE1
=
"""
FEATURE1
=
"""
...
@@ -330,6 +331,31 @@ Feature: Redis database server
...
@@ -330,6 +331,31 @@ Feature: Redis database server
And M2 contains database 3
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
"""
def
test_feature_has_repr
():
def
test_feature_has_repr
():
"Feature implements __repr__ nicely"
"Feature implements __repr__ nicely"
...
@@ -569,6 +595,7 @@ def test_scenarios_with_extra_whitespace():
...
@@ -569,6 +595,7 @@ def test_scenarios_with_extra_whitespace():
def
test_scenarios_parsing
():
def
test_scenarios_parsing
():
"Tags are parsed correctly"
feature
=
Feature
.
from_string
(
FEATURE15
)
feature
=
Feature
.
from_string
(
FEATURE15
)
scenarios_and_tags
=
[(
s
.
name
,
s
.
tags
)
for
s
in
feature
.
scenarios
]
scenarios_and_tags
=
[(
s
.
name
,
s
.
tags
)
for
s
in
feature
.
scenarios
]
...
@@ -591,3 +618,14 @@ def test_scenarios_parsing():
...
@@ -591,3 +618,14 @@ def test_scenarios_parsing():
(
'Slave -> Master promotion'
,
[]),
(
'Slave -> Master promotion'
,
[]),
(
'Restart farm'
,
[
u'restart_farm'
]),
(
'Restart farm'
,
[
u'restart_farm'
]),
])
])
def
test_background_parsing
():
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
)
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment