From 1918cd26a16bf6051b3fcc791e1f260bad846c72 Mon Sep 17 00:00:00 2001 From: Waylan Limberg Date: Wed, 20 Aug 2014 14:32:09 -0400 Subject: Refactored test framework to use YAML config files rather than INI. Fixes #333. --- tests/__init__.py | 110 ++++++++++++++++++++++----------------- tests/extensions/extra/test.cfg | 36 ++++++++----- tests/extensions/test.cfg | 86 +++++++++++++++++++----------- tests/html4/html4.html | 2 - tests/html4/html4.txt | 2 - tests/html4/test.cfg | 2 - tests/misc/no-attributes.html | 2 - tests/misc/no-attributes.txt | 3 -- tests/misc/test.cfg | 2 - tests/options/html4.html | 2 + tests/options/html4.txt | 2 + tests/options/no-attributes.html | 2 + tests/options/no-attributes.txt | 3 ++ tests/options/test.cfg | 10 +++- tests/php/extra/test.cfg | 13 ++--- tests/php/test.cfg | 100 +++++++++++++++++------------------ tests/pl/Tests_2004/test.cfg | 16 +++--- tests/pl/Tests_2007/test.cfg | 40 +++++++------- tests/plugins.py | 6 ++- tests/safe_mode/test.cfg | 12 ++--- tests/util.py | 23 -------- tox.ini | 1 + 22 files changed, 254 insertions(+), 221 deletions(-) delete mode 100644 tests/html4/html4.html delete mode 100644 tests/html4/html4.txt delete mode 100644 tests/html4/test.cfg delete mode 100644 tests/misc/no-attributes.html delete mode 100644 tests/misc/no-attributes.txt delete mode 100644 tests/misc/test.cfg create mode 100644 tests/options/html4.html create mode 100644 tests/options/html4.txt create mode 100644 tests/options/no-attributes.html create mode 100644 tests/options/no-attributes.txt delete mode 100644 tests/util.py diff --git a/tests/__init__.py b/tests/__init__.py index a16d0e6..a56f196 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -1,64 +1,78 @@ - import os import markdown import codecs import difflib try: import nose -except ImportError: - raise ImportError("The nose testing framework is required to run " \ - "Python-Markdown tests. Run `easy_install nose` " \ - "to install the latest version.") -from . import util -from .plugins import HtmlOutput, Markdown +except ImportError as e: + msg = e.args[0] + msg = msg + ". The nose testing framework is required to run the Python-" \ + "Markdown tests. Run `pip install nose` to install the latest version." + e.args = (msg,) + e.args[1:] + raise +from .plugins import HtmlOutput, Markdown, MarkdownSyntaxError try: import tidylib except ImportError: tidylib = None - +try: + import yaml +except ImportError as e: + msg = e.args[0] + msg = msg + ". A YAML library is required to run the Python-Markdown " \ + "tests. Run `pip install pyyaml` to install the latest version." + e.args = (msg,) + e.args[1:] + raise test_dir = os.path.abspath(os.path.dirname(__file__)) -def relpath(path, start=test_dir): - """ reimplement relpath for python 2.3-2.5 from 2.6 """ - if not path: - raise ValueError('no path secified') - start_list = os.path.abspath(start).split(os.path.sep) - path_list = os.path.abspath(path).split(os.path.sep) - # Work out how much of the filepath is shared by start and path. - i = len(os.path.commonprefix([start_list, path_list])) - rel_list = [os.path.pardir] * (len(start_list)-i) + path_list[i:] - if not rel_list: - return test_dir - return os.path.join(*rel_list) +class YamlConfig(): + def __init__(self, defaults, filename): + """ Set defaults and load config file if it exists. """ + self.DEFAULT_SECTION = 'DEFAULT' + self._defaults = defaults + self._config = {} + if os.path.exists(filename): + with codecs.open(filename, encoding="utf-8") as f: + self._config = yaml.load(f) + + def get(self, section, option): + """ Get config value for given section and option key. """ + if section in self._config and option in self._config[section]: + return self._config[section][option] + return self._defaults[option] + + def get_section(self, file): + """ Get name of config section for given file. """ + filename = os.path.basename(file) + if filename in self._config: + return filename + else: + return self.DEFAULT_SECTION + + def get_args(self, file): + """ Get args to pass to markdown from config for a given file. """ + args = {} + section = self.get_section(file) + if section in self._config: + for key in self._config[section].keys(): + # Filter out args unique to testing framework + if key not in self._defaults.keys(): + args[key] = self.get(section, key) + return args + def get_config(dir_name): """ Get config for given directory name. """ - config = util.CustomConfigParser({'normalize': '0', - 'skip': '0', - 'input_ext': '.txt', - 'output_ext': '.html'}) - config.read(os.path.join(dir_name, 'test.cfg')) + defaults = { + 'normalize': False, + 'skip': False, + 'input_ext': '.txt', + 'output_ext': '.html' + } + config = YamlConfig(defaults, os.path.join(dir_name, 'test.cfg')) return config -def get_section(file, config): - """ Get name of config section for given file. """ - filename = os.path.basename(file) - if config.has_section(filename): - return filename - else: - return 'DEFAULT' - -def get_args(file, config): - """ Get args to pass to markdown from config for a given file. """ - args = {} - section = get_section(file, config) - for key, v in config.items(section): - # Filter out args unique to testing framework - if key not in ['normalize', 'skip', 'input_ext', 'output_ext']: - args[key] = config.get(section, key) - return args - def normalize(text): """ Normalize whitespace for a string of html using tidylib. """ output, errors = tidylib.tidy_fragment(text, options={ @@ -81,7 +95,7 @@ class CheckSyntax(object): def __call__(self, file, config): """ Compare expected output to actual output and report result. """ - cfg_section = get_section(file, config) + cfg_section = config.get_section(file) if config.get(cfg_section, 'skip'): raise nose.plugins.skip.SkipTest('Test skipped per config.') input_file = file + config.get(cfg_section, 'input_ext') @@ -91,7 +105,7 @@ class CheckSyntax(object): with codecs.open(output_file, encoding="utf-8") as f: # Normalize line endings (on windows, git may have altered line endings). expected_output = f.read().replace("\r\n", "\n") - output = markdown.markdown(input, **get_args(file, config)) + output = markdown.markdown(input, **config.get_args(file)) if tidylib and config.get(cfg_section, 'normalize'): # Normalize whitespace with tidylib before comparing. expected_output = normalize(expected_output) @@ -105,7 +119,7 @@ class CheckSyntax(object): 'actual_output.html', n=3)] if diff: - raise util.MarkdownSyntaxError('Output from "%s" failed to match expected ' + raise MarkdownSyntaxError('Output from "%s" failed to match expected ' 'output.\n\n%s' % (input_file, ''.join(diff))) def TestSyntax(): @@ -115,9 +129,9 @@ def TestSyntax(): # Loop through files and generate tests. for file in files: root, ext = os.path.splitext(file) - if ext == config.get(get_section(file, config), 'input_ext'): + if ext == config.get(config.get_section(file), 'input_ext'): path = os.path.join(dir_name, root) - check_syntax = CheckSyntax(description=relpath(path, test_dir)) + check_syntax = CheckSyntax(description=os.path.relpath(path, test_dir)) yield check_syntax, path, config def generate(file, config): diff --git a/tests/extensions/extra/test.cfg b/tests/extensions/extra/test.cfg index 52d48f0..fe5ca22 100644 --- a/tests/extensions/extra/test.cfg +++ b/tests/extensions/extra/test.cfg @@ -1,20 +1,28 @@ -[DEFAULT] -extensions=extra +DEFAULT: + extensions: + - extra -[loose_def_list] -extensions=def_list +loose_def_list: + extensions: + - def_list -[simple_def-lists] -extensions=def_list +simple_def-lists: + extensions: + - def_list -[abbr] -extensions=abbr +abbr: + extensions: + - abbr -[footnotes] -extensions=footnotes +footnotes: + extensions: + - footnotes -[tables] -extensions=tables +tables: + extensions: + - tables -[tables_and_attr_list] -extensions=tables,attr_list +tables_and_attr_list: + extensions: + - tables + - attr_list diff --git a/tests/extensions/test.cfg b/tests/extensions/test.cfg index c05a64e..0ef3c94 100644 --- a/tests/extensions/test.cfg +++ b/tests/extensions/test.cfg @@ -1,43 +1,69 @@ -[attr_list] -extensions=attr_list,def_list,smarty +attr_list: + extensions: + - attr_list + - def_list + - smarty -[codehilite] -extensions=codehilite -# This passes or not based on version of pygments. -skip=1 +codehilite: + extensions: + - codehilite + # This passes or not based on version of pygments. + skip: True -[toc] -extensions=toc +toc: + extensions: + - toc -[toc_invalid] -extensions=toc +toc_invalid: + extensions: + - toc -[toc_out_of_order] -extensions=toc +toc_out_of_order: + extensions: + - toc -[toc_nested] -extensions=toc(permalink=1) +toc_nested: + extensions: + - toc + extension_configs: + toc: + permalink: True -[toc_nested2] -extensions=toc(permalink=[link]) +toc_nested2: + extensions: + - toc + extension_configs: + toc: + permalink: "[link]" -[wikilinks] -extensions=wikilinks +wikilinks: + extensions: + - wikilinks -[fenced_code] -extensions=fenced_code +fenced_code: + extensions: + - fenced_code -[github_flavored] -extensions=fenced_code +github_flavored: + extensions: + - fenced_code -[sane_lists] -extensions=sane_lists +sane_lists: + extensions: + - sane_lists -[nl2br_w_attr_list] -extensions=nl2br,attr_list +nl2br_w_attr_list: + extensions: + - nl2br + - attr_list -[admonition] -extensions=admonition +admonition: + extensions: + - admonition -[smarty] -extensions=smarty(smart_angled_quotes=1) +smarty: + extensions: + - smarty + extension_configs: + smarty: + smart_angled_quotes: True diff --git a/tests/html4/html4.html b/tests/html4/html4.html deleted file mode 100644 index 7c88ad7..0000000 --- a/tests/html4/html4.html +++ /dev/null @@ -1,2 +0,0 @@ -

