Skip to content

Instantly share code, notes, and snippets.

@npryce
Last active August 29, 2015 14:02
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save npryce/9c4dc2e0ea7eaf6e27fc to your computer and use it in GitHub Desktop.
Save npryce/9c4dc2e0ea7eaf6e27fc to your computer and use it in GitHub Desktop.
A quick-and-dirty Approval Testing tool for Python and Py.Test
import string
import os
from filecmp import cmp as file_contents_equal
def _extension(template_file, format):
if format is not None:
return "." + format
elif template_file is not None:
return os.path.splitext(template_file)[1]
else:
return ".txt"
def approve(test_fn, template_file, format, args, kwargs):
test_name = test_fn.__module__ + "." + test_fn.__name__
extension = _extension(template_file, format)
received_file = test_name + "-received" + extension
approved_file = test_name + "-approved" + extension
with open(received_file, mode="w") as received:
if template_file is None:
test_fn(received, *args, **kwargs)
else:
template = string.Template(open(template_file).read())
template_params = dict()
template_params["_resourcedir"] = os.path.dirname(template_file);
template_params.update(test_fn(*args, **kwargs))
received.write(template.substitute(template_params))
assert os.path.exists(approved_file), \
"no approved file: " + approved_file
assert file_contents_equal(received_file, approved_file), \
"diff " + received_file + " " + approved_file
os.remove(received_file)
def approval(template=None, format=None):
def decorator(test_fn):
def run_approval(*args, **kwargs):
approve(test_fn, template, format, args, kwargs)
return run_approval
return decorator

Example

${x} + ${y} = ${sum}

from approval import approval
# Without a template, the test function is passed a stream and must write results to be approved
@approval(format="md")
def test_something(out):
out.write("Example\n")
out.write("=======\n")
out.write("{} + {} = {}", 1, 2, 1+2)
# With a template, the test function must return a dict of template parameters that are expanded by the Python string.Template class
@approval(format="example-template.md")
def test_something_else():
return dict(x: 1, y: 2, sum: 1+2)
# Either way, received and approved files will be written to / read from the current working directory.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment