Skip to content

Commit

Permalink
Merge pull request #123 from elyezer/pr-122
Browse files Browse the repository at this point in the history
Drop support to token_prefix option
  • Loading branch information
sthirugn committed Nov 18, 2016
2 parents 98875d1 + 68ec79b commit 8485ddf
Show file tree
Hide file tree
Showing 7 changed files with 45 additions and 57 deletions.
8 changes: 1 addition & 7 deletions docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -50,13 +50,7 @@ minimum-tokens
.. note::

To help test case parsing, make sure that each test case docstring has the
tokens in the following format ``{token_prefix}token{token_suffix}``,
where:

token_prefix
This is configurable and by default, it is ``:``.
token_suffix
This is not configurable and should always be ``:``.
tokens in the following format ``:token:``.

Sample Test Case
++++++++++++++++
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
author='Suresh Thirugn',
author_email='sthirugn@redhat.com',
packages=find_packages(),
install_requires=['Click', 'termcolor'],
install_requires=['Click', 'termcolor', 'docutils'],
entry_points='''
[console_scripts]
testimony=testimony.cli:testimony
Expand Down
1 change: 0 additions & 1 deletion testimony/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,6 @@ def __init__(self, function_def, parent_class=None, testmodule=None):
self.parser = DocstringParser(
SETTINGS.get('tokens'),
SETTINGS.get('minimum_tokens'),
SETTINGS.get('token_prefix', ':'),
)
self._parse_docstring()

Expand Down
17 changes: 1 addition & 16 deletions testimony/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,36 +5,21 @@
from testimony import SETTINGS, constants, main


def _validate_token_prefix(ctx, param, value):
"""Ensure single character for token prefix."""
if len(value) != 1:
raise click.BadParameter('token prefix should be a single character.')
else:
return value


@click.command()
@click.option('-j', '--json', help='JSON output', is_flag=True)
@click.option('-n', '--nocolor', default=False, help='Color output',
is_flag=True)
@click.option('--tokens', help='Comma separated list of expected tokens')
@click.option(
'--minimum-tokens', help='Comma separated list of minimum expected tokens')
@click.option(
'--token-prefix',
callback=_validate_token_prefix,
default=':',
help='Single character token prefix'
)
@click.argument('report', type=click.Choice(constants.REPORT_TAGS))
@click.argument('path', nargs=-1, type=click.Path(exists=True))
def testimony(
json, nocolor, tokens, minimum_tokens, token_prefix, report, path):
json, nocolor, tokens, minimum_tokens, report, path):
"""Inspect and report on the Python test cases."""
if tokens:
SETTINGS['tokens'] = [token.strip() for token in tokens.split(',')]
if minimum_tokens:
SETTINGS['minimum_tokens'] = [
token.strip() for token in minimum_tokens.split(',')]
SETTINGS['token_prefix'] = token_prefix
main(report, path, json, nocolor)
39 changes: 30 additions & 9 deletions testimony/parser.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
# coding=utf-8
"""Docstring parser utilities for Testimony."""
import re
from docutils.core import publish_string
from xml.etree import ElementTree

from testimony.constants import DEFAULT_MINIMUM_TOKENS, DEFAULT_TOKENS


class DocstringParser(object):
"""Parse docstring extracting tokens."""

def __init__(self, tokens=None, minimum_tokens=None, prefix=':'):
def __init__(self, tokens=None, minimum_tokens=None):
"""Initialize the parser with expected tokens and the minimum set."""
if tokens is None:
self.tokens = DEFAULT_TOKENS
Expand All @@ -20,10 +21,6 @@ def __init__(self, tokens=None, minimum_tokens=None, prefix=':'):
self.minimum_tokens = minimum_tokens
self.minimum_tokens = set(self.minimum_tokens)
self.tokens = set(self.tokens)
self.token_regex = re.compile(
r'^{0}(\w+):\s+([^{0}]+)(\n|$)'.format(prefix),
flags=re.MULTILINE
)
if not self.minimum_tokens.issubset(self.tokens):
raise ValueError('tokens should contain minimum_tokens')

Expand Down Expand Up @@ -51,15 +48,39 @@ def parse(self, docstring=None):
"""
if docstring is None:
return {}, {}
tokens_dict = {}
valid_tokens = {}
invalid_tokens = {}
for match in self.token_regex.finditer(docstring):
token = match.group(1).strip().lower()
value = match.group(2).strip()

# Parse the docstring with the docutils RST parser and output the
# result as XML, this ease the process of getting the tokens
# information.
docstring_xml = publish_string(docstring, writer_name='xml')
root = ElementTree.fromstring(docstring_xml)
tokens = root.findall('./field_list/field')
for token in tokens:
token_name = token.find('./field_name').text.lower()
value_el = token.find('./field_body/')
if value_el is None:
invalid_tokens[token_name] = ''
continue
if value_el.tag == 'paragraph':
value = value_el.text
if value_el.tag == 'enumerated_list':
value_lst = map(lambda elem: elem.text,
value_el.findall('./list_item/paragraph'))
list_enum = list(enumerate(value_lst, start=1))
steps = map(lambda val: '{}. {}'.format(val[0], val[1]),
list_enum)
value = '\n'.join(steps)
tokens_dict[token_name] = value

for token, value in tokens_dict.items():
if token in self.tokens:
valid_tokens[token] = value
else:
invalid_tokens[token] = value

return valid_tokens, invalid_tokens

def validate_tokens(self, tokens):
Expand Down
4 changes: 3 additions & 1 deletion tests/sample_output.txt
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ Setup:

Steps:
1. Login to the application with valid credentials
2. Add a colon to the steps token: it should appear.

Tags:
t1, t2, t3
Expand Down Expand Up @@ -145,7 +146,8 @@ Setup:
Global setup

Steps:
1. Login to the application with valid username and no password
1. Login to the application with valid username
and no password

Test:
Login with invalid credentials
Expand Down
31 changes: 9 additions & 22 deletions tests/test_sample.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,8 @@ def test_positive_login_1(self):
:Feture: Login - Positive
:Steps:
1. Login to the application with valid credentials
:Steps: 1. Login to the application with valid credentials
2. Add a colon to the steps token: it should appear.
:Assert: Login is successful
Expand Down Expand Up @@ -50,14 +49,11 @@ def test_positive_login_3(self):
:Feature: Login - Positive
:Steps:
1. Login to the application with valid Latin credentials
:Steps: 1. Login to the application with valid Latin credentials
:Assert: Login is successful
:Tags: t1
"""
# Code to perform the test
pass
Expand All @@ -68,15 +64,12 @@ def test_positive_login_4(self):
:Feature: Login - Positive
:Steps:
1. Login to the application with valid credentials having
special characters
:Steps: 1. Login to the application with valid credentials having
special characters
:Assert: Activation key is created
:Status: Manual
"""
# Code to perform the test
pass
Expand All @@ -85,9 +78,7 @@ def test_positive_login_4(self):
def test_negative_login_5(self):
"""Test missing required docstrings
:Steps:
1. Login to the application with invalid credentials
:Steps: 1. Login to the application with invalid credentials
:BZ: 123456
Expand All @@ -109,9 +100,7 @@ def test_negative_login_6(self):
:Feature: Login - Negative
:Steps:
1. Login to the application with invalid credentials
:Steps: 1. Login to the application with invalid credentials
:Assert: Login failed
Expand All @@ -137,12 +126,10 @@ def test_negative_login_7(self):
:Feature: Login - Negative
:Steps:
1. Login to the application with valid username and no password
:Steps: 1. Login to the application with valid username
and no password
:Assert: Login failed
"""
# Code to perform the test
pass

0 comments on commit 8485ddf

Please sign in to comment.