Skip to content

Commit dea7d8f

Browse files
committed
Consistent --output; Improved coverage: main()
Coverage at 99% according to coverage.py * `compare_perf_tests.py` now always outputs the same format to stdout as is written to `--output` file * Added integration test for the main() function * Added tests for console output (and suppressed it leaking during testing) * Fixed file name in test’s file header
1 parent 9265a71 commit dea7d8f

File tree

2 files changed

+129
-46
lines changed

2 files changed

+129
-46
lines changed

benchmark/scripts/compare_perf_tests.py

Lines changed: 13 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -268,7 +268,7 @@ def _formatted_text(self, ROW, HEADER_SEPARATOR, DETAIL):
268268
widths = self._column_widths()
269269

270270
def justify_columns(contents):
271-
return tuple(map(lambda (w, c): c.ljust(w), zip(widths, contents)))
271+
return tuple([c.ljust(w) for w, c in zip(widths, contents)])
272272

273273
def row(contents):
274274
return ROW.format(*justify_columns(contents))
@@ -409,34 +409,18 @@ def main():
409409
args.delta_threshold)
410410
formatter = ReportFormatter(comparator, args.old_branch, args.new_branch,
411411
args.changes_only)
412-
413-
if args.format:
414-
if args.format.lower() != 'markdown':
415-
print(formatter.git())
416-
else:
417-
print(formatter.markdown())
418-
419-
if args.format:
420-
if args.format.lower() == 'html':
421-
if args.output:
422-
write_to_file(args.output, formatter.html())
423-
else:
424-
print('Error: missing --output flag.')
425-
sys.exit(1)
426-
elif args.format.lower() == 'markdown':
427-
if args.output:
428-
write_to_file(args.output, formatter.markdown())
429-
elif args.format.lower() != 'git':
430-
print('{0} is unknown format.'.format(args.format))
431-
sys.exit(1)
432-
433-
434-
def write_to_file(file_name, data):
435-
"""
436-
Write data to given file
437-
"""
438-
with open(file_name, 'w') as f:
439-
f.write(data)
412+
formats = {
413+
'markdown': formatter.markdown,
414+
'git': formatter.git,
415+
'html': formatter.html
416+
}
417+
418+
report = formats[args.format]()
419+
print(report)
420+
421+
if args.output:
422+
with open(args.output, 'w') as f:
423+
f.write(report)
440424

441425

442426
if __name__ == '__main__':

benchmark/scripts/test_compare_perf_tests.py

Lines changed: 116 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#!/usr/bin/python
22
# -*- coding: utf-8 -*-
33

4-
# ===--- benchmark_utils.py ----------------------------------------------===//
4+
# ===--- test_compare_perf_tests.py --------------------------------------===//
55
#
66
# This source file is part of the Swift.org open source project
77
#
@@ -15,16 +15,32 @@
1515

1616
import os
1717
import shutil
18+
import sys
1819
import tempfile
1920
import unittest
2021

22+
from StringIO import StringIO
23+
from contextlib import contextmanager
24+
2125
from compare_perf_tests import PerformanceTestResult
2226
from compare_perf_tests import ReportFormatter
2327
from compare_perf_tests import ResultComparison
2428
from compare_perf_tests import TestComparator
29+
from compare_perf_tests import main
2530
from compare_perf_tests import parse_args
2631

2732

33+
@contextmanager
34+
def captured_output():
35+
new_out, new_err = StringIO(), StringIO()
36+
old_out, old_err = sys.stdout, sys.stderr
37+
try:
38+
sys.stdout, sys.stderr = new_out, new_err
39+
yield sys.stdout, sys.stderr
40+
finally:
41+
sys.stdout, sys.stderr = old_out, old_err
42+
43+
2844
class TestPerformanceTestResult(unittest.TestCase):
2945

3046
def test_init(self):
@@ -195,6 +211,11 @@ def write_temp_file(self, file_name, data):
195211
f.write(data)
196212
return temp_file_name
197213

214+
def assert_report_contains(self, texts, report):
215+
assert not isinstance(texts, str)
216+
for text in texts:
217+
self.assertIn(text, report)
218+
198219

199220
class TestTestComparator(OldAndNewLog):
200221
def test_init(self):
@@ -236,14 +257,6 @@ def setUp(self):
236257
self.git = self.rf.git()
237258
self.html = self.rf.html()
238259

239-
def assert_report_contains(self, texts, report):
240-
# assert not isinstance(texts, str)
241-
if isinstance(texts, str):
242-
self.assertIn(texts, report)
243-
else:
244-
for text in texts:
245-
self.assertIn(text, report)
246-
247260
def assert_markdown_contains(self, texts):
248261
self.assert_report_contains(texts, self.markdown)
249262