A test of the most
-basic of html/xhtml differences.

\ No newline at end of file diff --git a/tests/html4/html4.txt b/tests/html4/html4.txt deleted file mode 100644 index fddaf8e..0000000 --- a/tests/html4/html4.txt +++ /dev/null @@ -1,2 +0,0 @@ -A test of the most -basic of html/xhtml differences. \ No newline at end of file diff --git a/tests/html4/test.cfg b/tests/html4/test.cfg deleted file mode 100644 index a3fc498..0000000 --- a/tests/html4/test.cfg +++ /dev/null @@ -1,2 +0,0 @@ -[DEFAULT] -output_format=html4 diff --git a/tests/misc/no-attributes.html b/tests/misc/no-attributes.html deleted file mode 100644 index a72e888..0000000 --- a/tests/misc/no-attributes.html +++ /dev/null @@ -1,2 +0,0 @@ -

Regression test for issue 87

-

It's run with enable_attributes=False so this {@id=explanation} should not become an attribute

\ No newline at end of file diff --git a/tests/misc/no-attributes.txt b/tests/misc/no-attributes.txt deleted file mode 100644 index b2cb653..0000000 --- a/tests/misc/no-attributes.txt +++ /dev/null @@ -1,3 +0,0 @@ -Regression *test* for issue 87 - -It's run with enable_attributes=False so this {@id=explanation} should not become an attribute diff --git a/tests/misc/test.cfg b/tests/misc/test.cfg deleted file mode 100644 index 21e0061..0000000 --- a/tests/misc/test.cfg +++ /dev/null @@ -1,2 +0,0 @@ -[no-attributes] -enable_attributes=False \ No newline at end of file diff --git a/tests/options/html4.html b/tests/options/html4.html new file mode 100644 index 0000000..7c88ad7 --- /dev/null +++ b/tests/options/html4.html @@ -0,0 +1,2 @@ +

