From 4024a9446a4c7219649569a891d7edf002f288e0 Mon Sep 17 00:00:00 2001 From: Ralph Giles Date: Mon, 3 Jun 2019 16:05:25 -0700 Subject: [PATCH 1/2] Don't assert on empty directories. When run on a directory with no cts data at all, the report generator for `hooktest --console` would throw a StatisticsError trying to calculate the mean coverage over zero files. Check for this condition and report zero coverage instead. Add a test for this condition, invoking hooktest on the included emptydir fixture. --- HookTest/test.py | 6 +++++- tests/test_run.py | 27 ++++++++++++++++++++++++++- 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/HookTest/test.py b/HookTest/test.py index 20eb5d1..51c75fe 100644 --- a/HookTest/test.py +++ b/HookTest/test.py @@ -612,7 +612,11 @@ def end(self): dtds=dtd_errors, empts=empty_refs)) t_pass = num_texts - num_failed - cov = round(statistics.mean([test.coverage for test in self.results.values()]), ndigits=2) + cov_results = [test.coverage for test in self.results.values()] + if cov_results: + cov = round(statistics.mean(cov_results), ndigits=2) + else: + cov = 0.00 results_table = PT(["HookTestResults", ""]) results_table.align["HookTestResults", ""] = "c" results_table.hrules = pt_all diff --git a/tests/test_run.py b/tests/test_run.py index cf715b4..bc5b50f 100644 --- a/tests/test_run.py +++ b/tests/test_run.py @@ -77,7 +77,7 @@ def hooktest(self, args): ..note:: See https://wrongsideofmemphis.wordpress.com/2010/03/01/store-standard-output-on-a-variable-in-python/ :param args: List of commandline arguments - :return: Sys stdout, status + :return: status, output_string """ # Store the reference, in case you want to show things again in standard output old_stdout = sys.stdout @@ -570,3 +570,28 @@ def test_run_local_greek_count_word_raise(self): "Word Counting", logs, "Word Counting should not be there" ) + + def test_run_emptyDir(self): + """Test a run against an empty directory. + + Should fail but not assert.""" + status, logs = self.hooktest([ + "./tests/emptyDir", "--console", "--verbose" + ]) + self.assertLogResult( + logs, "Total Texts", "0", + "No texts should have been found" + ) + self.assertLogResult( + logs, "Passing Texts", "0", + "No texts should have passed" + ) + self.assertLogResult( + logs, "Metadata Files", "0", + "No metadata should have been found" + ) + self.assertLogResult( + logs, "Passing Metadata", "0", + "No metadata should have passed" + ) + self.assertEqual(status, "error", "Should error with no files") From d4e9ed995eb7ad5050359f8822a86fc8993d659d Mon Sep 17 00:00:00 2001 From: Ralph Giles Date: Mon, 3 Jun 2019 18:03:59 -0700 Subject: [PATCH 2/2] Clean up test.run code. The file lists returned by the finder are already iterable, so there's no need to create a new list from them. If there were just wrapping them in `list()` is another possiblity. Also update the comments so they match the code better. --- HookTest/test.py | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/HookTest/test.py b/HookTest/test.py index 20eb5d1..fd2756c 100644 --- a/HookTest/test.py +++ b/HookTest/test.py @@ -400,11 +400,11 @@ def run(self): self.text_files, self.cts_files = self.find() self.start() - # We deal with Inventory files first to get a list of urns + # We deal with Inventory files first to get a list of urns with Pool(processes=self.workers) as executor: - # We iterate over a dictionary of completed tasks - for future in executor.imap_unordered(self.unit, [file for file in self.cts_files]): + # We iterate over the list of files, checking them in parallel. + for future in executor.imap_unordered(self.unit, self.cts_files): result, filepath, additional = future self.results[filepath] = result self.passing[filepath] = result.status @@ -416,10 +416,9 @@ def run(self): executor.join() self.middle() # To print the results from the metadata file tests - # We load a thread pool which has 5 maximum workers + # Now deal with the text files. with Pool(processes=self.workers) as executor: - # We create a dictionary of tasks which - for future in executor.imap_unordered(self.unit, [file for file in self.text_files]): + for future in executor.imap_unordered(self.unit, self.text_files): result, filepath, additional = future self.results[filepath] = result self.passing[filepath] = result.status