"$DATADIR/1.yarn"
SCENARIO foo
WHEN doing ok
IMPLEMENTS WHEN doing ok
true
EOF
./run-yarn "$DATADIR/1.yarn"
cmdtest-0.10/yarn.tests/no-then.stderr 0000644 0001750 0001750 00000000056 12224016632 017667 0 ustar jenkins jenkins ERROR: Some scenarios have no THENs:
"foo"
cmdtest-0.10/yarn.tests/selected-test.script 0000755 0001750 0001750 00000000445 12224016632 021072 0 ustar jenkins jenkins #!/bin/sh
set -eu
cat << EOF > "$DATADIR/test.yarn"
SCENARIO bar test
THEN do bar
SCENARIO foo test
THEN do foo
IMPLEMENTS THEN do (.*)
touch "$DATADIR/\$MATCH_1"
EOF
./run-yarn "$DATADIR/test.yarn" --run 'foo test'
test -e "$DATADIR/foo"
! test -e "$DATADIR/bar"
cmdtest-0.10/yarn.tests/setup 0000755 0001750 0001750 00000000057 12224016632 016161 0 ustar jenkins jenkins #!/bin/sh
find "$DATADIR" -mindepth 1 -delete
cmdtest-0.10/yarn.tests/shell-lib.script 0000755 0001750 0001750 00000000113 12224016632 020170 0 ustar jenkins jenkins #!/bin/sh
set -eu
./run-yarn --shell-library shell-lib.sh shell-lib.yarn
cmdtest-0.10/yarn.tests/simple.exit 0000644 0001750 0001750 00000000002 12224016632 017245 0 ustar jenkins jenkins 1
cmdtest-0.10/yarn.tests/simple.script 0000755 0001750 0001750 00000000057 12224016632 017615 0 ustar jenkins jenkins #!/bin/sh
set -eu
./run-yarn simple.scenario
cmdtest-0.10/yarn.tests/simple.stderr 0000644 0001750 0001750 00000000050 12224016632 017602 0 ustar jenkins jenkins ERROR: Test suite FAILED in 1 scenarios
cmdtest-0.10/yarn.tests/snapshot.script 0000755 0001750 0001750 00000003365 12224016632 020170 0 ustar jenkins jenkins #!/bin/sh
set -eu
cat << EOF > "$DATADIR/foo.yarn"
SCENARIO foo
GIVEN foo
WHEN foo
THEN foo
SCENARIO bar
GIVEN bar
WHEN bar
THEN bar
IMPLEMENTS GIVEN (.*)
touch "\$DATADIR/\$MATCH_1.given"
IMPLEMENTS WHEN (.*)
touch "\$DATADIR/\$MATCH_1.when"
IMPLEMENTS THEN (.*)
touch "\$DATADIR/\$MATCH_1.then"
EOF
./run-yarn --snapshot --tempdir "$DATADIR/tmp" "$DATADIR/foo.yarn"
test -e "$DATADIR/tmp/bar"
test -e "$DATADIR/tmp/bar/datadir"
test -e "$DATADIR/tmp/bar/datadir/bar.given"
test -e "$DATADIR/tmp/bar/datadir/bar.when"
test -e "$DATADIR/tmp/bar/datadir/bar.then"
test -e "$DATADIR/tmp/bar/001-GIVEN-bar"
test -e "$DATADIR/tmp/bar/001-GIVEN-bar/bar.given"
! test -e "$DATADIR/tmp/bar/001-GIVEN-bar/bar.when"
! test -e "$DATADIR/tmp/bar/001-GIVEN-bar/bar.then"
test -e "$DATADIR/tmp/bar/002-WHEN-bar"
test -e "$DATADIR/tmp/bar/002-WHEN-bar/bar.given"
test -e "$DATADIR/tmp/bar/002-WHEN-bar/bar.when"
! test -e "$DATADIR/tmp/bar/002-WHEN-bar/bar.then"
test -e "$DATADIR/tmp/bar/003-THEN-bar"
test -e "$DATADIR/tmp/bar/003-THEN-bar/bar.given"
test -e "$DATADIR/tmp/bar/003-THEN-bar/bar.when"
test -e "$DATADIR/tmp/bar/003-THEN-bar/bar.then"
test -e "$DATADIR/tmp/foo/001-GIVEN-foo"
test -e "$DATADIR/tmp/foo/001-GIVEN-foo/foo.given"
! test -e "$DATADIR/tmp/foo/001-GIVEN-foo/foo.when"
! test -e "$DATADIR/tmp/foo/001-GIVEN-foo/foo.then"
test -e "$DATADIR/tmp/foo/002-WHEN-foo"
test -e "$DATADIR/tmp/foo/002-WHEN-foo/foo.given"
test -e "$DATADIR/tmp/foo/002-WHEN-foo/foo.when"
! test -e "$DATADIR/tmp/foo/002-WHEN-foo/foo.then"
test -e "$DATADIR/tmp/foo/003-THEN-foo"
test -e "$DATADIR/tmp/foo/003-THEN-foo/foo.given"
test -e "$DATADIR/tmp/foo/003-THEN-foo/foo.when"
test -e "$DATADIR/tmp/foo/003-THEN-foo/foo.then"
cmdtest-0.10/yarn.tests/warn-if-empty.script 0000755 0001750 0001750 00000000375 12224016632 021026 0 ustar jenkins jenkins #!/bin/sh
set -eu
touch "$DATADIR/empty.yarn"
# The grep below will fail unless the string exists, thereby failing the
# entire test.
./run-yarn --no-quiet --log=/dev/stdout "$DATADIR/empty.yarn" 2>&1 |
grep 'No scenario code blocks' > /dev/null
cmdtest-0.10/yarnlib/ 0000755 0001750 0001750 00000000000 12224016632 014417 5 ustar jenkins jenkins cmdtest-0.10/yarnlib/__init__.py 0000644 0001750 0001750 00000001514 12224016632 016531 0 ustar jenkins jenkins # Copyright 2013 Lars Wirzenius
#
# 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 .
#
# =*= License: GPL-3+ =*=
from mdparser import MarkdownParser
from elements import Scenario, ScenarioStep, Implementation
from block_parser import BlockParser, BlockError
cmdtest-0.10/yarnlib/block_parser.py 0000644 0001750 0001750 00000010511 12224016632 017435 0 ustar jenkins jenkins # Copyright 2013 Lars Wirzenius
#
# 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 .
#
# =*= License: GPL-3+ =*=
import cliapp
import yarnlib
class BlockError(cliapp.AppException):
pass
# Parse a sequence of textual blocks into scenario and Implementation
# objects, and their constituent objects.
class BlockParser(object):
def __init__(self):
self.scenarios = []
self.implementations = []
self.line_parsers = {
'SCENARIO': self.parse_scenario,
'ASSUMING': self.parse_assuming,
'GIVEN': self.parse_given,
'WHEN': self.parse_when,
'THEN': self.parse_then,
'FINALLY': self.parse_finally,
'AND': self.parse_and,
'IMPLEMENTS': self.parse_implementing,
}
def parse_blocks(self, blocks):
while blocks:
blocks = self.parse_one(blocks)
def parse_one(self, blocks):
assert blocks
block = blocks[0]
assert block
t = block.split('\n', 1)
assert len(t) in [1,2]
if len(t) == 1:
line1 = block
block = ''
else:
line1, block = t
if block:
blocks[0] = block
else:
del blocks[0]
words = line1.split()
if not words:
return blocks
rest = ' '.join(words[1:])
for keyword in self.line_parsers:
if words[0] == keyword:
return self.line_parsers[keyword](rest, blocks)
raise BlockError("Syntax error: unknown step: %s" % line1)
def parse_scenario(self, line, blocks):
self.scenarios.append(yarnlib.Scenario(line))
return blocks
def parse_simple(self, what, line, blocks):
if not self.scenarios:
raise BlockError('Syntax errror: %s before SCENARIO' % what)
step = yarnlib.ScenarioStep(what, line)
self.scenarios[-1].steps.append(step)
return blocks
def parse_assuming(self, line, blocks):
return self.parse_simple('ASSUMING', line, blocks)
def parse_given(self, line, blocks):
return self.parse_simple('GIVEN', line, blocks)
def parse_when(self, line, blocks):
return self.parse_simple('WHEN', line, blocks)
def parse_then(self, line, blocks):
return self.parse_simple('THEN', line, blocks)
def parse_finally(self, line, blocks):
return self.parse_simple('FINALLY', line, blocks)
def parse_and(self, line, blocks):
if not self.scenarios:
raise BlockError('Syntax errror: AND before SCENARIO')
scenario = self.scenarios[-1]
if not scenario.steps:
raise BlockError(
'Syntax errror: AND before what it would continue')
step = scenario.steps[-1]
assert step.what in self.line_parsers
return self.line_parsers[step.what](line, blocks)
def parse_implementing(self, line, blocks):
words = line.split()
if len(words) < 2:
raise BlockError(
'Syntax error: IMPLEMENTS must have what and regexp')
what = words[0]
regexp = ' '.join(words[1:])
if blocks:
block = blocks[0]
shell = []
rest = []
for block_line in block.splitlines():
if rest or block_line.startswith('IMPLEMENTS'):
rest.append(block_line)
else:
shell.append(block_line)
shell = '\n'.join(shell)
if rest:
blocks[0] = '\n'.join(rest)
else:
del blocks[0]
else:
shell = ''
implementation = yarnlib.Implementation(what, regexp, shell)
self.implementations.append(implementation)
return blocks
cmdtest-0.10/yarnlib/block_parser_tests.py 0000644 0001750 0001750 00000011750 12224016632 020665 0 ustar jenkins jenkins # Copyright 2013 Lars Wirzenius
#
# 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 .
#
# =*= License: GPL-3+ =*=
import unittest
import yarnlib
class BlockParserTests(unittest.TestCase):
def setUp(self):
self.parser = yarnlib.BlockParser()
def test_is_initially_empty(self):
self.assertEqual(self.parser.scenarios, [])
self.assertEqual(self.parser.implementations, [])
def test_parses_simple_elements(self):
self.parser.parse_blocks(
['SCENARIO foo', 'ASSUMING something', 'GIVEN bar',
'WHEN foobar\nTHEN yoyo\nFINALLY yay\nAND yeehaa'])
self.assertEqual(len(self.parser.scenarios), 1)
self.assertEqual(len(self.parser.implementations), 0)
scenario = self.parser.scenarios[0]
self.assertEqual(scenario.name, 'foo')
self.assertEqual(len(scenario.steps), 6)
self.assertEqual(scenario.steps[0].what, 'ASSUMING')
self.assertEqual(scenario.steps[0].text, 'something')
self.assertEqual(scenario.steps[1].what, 'GIVEN')
self.assertEqual(scenario.steps[1].text, 'bar')
self.assertEqual(scenario.steps[2].what, 'WHEN')
self.assertEqual(scenario.steps[2].text, 'foobar')
self.assertEqual(scenario.steps[3].what, 'THEN')
self.assertEqual(scenario.steps[3].text, 'yoyo')
self.assertEqual(scenario.steps[4].what, 'FINALLY')
self.assertEqual(scenario.steps[4].text, 'yay')
self.assertEqual(scenario.steps[5].what, 'FINALLY')
self.assertEqual(scenario.steps[5].text, 'yeehaa')
def test_normalises_whitespace(self):
self.parser.parse_blocks(['SCENARIO foo bar '])
self.assertEqual(self.parser.scenarios[0].name, 'foo bar')
def test_handles_empty_line(self):
self.parser.parse_blocks(['SCENARIO foo\n\nGIVEN bar\nTHEN foobar'])
self.assertEqual(len(self.parser.scenarios), 1)
def test_raises_error_for_unknown_step(self):
self.assertRaises(
yarnlib.BlockError,
self.parser.parse_blocks,
['SCENARIO foo\nblah'])
def test_raises_error_for_step_outside_scenario(self):
self.assertRaises(
yarnlib.BlockError,
self.parser.parse_blocks,
['GIVEN foo'])
def test_raises_error_for_AND_before_scenario(self):
self.assertRaises(
yarnlib.BlockError,
self.parser.parse_blocks,
['AND bar'])
def test_raises_error_for_AND_before_step(self):
self.assertRaises(
yarnlib.BlockError,
self.parser.parse_blocks,
['SCENARIO foo\nAND bar'])
def test_parses_implements_in_a_block_by_itself(self):
self.parser.parse_blocks(['IMPLEMENTS GIVEN foo\ntrue'])
impls = self.parser.implementations
self.assertEqual(len(impls), 1)
self.assertEqual(impls[0].what, 'GIVEN')
self.assertEqual(impls[0].regexp, 'foo')
self.assertEqual(impls[0].shell, 'true')
def test_parses_implements_with_empty_shell_text(self):
self.parser.parse_blocks(['IMPLEMENTS GIVEN foo'])
impls = self.parser.implementations
self.assertEqual(len(impls), 1)
self.assertEqual(impls[0].what, 'GIVEN')
self.assertEqual(impls[0].regexp, 'foo')
self.assertEqual(impls[0].shell, '')
def test_parses_two_implements_in_a_code_block(self):
self.parser.parse_blocks(
['IMPLEMENTS GIVEN foo\ntrue\nIMPLEMENTS WHEN bar\ncat /dev/null'])
impls = self.parser.implementations
self.assertEqual(len(impls), 2)
self.assertEqual(impls[0].what, 'GIVEN')
self.assertEqual(impls[0].regexp, 'foo')
self.assertEqual(impls[0].shell, 'true')
self.assertEqual(impls[1].what, 'WHEN')
self.assertEqual(impls[1].regexp, 'bar')
self.assertEqual(impls[1].shell, 'cat /dev/null')
def test_raises_error_for_implements_with_no_args(self):
self.assertRaises(
yarnlib.BlockError,
self.parser.parse_blocks,
['IMPLEMENTS'])
def test_raises_error_for_implements_with_one_args(self):
self.assertRaises(
yarnlib.BlockError,
self.parser.parse_blocks,
['IMPLEMENTS GIVEN'])
def test_raises_error_for_implements_with_first_args_not_a_keyword(self):
self.assertRaises(
yarnlib.BlockError,
self.parser.parse_blocks,
['IMPLEMENTS foo'])
cmdtest-0.10/yarnlib/elements.py 0000644 0001750 0001750 00000002546 12224016632 016614 0 ustar jenkins jenkins # Copyright 2013 Lars Wirzenius
#
# 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 .
#
# =*= License: GPL-3+ =*=
# This is a step in a scenario: GIVEN, WHEN, THEN, etc.
class ScenarioStep(object):
def __init__(self, what, text):
self.what = what
self.text = text
self.implementation = None
# This is the scenario itself.
class Scenario(object):
def __init__(self, name):
self.name = name
self.steps = []
# This is an IMPLEMENTS chunk.
class Implementation(object):
def __init__(self, what, regexp, shell):
self.what = what
self.regexp = regexp
self.shell = shell
def execute(self):
exit, out, err = cliapp.runcmd_unchecked(
['sh', '-c', 'set -eu\n' + self.shell])
return exit
cmdtest-0.10/yarnlib/mdparser.py 0000644 0001750 0001750 00000004660 12224016632 016614 0 ustar jenkins jenkins # Copyright 2013 Lars Wirzenius
#
# 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 .
#
# =*= License: GPL-3+ =*=
import logging
import markdown
import StringIO
from markdown.treeprocessors import Treeprocessor
#
# Classes for Markdown parsing. See python-markdown documentation
# for details. We want to find all top level code blocks (indented
# four spaces in the Markdown), which we'll parse for scenario test
# stuff later on. We create a Python markdown extension and use
# "tree processor" to analyse the parsed ElementTree at the right
# moment for top level blocks.
#
# This is a Treeprocessor that iterates over the parsed Markdown,
# as an ElementTree, and finds all top level code blocks.
class GatherCodeBlocks(Treeprocessor):
def __init__(self, blocks):
self.blocks = blocks
def run(self, root):
for child in root.getchildren():
if child.tag == 'pre':
code = child.find('code')
self.blocks.append(code.text)
return root
# This is the Python Markdown extension to call the code block
# gatherer at the right time. It stores the list of top level
# code blocks as the blocks attribute.
class ParseScenarioTestBlocks(markdown.extensions.Extension):
def extendMarkdown(self, md, md_globals):
self.blocks = []
self.gatherer = GatherCodeBlocks(self.blocks)
md.treeprocessors.add('gathercode', self.gatherer, '_end')
class MarkdownParser(object):
def __init__(self):
self.blocks = []
def parse_string(self, text):
ext = ParseScenarioTestBlocks()
f = StringIO.StringIO()
markdown.markdown(text, output=f, extensions=[ext])
self.blocks.extend(ext.blocks)
return ext.blocks
def parse_file(self, filename): # pragma: no cover
with open(filename) as f:
return self.parse_string(f.read())
cmdtest-0.10/yarnlib/mdparser_tests.py 0000644 0001750 0001750 00000004627 12224016632 020041 0 ustar jenkins jenkins # Copyright 2013 Lars Wirzenius
#
# 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 .
#
# =*= License: GPL-3+ =*=
import unittest
import yarnlib
class MarkdownParserTests(unittest.TestCase):
def setUp(self):
self.parser = yarnlib.MarkdownParser()
def test_finds_code_block(self):
result = self.parser.parse_string('''
This is blah blah text.
this is a code block
More text.
''')
self.assertEqual(self.parser.blocks, ['this is a code block\n'])
self.assertEqual(result, ['this is a code block\n'])
def test_finds_consecutive_code_blocks_as_one(self):
self.parser.parse_string('''
This is blah blah text.
this is a code block
this is a second code block
More text.
''')
self.assertEqual(
self.parser.blocks,
['this is a code block\n\nthis is a second code block\n'])
def test_finds_code_blocks_with_text_in_between_as_two_blocks(self):
self.parser.parse_string('''
This is blah blah text.
this is a code block
Blah.
this is a second code block
More text.
''')
self.assertEqual(
self.parser.blocks,
['this is a code block\n', 'this is a second code block\n'])
def test_only_finds_top_level_code_blocks(self):
self.parser.parse_string('''
This is blah blah text.
this is a code block
And now a list:
* list item
this is a second level code block
More text.
''')
self.assertEqual(self.parser.blocks, ['this is a code block\n'])
def test_parses_multiple_files(self):
result1 = self.parser.parse_string('''
block 1
''')
result2 = self.parser.parse_string('''
block 2
''')
self.assertEqual(result1, ['block 1\n'])
self.assertEqual(result2, ['block 2\n'])
self.assertEqual(self.parser.blocks, ['block 1\n', 'block 2\n'])