A test of the most
+basic of html/xhtml differences.

\ No newline at end of file diff --git a/tests/options/html4.txt b/tests/options/html4.txt new file mode 100644 index 0000000..fddaf8e --- /dev/null +++ b/tests/options/html4.txt @@ -0,0 +1,2 @@ +A test of the most +basic of html/xhtml differences. \ No newline at end of file diff --git a/tests/options/no-attributes.html b/tests/options/no-attributes.html new file mode 100644 index 0000000..a72e888 --- /dev/null +++ b/tests/options/no-attributes.html @@ -0,0 +1,2 @@ +

Regression test for issue 87

+

It's run with enable_attributes=False so this {@id=explanation} should not become an attribute

\ No newline at end of file diff --git a/tests/options/no-attributes.txt b/tests/options/no-attributes.txt new file mode 100644 index 0000000..b2cb653 --- /dev/null +++ b/tests/options/no-attributes.txt @@ -0,0 +1,3 @@ +Regression *test* for issue 87 + +It's run with enable_attributes=False so this {@id=explanation} should not become an attribute diff --git a/tests/options/test.cfg b/tests/options/test.cfg index d0d3368..eb8b853 100644 --- a/tests/options/test.cfg +++ b/tests/options/test.cfg @@ -1,2 +1,8 @@ -[lazy_ol_off] -lazy_ol = False +lazy_ol_off: + lazy_ol: False + +html4: + output_format: html4 + +no-attributes: + enable_attributes: False diff --git a/tests/php/extra/test.cfg b/tests/php/extra/test.cfg index 9c10984..c6011d6 100644 --- a/tests/php/extra/test.cfg +++ b/tests/php/extra/test.cfg @@ -1,6 +1,7 @@ -[DEFAULT] -extensions=extra -normalize=1 -input_ext=.text -output_ext=.xhtml -skip=1 +DEFAULT: + extensions: + - extra + normalize: True + input_ext: .text + output_ext: .xhtml + skip: True diff --git a/tests/php/test.cfg b/tests/php/test.cfg index 8b64d74..70c2601 100644 --- a/tests/php/test.cfg +++ b/tests/php/test.cfg @@ -1,50 +1,50 @@ -[DEFAULT] -normalize=1 -input_ext=.text -output_ext=.xhtml -#skip=1 - -[Quotes in attributes] -# attributes get output in differant order -skip=1 - -[Inline HTML (Span)] -# Backtick in raw HTML attribute TODO: fixme -skip=1 - -[Backslash escapes] -# Weird whitespace issue in output -skip=1 - -[Ins & del] -# Our behavior follows markdown.pl I think PHP is wrong here -skip=1 - -[Auto Links] -# TODO: fix raw HTML so is doesn't match as a
. -skip=1 - -[Empty List Item] -# We match markdown.pl here. Maybe someday we'll support this -skip=1 - -[Headers] -# TODO: fix headers to not require blank line before -skip=1 - -[Mixed OLs and ULs] -# We match markdown.pl here. I think PHP is wrong here -skip=1 - -[Emphasis] -# We have various minor differances in combined & incorrect em markup. -# Maybe fix a few of them - but most aren't too important -skip=1 - -[Code block in a list item] -# We match markdown.pl - not sure how php gets that output?? -skip=1 - -[PHP-Specific Bugs] -# Not sure what to make of the escaping stuff here. Why is PHP not removing a blackslash? -skip=1 +DEFAULT: + normalize: True + input_ext: .text + output_ext: .xhtml + #skip: True + +Quotes in attributes: + # attributes get output in differant order + skip: True + +Inline HTML (Span): + # Backtick in raw HTML attribute TODO: fixme + skip: True + +Backslash escapes: + # Weird whitespace issue in output + skip: True + +Ins & del: + # Our behavior follows markdown.pl I think PHP is wrong here + skip: True + +Auto Links: + # TODO: fix raw HTML so is doesn't match as a
. + skip: True + +Empty List Item: + # We match markdown.pl here. Maybe someday we'll support this + skip: True + +Headers: + # TODO: fix headers to not require blank line before + skip: True + +Mixed OLs and ULs: + # We match markdown.pl here. I think PHP is wrong here + skip: True + +Emphasis: + # We have various minor differances in combined & incorrect em markup. + # Maybe fix a few of them - but most aren't too important + skip: True + +Code block in a list item: + # We match markdown.pl - not sure how php gets that output?? + skip: True + +PHP-Specific Bugs: + # Not sure what to make of the escaping stuff here. Why is PHP not removing a blackslash? + skip: True diff --git a/tests/pl/Tests_2004/test.cfg b/tests/pl/Tests_2004/test.cfg index d3850f4..80f48e5 100644 --- a/tests/pl/Tests_2004/test.cfg +++ b/tests/pl/Tests_2004/test.cfg @@ -1,10 +1,10 @@ -[DEFAULT] -input_ext=.text -normalize=1 -# comment out next line to run these tests -#skip=1 +DEFAULT: + input_ext: .text + normalize: True + # comment out next line to run these tests + #skip: True -[Yuri-Footnotes] -extensions=footnotes -skip=1 +Yuri-Footnotes: + extensions: footnotes + skip: True diff --git a/tests/pl/Tests_2007/test.cfg b/tests/pl/Tests_2007/test.cfg index c86ca26..d885b71 100644 --- a/tests/pl/Tests_2007/test.cfg +++ b/tests/pl/Tests_2007/test.cfg @@ -1,25 +1,25 @@ -[DEFAULT] -input_ext=.text -normalize=1 -# comment out next line to run these tests -#skip=1 +DEFAULT: + input_ext: .text + normalize: True + # comment out next line to run these tests + #skip: True -[Images] -# the attributes don't get ordered the same so we skip this -skip=1 +Images: + # the attributes don't get ordered the same so we skip this + skip: True -[Code Blocks] -# some weird whitespace issue -skip=1 +Code Blocks: + # some weird whitespace issue + skip: True -[Links, reference style] -# weird issue with nested brackets TODO: fixme -skip=1 + Links, reference style: + # weird issue with nested brackets TODO: fixme + skip: True -[Backslash escapes] -# backticks in raw html attributes TODO: fixme -skip=1 +Backslash escapes: + # backticks in raw html attributes TODO: fixme + skip: True -[Code Spans] -# more backticks in raw html attributes TODO: fixme -skip=1 +Code Spans: + # more backticks in raw html attributes TODO: fixme + skip: True diff --git a/tests/plugins.py b/tests/plugins.py index bbeed60..12bac55 100644 --- a/tests/plugins.py +++ b/tests/plugins.py @@ -1,8 +1,12 @@ import traceback -from .util import MarkdownSyntaxError from nose.plugins import Plugin from nose.plugins.errorclass import ErrorClass, ErrorClassPlugin + +class MarkdownSyntaxError(Exception): + pass + + class Markdown(ErrorClassPlugin): """ Add MarkdownSyntaxError and ensure proper formatting. """ mdsyntax = ErrorClass(MarkdownSyntaxError, diff --git a/tests/safe_mode/test.cfg b/tests/safe_mode/test.cfg index 57f0b6a..4e1720e 100644 --- a/tests/safe_mode/test.cfg +++ b/tests/safe_mode/test.cfg @@ -1,8 +1,8 @@ -[DEFAULT] -safe_mode=escape +DEFAULT: + safe_mode: escape -[remove] -safe_mode=remove +remove: + safe_mode: remove -[replace] -safe_mode=replace +replace: + safe_mode: replace diff --git a/tests/util.py b/tests/util.py deleted file mode 100644 index 0f416fb..0000000 --- a/tests/util.py +++ /dev/null @@ -1,23 +0,0 @@ -import sys -if sys.version_info[0] == 3: - from configparser import ConfigParser -else: - from ConfigParser import SafeConfigParser as ConfigParser - -class MarkdownSyntaxError(Exception): - pass - - -class CustomConfigParser(ConfigParser): - def get(self, section, option): - value = ConfigParser.get(self, section, option) - if option == 'extensions': - if len(value.strip()): - return value.split(',') - else: - return [] - if value.lower() in ['yes', 'true', 'on', '1']: - return True - if value.lower() in ['no', 'false', 'off', '0']: - return False - return value diff --git a/tox.ini b/tox.ini index f3e9327..7968fba 100644 --- a/tox.ini +++ b/tox.ini @@ -5,6 +5,7 @@ envlist = py26, py27, py31, py32, py33, py34 downloadcache = {toxworkdir}/cache deps = nose coverage + pyyaml pytidylib commands = coverage run --source=markdown {toxinidir}/run-tests.py {posargs} coverage report --show-missing -- cgit v1.2.3