Commit 6252e693 by Chris Jerdonek

Test runner now supports both YAML and JSON.

parent d53165ed
...@@ -4,7 +4,7 @@ History ...@@ -4,7 +4,7 @@ History
TBD TBD
--- ---
* TODO * Test runner now supports both yaml and json forms of Mustache spec.
0.5.0 (2012-04-03) 0.5.0 (2012-04-03)
------------------ ------------------
......
...@@ -11,14 +11,23 @@ FILE_ENCODING = 'utf-8' # the encoding of the spec test files. ...@@ -11,14 +11,23 @@ FILE_ENCODING = 'utf-8' # the encoding of the spec test files.
try: try:
# We use the JSON files rather than the YAML files because json libraries import yaml
# are available for Python 2.4. except ImportError:
import json try:
except: # We use the JSON files rather than the YAML files because json libraries
# The module json is not available prior to Python 2.6, whereas simplejson is. # are available for Python 2.4.
# Note that simplejson dropped support for Python 2.4 in simplejson v2.1.0, import json
# so Python 2.4 requires a simplejson install older than the most recent. except:
import simplejson as json # The module json is not available prior to Python 2.6, whereas simplejson is.
# Note that simplejson dropped support for Python 2.4 in simplejson v2.1.0,
# so Python 2.4 requires a simplejson install older than the most recent.
import simplejson as json
file_extension = 'json'
parser = json
else:
file_extension = 'yml'
parser = yaml
import glob import glob
import os.path import os.path
...@@ -29,7 +38,42 @@ from pystache.renderer import Renderer ...@@ -29,7 +38,42 @@ from pystache.renderer import Renderer
from pystache.tests.common import AssertStringMixin, SPEC_TEST_DIR from pystache.tests.common import AssertStringMixin, SPEC_TEST_DIR
spec_paths = glob.glob(os.path.join(SPEC_TEST_DIR, '*.json')) spec_paths = glob.glob(os.path.join(SPEC_TEST_DIR, '*.%s' % file_extension))
def parse(u, file_extension):
"""
Arguments:
u: a unicode string.
"""
# Find a cleaner mechanism for choosing between the two.
if file_extension[0] == 'j':
# Then json.
# The only way to get the simplejson module to return unicode strings
# is to pass it unicode. See, for example--
#
# http://code.google.com/p/simplejson/issues/detail?id=40
#
# and the documentation of simplejson.loads():
#
# "If s is a str then decoded JSON strings that contain only ASCII
# characters may be parsed as str for performance and memory reasons.
# If your code expects only unicode the appropriate solution is
# decode s to unicode prior to calling loads."
#
return json.loads(u)
# Otherwise, yaml.
def code_constructor(loader, node):
value = loader.construct_mapping(node)
return eval(value['python'], {})
yaml.add_constructor(u'!code', code_constructor)
return yaml.load(u)
# This test case lets us alert the user that spec tests are missing. # This test case lets us alert the user that spec tests are missing.
...@@ -47,7 +91,13 @@ class MustacheSpec(unittest.TestCase, AssertStringMixin): ...@@ -47,7 +91,13 @@ class MustacheSpec(unittest.TestCase, AssertStringMixin):
pass pass
def buildTest(testData, spec_filename): def buildTest(testData, spec_filename, parser):
"""
Arguments:
parser: the module used for parsing (e.g. yaml or json).
"""
name = testData['name'] name = testData['name']
description = testData['desc'] description = testData['desc']
...@@ -57,7 +107,8 @@ def buildTest(testData, spec_filename): ...@@ -57,7 +107,8 @@ def buildTest(testData, spec_filename):
def test(self): def test(self):
template = testData['template'] template = testData['template']
partials = testData.has_key('partials') and testData['partials'] or {} partials = testData.has_key('partials') and testData['partials'] or {}
expected = testData['expected'] # PyYAML seems to leave ASCII strings as byte strings.
expected = unicode(testData['expected'])
data = testData['data'] data = testData['data']
# Convert code strings to functions. # Convert code strings to functions.
...@@ -79,10 +130,10 @@ def buildTest(testData, spec_filename): ...@@ -79,10 +130,10 @@ def buildTest(testData, spec_filename):
def escape(s): def escape(s):
return s.replace("%", "%%") return s.replace("%", "%%")
subs = [description, template, json.__version__, str(json)] subs = [description, template, parser.__version__, str(parser)]
subs = tuple([escape(sub) for sub in subs]) subs = tuple([escape(sub) for sub in subs])
# We include the json module version to help in troubleshooting # We include the parsing module version info to help with troubleshooting
# json/simplejson issues. # yaml/json/simplejson issues.
message = """%s message = """%s
Template: \"""%s\""" Template: \"""%s\"""
...@@ -109,31 +160,20 @@ for spec_path in spec_paths: ...@@ -109,31 +160,20 @@ for spec_path in spec_paths:
file_name = os.path.basename(spec_path) file_name = os.path.basename(spec_path)
# We avoid use of the with keyword for Python 2.4 support. # We avoid use of the with keyword for Python 2.4 support.
# TODO: share code here with pystache's open() code.
f = open(spec_path, 'r') f = open(spec_path, 'r')
try: try:
s = f.read() s = f.read()
finally: finally:
f.close() f.close()
# The only way to get the simplejson module to return unicode strings
# is to pass it unicode. See, for example--
#
# http://code.google.com/p/simplejson/issues/detail?id=40
#
# and the documentation of simplejson.loads():
#
# "If s is a str then decoded JSON strings that contain only ASCII
# characters may be parsed as str for performance and memory reasons.
# If your code expects only unicode the appropriate solution is
# decode s to unicode prior to calling loads."
#
u = s.decode(FILE_ENCODING) u = s.decode(FILE_ENCODING)
spec_data = json.loads(u) spec_data = parse(u, file_extension)
tests = spec_data['tests'] tests = spec_data['tests']
for test in tests: for test in tests:
test = buildTest(test, file_name) test = buildTest(test, file_name, parser)
setattr(MustacheSpec, test.__name__, test) setattr(MustacheSpec, test.__name__, test)
# Prevent this variable from being interpreted as another test. # Prevent this variable from being interpreted as another test.
del(test) del(test)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment