diff options
author | Alexis Hildebrandt <afh@surryhill.net> | 2014-02-07 00:21:38 +0100 |
---|---|---|
committer | Alexis Hildebrandt <afh@surryhill.net> | 2014-02-07 00:21:38 +0100 |
commit | fbbb379fe08b051b40c071041108a2526533f417 (patch) | |
tree | b6cb11c1c40f80bb89d90668ee739593381bb576 /test/DocTests.py | |
parent | ffc8bf30f458408c2735854de92d51081d6e6a49 (diff) | |
download | fork-ledger-fbbb379fe08b051b40c071041108a2526533f417.tar.gz fork-ledger-fbbb379fe08b051b40c071041108a2526533f417.tar.bz2 fork-ledger-fbbb379fe08b051b40c071041108a2526533f417.zip |
Check examples in documentation when running tests
The DocTests.py script will parse a given texinfo file for specially
marked examples, run the ledger command from the example, and check
the result against the example output from the documentation.
Diffstat (limited to 'test/DocTests.py')
-rwxr-xr-x | test/DocTests.py | 139 |
1 files changed, 139 insertions, 0 deletions
diff --git a/test/DocTests.py b/test/DocTests.py new file mode 100755 index 00000000..daac1db5 --- /dev/null +++ b/test/DocTests.py @@ -0,0 +1,139 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +import os +import re +import sys +import hashlib +import subprocess + +from difflib import unified_diff + +class DocTests: + def __init__(self, argv): + if not os.path.isfile(argv[1]): + print "Cannot find ledger at '%s'" % argv[1] + sys.exit(1) + if not os.path.isfile(argv[2]): + print "Cannot find source path at '%s'" % argv[2] + sys.exit(1) + + self.ledger = os.path.abspath(argv[1]) + self.sourcepath = os.path.abspath(argv[2]) + scriptpath = os.path.dirname(os.path.realpath(__file__)) + self.verbose = False + self.debug = False + self.examples = dict() + self.testin_token = 'command' + self.testout_token = 'output' + + def read_example(self): + endexample = re.compile(r'^@end\s+smallexample\s*$') + example = str() + while True: + line = self.file.readline() + self.current_line += 1 + if len(line) <= 0 or endexample.match(line): break + example += line + return example + + def test_id(self, example): + return hashlib.sha1(example.rstrip()).hexdigest()[0:7].upper() + + def find_examples(self): + startexample = re.compile(r'^@smallexample\s+@c\s+(%s|%s)(?::([\dA-Fa-f]+))?' % (self.testin_token, self.testout_token)) + while True: + line = self.file.readline() + self.current_line += 1 + if len(line) <= 0: break + + startmatch = startexample.match(line) + if (startmatch): + test_begin_pos = self.file.tell() + test_begin_line = self.current_line + test_kind = startmatch.group(1) + test_id = startmatch.group(2) + example = self.read_example() + test_end_pos = self.file.tell() + test_end_line = self.current_line + + if not test_id: + print >> sys.stderr, 'Example', test_kind, 'in line', test_begin_line, 'is missing id.' + test_id = self.test_id(example) + if test_kind == self.testin_token: + print >> sys.stderr, 'Use', self.test_id(example) + elif test_kind == self.testin_token and test_id != self.test_id(example): + print >> sys.stderr, 'Expected test id', test_id, 'for example' \ + , test_kind, 'on line', test_begin_line, 'to be', self.test_id(example) + + try: + self.examples[test_id] + except KeyError: + self.examples[test_id] = dict() + + self.examples[test_id][test_kind] = { + 'bpos': test_begin_pos, + 'epos': test_end_pos, + 'blin': test_begin_line, + 'elin': test_end_line, + test_kind: example, + } + + def test_examples(self): + failed = 0 + for test_id in self.examples: + example = self.examples[test_id] + try: + command = example[self.testin_token][self.testin_token] + except KeyError: + command = None + try: + output = example[self.testout_token][self.testout_token] + except KeyError: + output = None + + if command and output: + command = command.rstrip().split() + if command[0] == '$': command.remove('$') + index = command.index('ledger') + command[index] = self.ledger + command.insert(index+1, '--init-file') + command.insert(index+2, '/dev/null') + scriptpath = os.path.dirname(os.path.realpath(__file__)) + test_input_dir = scriptpath + '/../test/input/' + for i, arg in enumerate(command): + if '.dat' in arg or '.ledger' in arg: + if os.path.exists(test_input_dir + arg): + command[i] = test_input_dir + arg + try: + verify = subprocess.check_output(command)#.decode('utf-8') + except: + verify = str() + valid = (output == verify) + if self.verbose: + print test_id, ':', u'Passed' if valid else u'FAILED' + else: + sys.stdout.write('.' if valid else 'E') + + if not valid: + failed += 1 + if self.debug: + print ' '.join(command) + for line in unified_diff(output.split('\n'), verify.split('\n'), fromfile='generated', tofile='expected'): + print(line) + print + print + return failed + + def main(self): + self.file = open(self.sourcepath) + self.current_line = 0 + self.find_examples() + failed_examples = self.test_examples() + self.file.close() + return failed_examples + +if __name__ == "__main__": + script = DocTests(sys.argv) + status = script.main() + sys.exit(status) |