@@ -257,7 +270,6 @@ def test_justified_columns(self):
257270
"""Table columns are all formated with same width, defined by the
258271
longest value.
259272
"""
260-
print self.markdown
261273
self.assert_markdown_contains([
262274
'AnyHashableWithAClass | 247027 | 319065 | 259056 | 10250445',
263275
'Array2D | 335831 | 335831 | +0.0% | 1.00x'])
@@ -269,7 +281,6 @@ def test_column_headers(self):
269281
"""Report contains table headers for ResultComparisons and changed
270282
PerformanceTestResults.
271283
"""
272-
print self.git
273284
self.assert_markdown_contains([
274285
'TEST | OLD | NEW | DELTA | SPEEDUP',
275286
'--- | --- | --- | --- | --- ',
@@ -304,7 +315,6 @@ def test_emphasize_speedup(self):
304315
'AngryPhonebook 10458 10458 +0.0% 1.00x',
305316
'ArrayAppend 23641 20000 -15.4% **1.18x (?)**'
306317
])
307-
print self.html
308318
self.assert_html_contains([
309319
"""
310320
<tr>
@@ -374,21 +384,30 @@ class Test_parse_args(unittest.TestCase):
374384
required = ['--old-file', 'old.log', '--new-file', 'new.log']
375385

376386
def test_required_input_arguments(self):
387+
with captured_output() as (_, err):
388+
self.assertRaises(SystemExit, parse_args, [])
389+
self.assertIn('usage: compare_perf_tests.py', err.getvalue())
390+
377391
args = parse_args(self.required)
378392
self.assertEquals(args.old_file, 'old.log')
379393
self.assertEquals(args.new_file, 'new.log')
380-
self.assertRaises(SystemExit, parse_args, [])
381394

382395
def test_format_argument(self):
396+
self.assertEquals(parse_args(self.required).format, 'markdown')
383397
self.assertEquals(
384398
parse_args(self.required + ['--format', 'markdown']).format,
385399
'markdown')
386400
self.assertEquals(
387401
parse_args(self.required + ['--format', 'git']).format, 'git')
388402
self.assertEquals(
389403
parse_args(self.required + ['--format', 'html']).format, 'html')
390-
self.assertRaises(SystemExit, parse_args,
391-
self.required + ['--format', 'bogus'])
404+
405+
with captured_output() as (_, err):
406+
self.assertRaises(SystemExit, parse_args,
407+
self.required + ['--format', 'bogus'])
408+
self.assertIn("error: argument --format: invalid choice: 'bogus' "
409+
"(choose from 'markdown', 'git', 'html')",
410+
err.getvalue())
392411

393412
def test_delta_threshold_argument(self):
394413
# default value
@@ -401,8 +420,13 @@ def test_delta_threshold_argument(self):
401420
self.assertEquals(args.delta_threshold, 1.0)
402421
args = parse_args(self.required + ['--delta-threshold', '.2'])
403422
self.assertEquals(args.delta_threshold, 0.2)
404-
self.assertRaises(SystemExit, parse_args,
405-
self.required + ['--delta-threshold', '2,2'])
423+
424+
with captured_output() as (_, err):
425+
self.assertRaises(SystemExit, parse_args,
426+
self.required + ['--delta-threshold', '2,2'])
427+
self.assertIn(" error: argument --delta-threshold: invalid float "
428+
"value: '2,2'",
429+
err.getvalue())
406430

407431
def test_output_argument(self):
408432
self.assertEquals(parse_args(self.required).output, None)
@@ -428,5 +452,80 @@ def test_branch_arguments(self):
428452
self.assertEquals(args.new_branch, 'amazing-optimization')
429453

430454

455+
class Test_compare_perf_tests_main(OldAndNewLog):
456+
"""Integration test that invokes the whole comparison script."""
457+
markdown = [
458+
'<summary>Regression (1)</summary>',
459+
'TEST | OLD | NEW | DELTA | SPEEDUP',
460+
'BitCount | 3 | 9 | +199.9% | **0.33x**',
461+
]
462+
git = [
463+
'Regression (1):',
464+
'TEST OLD NEW DELTA SPEEDUP',
465+
'BitCount 3 9 +199.9% **0.33x**',
466+
]
467+
html = ['<html>', "<td align='left'>BitCount</td>"]
468+
469+
def execute_main_with_format(self, report_format, test_output=False):
470+
report_file = self.test_dir + 'report.log'
471+
args = ['compare_perf_tests.py',
472+
'--old-file', self.old_log,
473+
'--new-file', self.new_log,
474+
'--format', report_format]
475+
476+
sys.argv = (args if not test_output else
477+
args + ['--output', report_file])
478+
479+
with captured_output() as (out, _):
480+
main()
481+
report_out = out.getvalue()
482+
483+
if test_output:
484+
with open(report_file, 'r') as f:
485+
report = f.read()
486+
# because print adds newline, add one here, too:
487+
report_file = str(report + '\n')
488+
else:
489+
report_file = None
490+
491+
return report_out, report_file
492+
493+
def test_markdown(self):
494+
"""Writes Markdown formatted report to stdout"""
495+
report_out, _ = self.execute_main_with_format('markdown')
496+
self.assert_report_contains(self.markdown, report_out)
497+
498+
def test_markdown_output(self):
499+
"""Writes Markdown formatted report to stdout and `--output` file."""
500+
report_out, report_file = (
501+
self.execute_main_with_format('markdown', test_output=True))
502+
self.assertEquals(report_out, report_file)
503+
self.assert_report_contains(self.markdown, report_file)
504+
505+
def test_git(self):
506+
"""Writes Git formatted report to stdout."""
507+
report_out, _ = self.execute_main_with_format('git')
508+
self.assert_report_contains(self.git, report_out)
509+
510+
def test_git_output(self):
511+
"""Writes Git formatted report to stdout and `--output` file."""
512+
report_out, report_file = (
513+
self.execute_main_with_format('git', test_output=True))
514+
self.assertEquals(report_out, report_file)
515+
self.assert_report_contains(self.git, report_file)
516+
517+
def test_html(self):
518+
"""Writes HTML formatted report to stdout."""
519+
report_out, _ = self.execute_main_with_format('html')
520+
self.assert_report_contains(self.html, report_out)
521+
522+
def test_html_output(self):
523+
"""Writes HTML formatted report to stdout and `--output` file."""
524+
report_out, report_file = (
525+
self.execute_main_with_format('html', test_output=True))
526+
self.assertEquals(report_out, report_file)
527+
self.assert_report_contains(self.html, report_file)
528+
529+
431530
if __name__ == '__main__':
432531
unittest.main()

0 commit comments

Comments
 (0)