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
ae074e49
Commit
ae074e49
authored
Feb 03, 2011
by
Paul Bonser
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
add multiline string support
Includes tests, implementation, and documentation
parent
1e9cb104
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
226 additions
and
5 deletions
+226
-5
docs/contents.rst
+1
-0
docs/index.rst
+1
-0
docs/tutorial/multiline.rst
+118
-0
lettuce/core.py
+16
-5
lettuce/strings.py
+14
-0
tests/unit/test_step_parsing.py
+76
-0
No files found.
docs/contents.rst
View file @
ae074e49
...
@@ -13,6 +13,7 @@ Lettuce documentation contents
...
@@ -13,6 +13,7 @@ Lettuce documentation contents
intro/wtf
intro/wtf
tutorial/simple
tutorial/simple
tutorial/tables
tutorial/tables
tutorial/multiline
tutorial/scenario-outlines
tutorial/scenario-outlines
tutorial/steps-from-step-definitions
tutorial/steps-from-step-definitions
reference/features
reference/features
...
...
docs/index.rst
View file @
ae074e49
...
@@ -104,6 +104,7 @@ walkthrough
...
@@ -104,6 +104,7 @@ 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>`
* :ref:`multi-line strings <tutorial-multiline>`
* :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>`
...
...
docs/tutorial/multiline.rst
0 → 100644
View file @
ae074e49
.. _tutorial-multiline:
multi-line strings
===========================
Now imagine you are writing an application which manipulates
strings. When writing the tests, you may find yourself wanting to put
multi-line strings in your steps.
Multi-line strings will do the trick
.. highlight:: ruby
::
Feature: Split a string into multiple lines on spaces
In order to make strings more readable
As a user
I want to have words split into their own lines
Scenario: Split small-ish string
Given I have the string "one two three four five"
When I ask to have the string split into lines
Then I should see the following:
"""
one
two
three
four
five
"""
A line with nothing but three quotes (""") is used to indicate the
beginning and the end of a multi-line string.
Now, let's define a step that knows how to use this.
.. highlight:: python
::
from lettuce import step
@step('I should see the following:')
def i_should_see_the_following(step):
assert step.multiline == """one
two
three
four
five"""
Nice and straightforward.
Notice that leading spaces are stripped, and there's not a newline at
the beginning or end. This is due to the way that the parser strips
blank lines and leading and trailing whitespace.
If you need blank lines leading or trailing whitespace, you can
include lines which start and/or end with double quote, and they will
be concatenated with the other multiline lines, with the quotes
stripped off and their whitespace preserved.
For example
.. highlight:: ruby
::
Feature: Split a string into multiple lines on spaces
In order to make strings more readable
As a user
I want to have words split into their own lines
Scenario: Split small-ish string
Given I have the string "one two three four five"
When I ask to have the string split into lines
Then I should see the following:
"""
" one
" two "
" three "
" four "
" five "
"
"""
Which we can verify like so:
.. highlight:: python
::
from lettuce import step
@step('I should see the following:')
def i_should_see_the_following(step):
assert step.multiline == '\n'.append([
' one',
' two ',
' three ',
' four ',
' five ',
''])
Admittedly, this is a hack, but there's no clean way to preserve
whitespace in only one section of a feature definition in the current
parser implementation.
Note that the first line doesn't have any whitespace at the end, and
thus doesn't need to have a quote at the end of it.
Also note that if you want a double quote at the beginning of a line
in your string, you'll have to start your line with two double quotes,
since the first one will be stripped off.
\ No newline at end of file
lettuce/core.py
View file @
ae074e49
...
@@ -149,7 +149,7 @@ class Step(object):
...
@@ -149,7 +149,7 @@ class Step(object):
self
.
sentence
=
sentence
self
.
sentence
=
sentence
self
.
original_sentence
=
sentence
self
.
original_sentence
=
sentence
self
.
_remaining_lines
=
remaining_lines
self
.
_remaining_lines
=
remaining_lines
keys
,
hashes
=
self
.
_parse_remaining_lines
(
remaining_lines
)
keys
,
hashes
,
self
.
multiline
=
self
.
_parse_remaining_lines
(
remaining_lines
)
self
.
keys
=
tuple
(
keys
)
self
.
keys
=
tuple
(
keys
)
self
.
hashes
=
list
(
hashes
)
self
.
hashes
=
list
(
hashes
)
...
@@ -250,7 +250,9 @@ class Step(object):
...
@@ -250,7 +250,9 @@ class Step(object):
return
u'<Step: "
%
s">'
%
self
.
sentence
return
u'<Step: "
%
s">'
%
self
.
sentence
def
_parse_remaining_lines
(
self
,
lines
):
def
_parse_remaining_lines
(
self
,
lines
):
return
strings
.
parse_hashes
(
lines
)
multiline
=
strings
.
parse_multiline
(
lines
)
keys
,
hashes
=
strings
.
parse_hashes
(
lines
)
return
keys
,
hashes
,
multiline
def
_get_match
(
self
,
ignore_case
):
def
_get_match
(
self
,
ignore_case
):
matched
,
func
=
None
,
lambda
:
None
matched
,
func
=
None
,
lambda
:
None
...
@@ -386,19 +388,28 @@ class Step(object):
...
@@ -386,19 +388,28 @@ class Step(object):
parsed, but must be well-formed under a regular step sentence.
parsed, but must be well-formed under a regular step sentence.
"""
"""
invalid_first_line_error
=
'
\n
First line of step "
%
(line)
s" is in table
form.'
invalid_first_line_error
=
'
\n
First line of step "
%
s" is in
%
s
form.'
if
lines
and
strings
.
wise_startswith
(
lines
[
0
],
u'|'
):
if
lines
and
strings
.
wise_startswith
(
lines
[
0
],
u'|'
):
raise
LettuceSyntaxError
(
raise
LettuceSyntaxError
(
None
,
None
,
invalid_first_line_error
%
lines
[
0
])
invalid_first_line_error
%
(
lines
[
0
],
'table'
))
if
lines
and
strings
.
wise_startswith
(
lines
[
0
],
u'"""'
):
raise
LettuceSyntaxError
(
None
,
invalid_first_line_error
%
(
lines
[
0
],
'multiline'
))
# Select only lines that aren't end-to-end whitespace
# Select only lines that aren't end-to-end whitespace
only_whitspace
=
re
.
compile
(
'^
\
s*$'
)
only_whitspace
=
re
.
compile
(
'^
\
s*$'
)
lines
=
filter
(
lambda
x
:
not
only_whitspace
.
match
(
x
),
lines
)
lines
=
filter
(
lambda
x
:
not
only_whitspace
.
match
(
x
),
lines
)
step_strings
=
[]
step_strings
=
[]
in_multiline
=
False
for
line
in
lines
:
for
line
in
lines
:
if
strings
.
wise_startswith
(
line
,
u"|"
):
if
strings
.
wise_startswith
(
line
,
u'"""'
):
in_multiline
=
not
in_multiline
step_strings
[
-
1
]
+=
"
\n
%
s"
%
line
elif
strings
.
wise_startswith
(
line
,
u"|"
)
or
in_multiline
:
step_strings
[
-
1
]
+=
"
\n
%
s"
%
line
step_strings
[
-
1
]
+=
"
\n
%
s"
%
line
else
:
else
:
step_strings
.
append
(
line
)
step_strings
.
append
(
line
)
...
...
lettuce/strings.py
View file @
ae074e49
...
@@ -130,3 +130,17 @@ def parse_hashes(lines):
...
@@ -130,3 +130,17 @@ def parse_hashes(lines):
hashes
.
append
(
dict
(
zip
(
keys
,
values
)))
hashes
.
append
(
dict
(
zip
(
keys
,
values
)))
return
keys
,
hashes
return
keys
,
hashes
def
parse_multiline
(
lines
):
multilines
=
[]
in_multiline
=
False
for
line
in
lines
:
if
line
==
'"""'
:
in_multiline
=
not
in_multiline
elif
in_multiline
:
if
line
.
startswith
(
'"'
):
line
=
line
[
1
:]
if
line
.
endswith
(
'"'
):
line
=
line
[:
-
1
]
multilines
.
append
(
line
)
return
u'
\n
'
.
join
(
multilines
)
tests/unit/test_step_parsing.py
View file @
ae074e49
...
@@ -23,7 +23,44 @@ I_HAVE_TASTY_BEVERAGES = """I have the following tasty beverages in my freezer:
...
@@ -23,7 +23,44 @@ I_HAVE_TASTY_BEVERAGES = """I have the following tasty beverages in my freezer:
"""
"""
I_DIE_HAPPY
=
"I shall die with love in my heart"
I_DIE_HAPPY
=
"I shall die with love in my heart"
MULTI_LINE
=
'''
I have a string like so:
"""
This is line one
and this is line two
and this is line three
and this is line four,
with spaces at the beginning
"""
'''
MULTI_LINE_WHITESPACE
=
'''
I have a string like so:
"""
This is line one
and this is line two
and this is line three
" and this is line four,
"
" with spaces at the beginning
and spaces at the end "
"""
'''
INVALID_MULTI_LINE
=
'''
"""
invalid one...
"""
'''
from
lettuce.core
import
Step
from
lettuce.core
import
Step
from
lettuce.exceptions
import
LettuceSyntaxError
from
lettuce
import
strings
from
nose.tools
import
assert_equals
from
nose.tools
import
assert_equals
from
tests.asserts
import
*
from
tests.asserts
import
*
import
string
import
string
...
@@ -118,3 +155,42 @@ def test_can_parse_two_ordinary_steps():
...
@@ -118,3 +155,42 @@ def test_can_parse_two_ordinary_steps():
assert
isinstance
(
steps
[
1
],
Step
)
assert
isinstance
(
steps
[
1
],
Step
)
assert_equals
(
steps
[
0
]
.
sentence
,
I_DIE_HAPPY
)
assert_equals
(
steps
[
0
]
.
sentence
,
I_DIE_HAPPY
)
assert_equals
(
steps
[
1
]
.
sentence
,
I_LIKE_VEGETABLES
)
assert_equals
(
steps
[
1
]
.
sentence
,
I_LIKE_VEGETABLES
)
def
test_cannot_start_with_multiline
():
"It should raise an error when a step starts with a multiline string"
lines
=
strings
.
get_stripped_lines
(
INVALID_MULTI_LINE
)
try
:
step
=
Step
.
many_from_lines
(
lines
)
except
LettuceSyntaxError
:
return
assert
False
,
"LettuceSyntaxError not raised"
def
test_multiline_is_part_of_previous_step
():
"It should correctly parse a multi-line string as part of the preceding step"
lines
=
strings
.
get_stripped_lines
(
MULTI_LINE
)
steps
=
Step
.
many_from_lines
(
lines
)
print
steps
assert_equals
(
len
(
steps
),
1
)
assert
isinstance
(
steps
[
0
],
Step
)
assert_equals
(
steps
[
0
]
.
sentence
,
'I have a string like so:'
)
def
test_multiline_is_parsed
():
step
=
Step
.
from_string
(
MULTI_LINE
)
assert_equals
(
step
.
sentence
,
'I have a string like so:'
)
assert_equals
(
step
.
multiline
,
u"""This is line one
and this is line two
and this is line three
and this is line four,
with spaces at the beginning"""
)
def
test_multiline_with_whitespace
():
step
=
Step
.
from_string
(
MULTI_LINE_WHITESPACE
)
assert_equals
(
step
.
sentence
,
'I have a string like so:'
)
assert_equals
(
step
.
multiline
,
u"""This is line one
and this is line two
and this is line three
and this is line four,
with spaces at the beginning
and spaces at the end """
)
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