Skip to content

Commit

Permalink
Refactored test framework to use YAML config files rather than INI. F…
Browse files Browse the repository at this point in the history
  • Loading branch information
waylan committed Aug 20, 2014
1 parent e7b6a33 commit 1918cd2
Show file tree
Hide file tree
Showing 18 changed files with 245 additions and 212 deletions.
110 changes: 62 additions & 48 deletions tests/__init__.py
Original file line number Diff line number Diff line change
@@ -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={
Expand All @@ -81,7 +95,7 @@ def __init__(self, description=None):

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')
Expand All @@ -91,7 +105,7 @@ def __call__(self, file, config):
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)
Expand All @@ -105,7 +119,7 @@ def __call__(self, file, config):
'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():
Expand All @@ -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):
Expand Down
36 changes: 22 additions & 14 deletions tests/extensions/extra/test.cfg
Original file line number Diff line number Diff line change
@@ -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
86 changes: 56 additions & 30 deletions tests/extensions/test.cfg
Original file line number Diff line number Diff line change
@@ -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
2 changes: 0 additions & 2 deletions tests/html4/test.cfg

This file was deleted.

2 changes: 0 additions & 2 deletions tests/misc/test.cfg

This file was deleted.

File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
10 changes: 8 additions & 2 deletions tests/options/test.cfg
Original file line number Diff line number Diff line change
@@ -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
13 changes: 7 additions & 6 deletions tests/php/extra/test.cfg
Original file line number Diff line number Diff line change
@@ -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
Loading

0 comments on commit 1918cd2

Please sign in to comment.