Merge pull request #385 from prculley/report_test

This commit is contained in:
Nick Hall 2017-05-10 22:53:30 +01:00
commit 108d7b461c
2 changed files with 101 additions and 94 deletions

View File

@ -61,7 +61,7 @@ def mock_localtime(*args):
""" """
return strptime("25 Dec 1999", "%d %b %Y") return strptime("25 Dec 1999", "%d %b %Y")
class CompleteCheck(unittest.TestCase): class TestImports(unittest.TestCase):
"""The test class cases will be dynamically created at import time from """The test class cases will be dynamically created at import time from
files to be tested. The following defs are used by the test cases files to be tested. The following defs are used by the test cases
""" """
@ -278,39 +278,27 @@ if __name__ == "__main__":
del sys.argv[i] del sys.argv[i]
del sys.argv[i] del sys.argv[i]
# The following code dynamically creates the methods for each test file. # The following code dynamically creates the methods for each test file.
# The methods are inserted at load time into the 'CompleteCheck' class # The methods are inserted at load time into the 'TestImports' class
# via the modules' globals, taking advantage that they are a dict. # via the modules' globals, taking advantage that they are a dict.
if _tstfile: # single file mode if _tstfile: # single file mode
(fname, ext) = os.path.splitext(os.path.basename(_tstfile)) (fname, ext) = os.path.splitext(os.path.basename(_tstfile))
test_func = make_tst_function(_tstfile, fname) test_func = make_tst_function(_tstfile, fname)
clname = 'Import_{0}'.format(_tstfile) tname = "test_" + _tstfile.replace("-", "_").replace(".", "_")
globals()[clname] = type(clname, test_func.__name__ = tname
(CompleteCheck,), test_func.__doc__ = tname
{"testit": test_func}) setattr(TestImports, tname, test_func)
else: else:
_tstfiles = []
for _tstfile in os.listdir(TEST_DIR): for _tstfile in os.listdir(TEST_DIR):
(fname, ext) = os.path.splitext(os.path.basename(_tstfile)) (fname, ext) = os.path.splitext(os.path.basename(_tstfile))
if _tstfile != "SAMPLE.DEF" and (ext in (".gramps", ".difs", ".bak") \ if _tstfile != "SAMPLE.DEF" and (ext in (".gramps", ".difs", ".bak") \
or not fname.startswith("imp_")): or not fname.startswith("imp_")):
continue continue
test_func = make_tst_function(_tstfile, fname) test_func = make_tst_function(_tstfile, fname)
clname = 'Import_{0}'.format(_tstfile) tname = "test_" + _tstfile.replace("-", "_").replace(".", "_")
globals()[clname] = type(clname, test_func.__name__ = tname
(CompleteCheck,), test_func.__doc__ = tname
{"testit": test_func}) setattr(TestImports, tname, test_func)
_tstfiles.append(clname) test_func = None # keep nosetest from finding last one again
def test_import_classes():
"""
Dynamic Test-function lister for
nosetests. Creates an instance for each
import test, and yields the function to
test.
"""
for clname in _tstfiles:
instance = globals()[clname]()
yield instance.testit
if __name__ == "__main__": if __name__ == "__main__":
unittest.main() unittest.main()

View File

@ -24,21 +24,23 @@ import os
import shutil import shutil
from gramps.test.test_util import Gramps from gramps.test.test_util import Gramps
from gramps.gen.db.utils import open_database
from gramps.gen.user import User from gramps.gen.user import User
from gramps.gen.const import DATA_DIR
ddir = os.path.dirname(__file__) # ddir = os.path.dirname(__file__)
example = os.path.join(ddir, "..", "..", "..", # example = os.path.join(ddir, "..", "..", "..",
"example", "gramps", "data.gramps") # "example", "gramps", "data.gramps")
sample = os.path.join(ddir, "..", "..", "..", # sample = os.path.join(ddir, "..", "..", "..",
"example", "gedcom", "sample.ged") # "example", "gedcom", "sample.ged")
example = os.path.join(DATA_DIR, "tests", "data.gramps")
TREE_NAME = "Test_reporttest" TREE_NAME = "Test_reporttest"
class ReportControl: class ReportControl:
def tearDown(self): def tearDown(self):
out, err = self.call("-y", "--remove", TREE_NAME) out, err = self.call("-y", "--remove", TREE_NAME)
out, err = self.call("-y", "--remove", TREE_NAME + "_import_gedcom") # out, err = self.call("-y", "--remove", TREE_NAME + "_import_gedcom")
def call(self, *args): def call(self, *args):
#print("call:", args) #print("call:", args)
@ -49,13 +51,13 @@ class ReportControl:
def __init__(self): def __init__(self):
super().__init__() super().__init__()
self.tearDown() # removes it if it existed self.tearDown() # removes it if it existed
out, err = self.call("-C", TREE_NAME, out, err = self.call("-C", TREE_NAME,
"--import", example) "--import", example)
def addreport(self, class_, report_name, test_function, def addreport(self, class_, report_name, test_function,
files, **options): files, **options):
test_name = report_name.replace("-", "_") test_name = "test_" + report_name.replace("-", "_")
setattr(class_, test_name, dynamic_report_method( setattr(class_, test_name, dynamic_report_method(
report_name, report_name,
test_function, test_function,
@ -68,34 +70,38 @@ class ReportControl:
def addcli(self, class_, report_name, test_function, def addcli(self, class_, report_name, test_function,
files, *args, **options): files, *args, **options):
test_name = report_name.replace("-", "_") test_name = "test_" + report_name.replace("-", "_")
setattr(class_, test_name, setattr(class_, test_name,
dynamic_cli_method( dynamic_cli_method(
report_name, report_name,
test_function, test_function,
files, files,
*args)) *args, **options))
def dynamic_report_method(report_name, test_function, def dynamic_report_method(report_name, test_function,
files, *args, **options): files, *args, **options):
args = list(args) args = list(args)
args[-1] += "," + (",".join(["%s=%s" % (k, v) for (k,v) in options.items()])) args[-1] += "," + (",".join(["%s=%s" % (k, v)
for (k, v) in options.items()]))
options["files"] = files options["files"] = files
# This needs to have "test" in name:
def test_method(self): def test_method(self): # This needs to have "test" in name
out, err = self.call(*args) out, err = self.call(*args)
self.assertTrue(test_function(out, err, report_name, **options)) self.assertTrue(test_function(out, err, report_name, **options))
return test_method return test_method
def dynamic_cli_method(report_name, test_function, def dynamic_cli_method(report_name, test_function,
files, *args, **options): files, *args, **options):
options["files"] = files options["files"] = files
# This needs to have "test" in name:
def test_method(self): def test_method(self): # This needs to have "test" in name
out, err = self.call(*args) out, err = self.call(*args)
self.assertTrue(test_function(out, err, report_name, **options)) self.assertTrue(test_function(out, err, report_name, **options))
return test_method return test_method
class TestDynamic(unittest.TestCase): class TestDynamic(unittest.TestCase):
@classmethod @classmethod
def setUpClass(cls): def setUpClass(cls):
@ -115,10 +121,11 @@ class TestDynamic(unittest.TestCase):
@classmethod @classmethod
def tearDownClass(cls): def tearDownClass(cls):
out, err = cls.call("-y", "--remove", TREE_NAME) out, err = cls.call("-y", "--remove", TREE_NAME)
out, err = cls.call("-y", "--remove", TREE_NAME + "_import_gedcom") # out, err = cls.call("-y", "--remove", TREE_NAME + "_import_gedcom")
reports = ReportControl() reports = ReportControl()
def report_contains(text): def report_contains(text):
def test_output_file(out, err, report_name, **options): def test_output_file(out, err, report_name, **options):
ext = options["off"] ext = options["off"]
@ -134,16 +141,19 @@ def report_contains(text):
elif os.path.isfile(filename): elif os.path.isfile(filename):
os.remove(filename) os.remove(filename)
else: else:
raise Exception("can't find '%s' in order to delete it" % filename) raise Exception("can't find '%s' in order to delete it" %
filename)
elif os.path.isfile(report_name + "." + ext): elif os.path.isfile(report_name + "." + ext):
os.remove(report_name + "." + ext) os.remove(report_name + "." + ext)
else: else:
raise Exception("can't find '%s' in order to delete it" % (report_name + "." + ext)) raise Exception("can't find '%s' in order to delete it" %
(report_name + "." + ext))
return text in contents return text in contents
return test_output_file return test_output_file
def err_does_not_contain(text): def err_does_not_contain(text):
def test_output_file(out, err, report_name, **options): def test_output_file(dummy, err, report_name, **options):
if options.get("files", []): if options.get("files", []):
for filename in options.get("files", []): for filename in options.get("files", []):
if filename is None: if filename is None:
@ -153,18 +163,21 @@ def err_does_not_contain(text):
elif os.path.isfile(filename): elif os.path.isfile(filename):
os.remove(filename) os.remove(filename)
else: else:
raise Exception("can't find '%s' in order to delete it" % filename) raise Exception("can't find '%s' in order to delete it" %
filename)
else: else:
ext = options["off"] ext = options["off"]
if os.path.isfile(report_name + "." + ext): if os.path.isfile(report_name + "." + ext):
os.remove(report_name + "." + ext) os.remove(report_name + "." + ext)
else: else:
raise Exception("can't find '%s' in order to delete it" % (report_name + "." + ext)) raise Exception("can't find '%s' in order to delete it" %
(report_name + "." + ext))
return text not in err return text not in err
return test_output_file return test_output_file
def err_does_contain(text): def err_does_contain(text):
def test_output_file(out, err, report_name, **options): def test_output_file(dummy, err, report_name, **options):
if options.get("files", []): if options.get("files", []):
for filename in options.get("files", []): for filename in options.get("files", []):
if filename is None: if filename is None:
@ -174,21 +187,24 @@ def err_does_contain(text):
elif os.path.isfile(filename): elif os.path.isfile(filename):
os.remove(filename) os.remove(filename)
else: else:
raise Exception("can't find '%s' in order to delete it" % filename) raise Exception("can't find '%s' in order to delete it" %
filename)
else: else:
ext = options["off"] ext = options["off"]
if os.path.isfile(report_name + "." + ext): if os.path.isfile(report_name + "." + ext):
os.remove(report_name + "." + ext) os.remove(report_name + "." + ext)
else: else:
raise Exception("can't find '%s' in order to delete it" % (report_name + "." + ext)) raise Exception("can't find '%s' in order to delete it" %
(report_name + "." + ext))
if isinstance(text, list): if isinstance(text, list):
return all([(line in err) for line in text]) return all([(line in err) for line in text])
else: else:
return text in err return text in err
return test_output_file return test_output_file
def out_does_contain(text): def out_does_contain(text):
def test_output_file(out, err, report_name, **options): def test_output_file(out, dummy, report_name, **options):
if options.get("files", []): if options.get("files", []):
for filename in options.get("files", []): for filename in options.get("files", []):
if filename is None: if filename is None:
@ -198,13 +214,15 @@ def out_does_contain(text):
elif os.path.isfile(filename): elif os.path.isfile(filename):
os.remove(filename) os.remove(filename)
else: else:
raise Exception("can't find '%s' in order to delete it" % filename) raise Exception("can't find '%s' in order to delete it" %
filename)
else: else:
ext = options["off"] ext = options["off"]
if os.path.isfile(report_name + "." + ext): if os.path.isfile(report_name + "." + ext):
os.remove(report_name + "." + ext) os.remove(report_name + "." + ext)
else: else:
raise Exception("can't find '%s' in order to delete it" % (report_name + "." + ext)) raise Exception("can't find '%s' in order to delete it" %
(report_name + "." + ext))
if isinstance(text, list): if isinstance(text, list):
return all([(line in out) for line in text]) return all([(line in out) for line in text])
else: else:
@ -288,58 +306,58 @@ report_list = [
"ancestor_chart-4.svg", "ancestor_chart-4.svg",
"ancestor_chart-5.svg", "ancestor_chart-5.svg",
"ancestor_chart-6.svg", "ancestor_chart-6.svg",
]), # Ancestor Tree ]), # Ancestor Tree
("ancestor_report", "txt", []), # Ahnentafel Report ("ancestor_report", "txt", []), # Ahnentafel Report
("birthday_report", "txt", []), # Birthday and Anniversary Report ("birthday_report", "txt", []), # Birthday and Anniversary Report
("calendar", "svg", ["calendar-10.svg", "calendar-11.svg", ("calendar", "svg", ["calendar-10.svg", "calendar-11.svg",
"calendar-12.svg", "calendar-2.svg", "calendar-12.svg", "calendar-2.svg",
"calendar-3.svg", "calendar-4.svg", "calendar-3.svg", "calendar-4.svg",
"calendar-5.svg", "calendar-6.svg", "calendar-5.svg", "calendar-6.svg",
"calendar-7.svg", "calendar-8.svg", "calendar-7.svg", "calendar-8.svg",
"calendar-9.svg", "calendar.svg"]), # Calendar "calendar-9.svg", "calendar.svg"]), # Calendar
("descend_chart", "svg", []), # Descendant Tree ("descend_chart", "svg", []), # Descendant Tree
("descend_report", "txt", []), # Descendant Report ("descend_report", "txt", []), # Descendant Report
("det_ancestor_report", "txt", []), # Detailed Ancestral Report ("det_ancestor_report", "txt", []), # Detailed Ancestral Report
("det_descendant_report", "txt", []), # Detailed Descendant Report ("det_descendant_report", "txt", []), # Detailed Descendant Report
("endofline_report", "txt", []), # End of Line Report ("endofline_report", "txt", []), # End of Line Report
("family_descend_chart", "svg", []), # Family Descendant Tree ("family_descend_chart", "svg", []), # Family Descendant Tree
("family_group", "txt", []), # Family Group Report ("family_group", "txt", []), # Family Group Report
## COULD be dot ("familylines_graph", "dot", []), # Family Lines Graph # COULD be dot ("familylines_graph", "dot", []), # Family Lines Graph
("fan_chart", "svg", []), # Fan Chart ("fan_chart", "svg", []), # Fan Chart
## COULD be dot ("hourglass_graph", "dot", []), # Hourglass Graph # COULD be dot ("hourglass_graph", "dot", []), # Hourglass Graph
("indiv_complete", "txt", []), # Complete Individual Report ("indiv_complete", "txt", []), # Complete Individual Report
("kinship_report", "txt", []), # Kinship Report ("kinship_report", "txt", []), # Kinship Report
("notelinkreport", "txt", []), # Note Link Report ("notelinkreport", "txt", []), # Note Link Report
("number_of_ancestors", "txt", []), # Number of Ancestors Report ("number_of_ancestors", "txt", []), # Number of Ancestors Report
## NEED a place ("place_report", "txt", []), # Place Report # NEED a place ("place_report", "txt", []), # Place Report
("records", "txt", []), # Records Report ("records", "txt", []), # Records Report
## COULD be dot ("rel_graph", "dot", []), # Relationship Graph # COULD be dot ("rel_graph", "dot", []), # Relationship Graph
("statistics_chart", "svg", ["statistics_chart.svg", ("statistics_chart", "svg", ["statistics_chart.svg", # Statistics Charts
"statistics_chart-2.svg", "statistics_chart-2.svg",
"statistics_chart-3.svg"]), # Statistics Charts "statistics_chart-3.svg"]),
("summary", "txt", []), # Database Summary Report ("summary", "txt", []), # Database Summary Report
("timeline", "svg", ["timeline.svg", "timeline-2.svg"]), # Timeline Chart ("timeline", "svg", ["timeline.svg", "timeline-2.svg"]), # Timeline Chart
] ]
for (report_name, off, files) in report_list: for (_report_name, _off, _files) in report_list:
reports.addreport(TestDynamic, report_name, reports.addreport(TestDynamic, _report_name,
err_does_not_contain("Failed to write report."), err_does_not_contain("Failed to write report."),
files=files, files=_files,
off=off) off=_off)
txt_list = [
"W: Early marriage, Family: F0000, Smith, Martin and Jefferson, Elna",
"W: Multiple parents, Person: I0061, Jones, Roberta Michele",
"W: Multiple parents, Person: I0063, Jones, Frank Albert",
"W: Multiple parents, Person: I0076, Smith, Marie Astri",
"W: Multiple parents, Person: I0077, Smith, Susan Elizabeth",
"W: Old age but no death, Person: I0004, Smith, Ingeman",
"W: Old age but no death, Person: I0009, Smith, Emil",
"W: Old age but no death, Person: I0011, Smith, Hanna",
"W: Old age but no death, Person: I0058, Smith, Elaine Marie",
"W: Old age but no death, Person: I0072, Iverson, Alice Hannah", ]
reports.addcli(TestDynamic, "tool_verify", reports.addcli(TestDynamic, "tool_verify",
out_does_contain([ out_does_contain(txt_list),
"W: Early marriage, Family: F0000, Smith, Martin and Jefferson, Elna",
"W: Multiple parents, Person: I0061, Jones, Roberta Michele",
"W: Multiple parents, Person: I0063, Jones, Frank Albert",
"W: Multiple parents, Person: I0076, Smith, Marie Astri",
"W: Multiple parents, Person: I0077, Smith, Susan Elizabeth",
"W: Old age but no death, Person: I0004, Smith, Ingeman",
"W: Old age but no death, Person: I0009, Smith, Emil",
"W: Old age but no death, Person: I0011, Smith, Hanna",
"W: Old age but no death, Person: I0058, Smith, Elaine Marie",
"W: Old age but no death, Person: I0072, Iverson, Alice Hannah",
]),
[None], [None],
"--force", "--force",
"-O", TREE_NAME, "-O", TREE_NAME,
@ -347,9 +365,10 @@ reports.addcli(TestDynamic, "tool_verify",
"--action", "tool", "--action", "tool",
"--options", "name=verify") "--options", "name=verify")
txt_list = ["6 media objects were referenced, but not found",
"References to 6 media objects were kept"]
reports.addcli(TestDynamic, "tool_check", reports.addcli(TestDynamic, "tool_check",
out_does_contain(["6 media objects were referenced, but not found", out_does_contain(txt_list),
"References to 6 media objects were kept"]),
[None], [None],
"--force", "--force",
"-O", TREE_NAME, "-O", TREE_NAME,