def test_all(self): testsuites = JUnitHtmlReport.create(self._JUNIT_XML_DIR)._parse_xml_files() self.assertEqual(7, len(testsuites)) with temporary_dir() as output_dir: junit_html_report = JUnitHtmlReport.create(xml_dir=self._JUNIT_XML_DIR, open_report=True) with open(junit_html_report.report(output_dir), 'r') as html_file: html_data = html_file.read() self.assertIn('</span> org.pantsbuild.PåssingTest', html_data) self.assertIn('</span> testTwö</td>', html_data) self.assertIn('at org.pantsbuild.PåssingTest.testTwö(ErrorTest.java:29)', html_data)
def test_all(self): test_dir = os.path.join(self.real_build_root, 'tests/python/pants_test/backend/jvm/tasks/reports/junit_html_report_resources') testsuites = JUnitHtmlReport().parse_xml_files(test_dir) self.assertEqual(7, len(testsuites)) with temporary_dir() as output_dir: output_file = os.path.join(output_dir, 'junit-report.html') JUnitHtmlReport().report(test_dir, output_dir) self.assertTrue(os.path.exists(output_file)) with open(output_file) as html_file: html_data = ensure_text(html_file.read()) self.assertIn(u'</span> org.pantsbuild.PåssingTest', html_data) self.assertIn(u'</span> testTwö</td>', html_data) self.assertIn(u'at org.pantsbuild.PåssingTest.testTwö(ErrorTest.java:29)', html_data)
def parse_xml_file(self, basename): xml_file_path = os.path.join( self.real_build_root, 'tests/python/pants_test/backend/jvm/tasks/reports/junit_html_report_resources', basename ) return JUnitHtmlReport._parse_xml_file(xml_file_path)
def test_open_report(self): with temporary_dir() as output_dir: junit_html_report = JUnitHtmlReport.create(xml_dir=self._JUNIT_XML_DIR, open_report=True) report_file_path = junit_html_report.report(output_dir) self.assertIsNotNone(report_file_path) stat = os.stat(report_file_path) self.assertGreater(stat.st_size, 0)
def test_all(self): test_dir = os.path.join( self.real_build_root, 'tests/python/pants_test/backend/jvm/tasks/reports/junt_html_report_resources' ) testsuites = JUnitHtmlReport().parse_xml_files(test_dir) self.assertEqual(6, len(testsuites))
def test_time(self): testsuites = JUnitHtmlReport().parse_xml_file( self.xml_file_path('TEST-org.pantsbuild.TimeTest.xml')) self.assertEqual(1, len(testsuites)) self.assertEqual(4, testsuites[0].tests) self.assertEqual(0.5, testsuites[0].time) self.assertEqual(4, len(testsuites[0].testcases))
def do_report(exc=None): if coverage: coverage.report(all_targets, self.execute_java_for_coverage, tests_failed_exception=exc) if self._html_report: html_file_path = JUnitHtmlReport().report(output_dir, os.path.join(output_dir, 'reports')) if self._open: desktop.ui_open(html_file_path)
def _isolation(self, all_targets): run_dir = '_runs' mode_dir = 'isolated' if self._per_target else 'combined' batch_dir = str(self._batch_size) if self._batched else 'all' output_dir = os.path.join(self.workdir, run_dir, Target.identify(all_targets), mode_dir, batch_dir) safe_mkdir(output_dir, clean=False) if self._html_report: junit_html_report = JUnitHtmlReport.create( xml_dir=output_dir, open_report=self.get_options().open, logger=self.context.log, error_on_conflict=True) else: junit_html_report = NoJunitHtmlReport() coverage = CodeCoverage.global_instance().get_coverage_engine( self, output_dir, all_targets, self.execute_java_for_coverage) reports = self.Reports(junit_html_report, coverage) self.context.release_lock() try: yield output_dir, reports, coverage finally: lock_file = '.file_lock' preserve = (run_dir, lock_file) dist_dir = os.path.join( self.get_options().pants_distdir, os.path.relpath(self.workdir, self.get_options().pants_workdir)) with OwnerPrintingInterProcessFileLock( os.path.join(dist_dir, lock_file)): self._link_current_reports(report_dir=output_dir, link_dir=dist_dir, preserve=preserve) if self._legacy_report_layout: deprecated_conditional( predicate=lambda: True, entity_description='[test.junit] legacy_report_layout', stacklevel=3, removal_version='1.6.0.dev0', hint_message= 'Reports are now linked into {} by default; so scripts ' 'and CI jobs should be pointed there and the option ' 'configured to False in pants.ini until such time as ' 'the option is removed.'.format(dist_dir)) # NB: Deposit of the "current" test output in the root workdir (.pants.d/test/junit) is a # defacto public API and so we implement that behavior here to maintain backwards # compatibility for non-pants report file consumers. with OwnerPrintingInterProcessFileLock( os.path.join(self.workdir, lock_file)): self._link_current_reports(report_dir=output_dir, link_dir=self.workdir, preserve=preserve)
def test_merged_no_conflict(self): with temporary_dir() as xml_dir: def write_xml(name, xml, path=""): with open(os.path.join(xml_dir, path, f"TEST-{name}.xml"), "w") as fp: fp.write(xml) write_xml( "a-1", """ <testsuite name="suite-a" errors="0" failures="0" skipped="0" tests="1" time="0.01"> <testcase name="test-a" time="0.01" /> </testsuite> """, ) write_xml( "a-2", """ <testsuite name="suite-a" errors="0" failures="0" skipped="0" tests="1" time="0.01"> <testcase name="test-b" time="0.01" /> </testsuite> """, ) write_xml( "b", """ <testsuite name="suite-b" errors="0" failures="0" skipped="0" tests="2" time="0.04"> <testcase name="test-a" time="0.01" /> <testcase name="test-b" time="0.03" /> </testsuite> """, ) testsuites = list( ReportTestSuite.merged( JUnitHtmlReport.create(xml_dir)._parse_xml_files())) self.assertEqual(2, len(testsuites)) suites_by_name = {suite.name: suite for suite in testsuites} self.assertEqual(2, len(suites_by_name)) suite_a = suites_by_name["suite-a"] self.assertEqual(0, suite_a.errors) self.assertEqual(0, suite_a.failures) self.assertEqual(0, suite_a.skipped) self.assertEqual(0.02, suite_a.time) self.assertEqual(2, suite_a.tests) self.assertEqual(2, len(suite_a.testcases)) suite_b = suites_by_name["suite-b"] self.assertEqual(0, suite_b.errors) self.assertEqual(0, suite_b.failures) self.assertEqual(0, suite_b.skipped) self.assertEqual(0.04, suite_b.time) self.assertEqual(2, suite_b.tests) self.assertEqual(2, len(suite_b.testcases))
def test_unicode(self): testsuites = JUnitHtmlReport().parse_xml_file(self.xml_file_path('TEST-org.pantsbuild.UnicodeCharsTest.xml')) self.assertEqual(1, len(testsuites)) self.assertEqual(2, testsuites[0].tests) self.assertEqual(2, len(testsuites[0].testcases)) self.assertEquals(u'org.pantsbuild.PåssingTest', testsuites[0].name) self.assertEquals(u'testTwö', testsuites[0].testcases[1].name) self.assertIn(u'org.pantsbuild.PåssingTest.testTwö', testsuites[0].testcases[1].error['message'])
def test_skipped(self): testsuites = JUnitHtmlReport().parse_xml_file(self.xml_file_path('TEST-org.pantsbuild.SkippedTest.xml')) self.assertEqual(1, len(testsuites)) self.assertEqual(1, testsuites[0].tests) self.assertEqual(0, testsuites[0].errors) self.assertEqual(0, testsuites[0].failures) self.assertEqual(1, testsuites[0].skipped) self.assertEqual(0, testsuites[0].time) self.assertEqual(1, len(testsuites[0].testcases))
def do_report(exc=None): if coverage: coverage.report(all_targets, self.execute_java_for_coverage, tests_failed_exception=exc) if self._html_report: self.context.log.debug('Generating JUnit HTML report...') html_file_path = JUnitHtmlReport().report(output_dir, os.path.join(output_dir, 'reports')) self.context.log.debug('JUnit HTML report generated to {}'.format(html_file_path)) if self._open: desktop.ui_open(html_file_path)
def _do_report(exception=None): if self._coverage: self._coverage.report(targets, tests_and_targets.keys(), self.execute_java_for_coverage, tests_failed_exception=exception) if self._html_report: html_file_path = JUnitHtmlReport().report( self.workdir, os.path.join(self.workdir, 'reports')) if self._open: binary_util.ui_open(html_file_path)
def test_passing(self): testsuites = JUnitHtmlReport().parse_xml_file(self.xml_file_path('TEST-org.pantsbuild.PassingTest.xml')) self.assertEqual(1, len(testsuites)) self.assertEqual(4, testsuites[0].tests) self.assertEqual(0, testsuites[0].errors) self.assertEqual(0, testsuites[0].failures) self.assertEqual(0, testsuites[0].skipped) self.assertEqual(4.76, testsuites[0].time) self.assertEqual(4, len(testsuites[0].testcases)) self.assertIsNone(testsuites[0].testcases[0].failure) self.assertIsNone(testsuites[0].testcases[0].error)
def test_failed(self): testsuites = JUnitHtmlReport().parse_xml_file(self.xml_file_path('TEST-org.pantsbuild.FailureTest.xml')) self.assertEqual(1, len(testsuites)) self.assertEqual(1, testsuites[0].tests) self.assertEqual(0, testsuites[0].errors) self.assertEqual(1, testsuites[0].failures) self.assertEqual(0, testsuites[0].skipped) self.assertEqual(0.01, testsuites[0].time) self.assertEqual(1, len(testsuites[0].testcases)) self.assertIsNone(testsuites[0].testcases[0].error) self.assertEquals('java.lang.AssertionError', testsuites[0].testcases[0].failure['type']) self.assertIn('java.lang.AssertionError', testsuites[0].testcases[0].failure['message'])
def test_errored(self): testsuites = JUnitHtmlReport().parse_xml_file(self.xml_file_path('TEST-org.pantsbuild.ErrorTest.xml')) self.assertEqual(1, len(testsuites)) self.assertEqual(1, testsuites[0].tests) self.assertEqual(1, testsuites[0].errors) self.assertEqual(0, testsuites[0].failures) self.assertEqual(0, testsuites[0].skipped) self.assertEqual(0.32, testsuites[0].time) self.assertEqual(1, len(testsuites[0].testcases)) self.assertIsNone(testsuites[0].testcases[0].failure) self.assertEquals('java.lang.RuntimeException', testsuites[0].testcases[0].error['type']) self.assertIn('java.lang.RuntimeException', testsuites[0].testcases[0].error['message'])
def _isolation(self, all_targets): run_dir = '_runs' output_dir = os.path.join(self.workdir, run_dir, Target.identify(all_targets)) safe_mkdir(output_dir, clean=False) if self._html_report: junit_html_report = JUnitHtmlReport.create(output_dir, self.context.log) else: junit_html_report = NoJunitHtmlReport() if self.get_options().coverage or self.get_options().is_flagged( 'coverage_open'): settings = CoberturaTaskSettings.from_task(self, workdir=output_dir) coverage = Cobertura(settings, all_targets, self.execute_java_for_coverage) else: coverage = NoCoverage() reports = self.Reports(junit_html_report, coverage) self.context.release_lock() try: yield output_dir, reports, coverage finally: # NB: Deposit of the "current" test output in the root workdir (.pants.d/test/junit) is a # defacto public API and so we implement that behavior here to maintain backwards # compatibility for non-pants report file consumers. # TODO(John Sirois): Deprecate this ~API and provide a stable directory solution for test # output: https://github.com/pantsbuild/pants/issues/3879 lock_file = '.file_lock' with OwnerPrintingInterProcessFileLock( os.path.join(self.workdir, lock_file)): # Kill everything except the isolated `_runs/` dir. for name in os.listdir(self.workdir): path = os.path.join(self.workdir, name) if name not in (run_dir, lock_file): if os.path.isdir(path): safe_rmtree(path) else: os.unlink(path) # Link all the isolated run/ dir contents back up to the stable workdir for name in os.listdir(output_dir): path = os.path.join(output_dir, name) os.symlink(path, os.path.join(self.workdir, name))
def test_merged_conflict_first(self): with self.merge_conflict() as xml_dir: report = JUnitHtmlReport.create(xml_dir, error_on_conflict=False) testsuites = report._parse_xml_files() self.assertEqual(1, len(testsuites)) suite_a = testsuites[0] self.assertEqual(1, suite_a.errors) self.assertEqual(0, suite_a.failures) self.assertEqual(0, suite_a.skipped) self.assertEqual(0.04, suite_a.time) self.assertEqual(2, suite_a.tests) self.assertEqual([ReportTestCase(name='test-a', time=0.02), ReportTestCase(name='test-b', time=0.02, error='java.lang.RuntimeException!')], suite_a.testcases)
def test_merged_no_conflict(self): with temporary_dir() as xml_dir: def write_xml(name, xml, path=''): with open(os.path.join(xml_dir, path, 'TEST-{}.xml'.format(name)), 'w') as fp: fp.write(xml) write_xml('a-1', """ <testsuite name="suite-a" errors="0" failures="0" skipped="0" tests="1" time="0.01"> <testcase name="test-a" time="0.01" /> </testsuite> """) write_xml('a-2', """ <testsuite name="suite-a" errors="0" failures="0" skipped="0" tests="1" time="0.01"> <testcase name="test-b" time="0.01" /> </testsuite> """) write_xml('b', """ <testsuite name="suite-b" errors="0" failures="0" skipped="0" tests="2" time="0.04"> <testcase name="test-a" time="0.01" /> <testcase name="test-b" time="0.03" /> </testsuite> """) testsuites = list(ReportTestSuite.merged(JUnitHtmlReport.create(xml_dir)._parse_xml_files())) self.assertEqual(2, len(testsuites)) suites_by_name = {suite.name: suite for suite in testsuites} self.assertEqual(2, len(suites_by_name)) suite_a = suites_by_name['suite-a'] self.assertEqual(0, suite_a.errors) self.assertEqual(0, suite_a.failures) self.assertEqual(0, suite_a.skipped) self.assertEqual(0.02, suite_a.time) self.assertEqual(2, suite_a.tests) self.assertEqual(2, len(suite_a.testcases)) suite_b = suites_by_name['suite-b'] self.assertEqual(0, suite_b.errors) self.assertEqual(0, suite_b.failures) self.assertEqual(0, suite_b.skipped) self.assertEqual(0.04, suite_b.time) self.assertEqual(2, suite_b.tests) self.assertEqual(2, len(suite_b.testcases))
def test_all(self): test_dir = os.path.join( self.real_build_root, 'tests/python/pants_test/backend/jvm/tasks/reports/junit_html_report_resources' ) testsuites = JUnitHtmlReport._parse_xml_files(test_dir) self.assertEqual(7, len(testsuites)) with temporary_dir() as output_dir: output_file = os.path.join(output_dir, 'junit-report.html') JUnitHtmlReport(xml_dir=test_dir, report_dir=output_dir, logger=mock.Mock()).report() self.assertTrue(os.path.exists(output_file)) with open(output_file) as html_file: html_data = ensure_text(html_file.read()) self.assertIn(u'</span> org.pantsbuild.PåssingTest', html_data) self.assertIn(u'</span> testTwö</td>', html_data) self.assertIn(u'at org.pantsbuild.PåssingTest.testTwö(ErrorTest.java:29)', html_data)
def _isolation(self, all_targets): run_dir = '_runs' output_dir = os.path.join(self.workdir, run_dir, Target.identify(all_targets)) safe_mkdir(output_dir, clean=False) if self._html_report: junit_html_report = JUnitHtmlReport.create(output_dir, self.context.log) else: junit_html_report = NoJunitHtmlReport() if self.get_options().coverage or self.get_options().is_flagged('coverage_open'): settings = CoberturaTaskSettings.from_task(self, workdir=output_dir) coverage = Cobertura(settings, all_targets, self.execute_java_for_coverage) else: coverage = NoCoverage() reports = self.Reports(junit_html_report, coverage) self.context.release_lock() try: yield output_dir, reports, coverage finally: # NB: Deposit of the "current" test output in the root workdir (.pants.d/test/junit) is a # defacto public API and so we implement that behavior here to maintain backwards # compatibility for non-pants report file consumers. # TODO(John Sirois): Deprecate this ~API and provide a stable directory solution for test # output: https://github.com/pantsbuild/pants/issues/3879 lock_file = '.file_lock' with OwnerPrintingInterProcessFileLock(os.path.join(self.workdir, lock_file)): # Kill everything except the isolated `_runs/` dir. for name in os.listdir(self.workdir): path = os.path.join(self.workdir, name) if name not in (run_dir, lock_file): if os.path.isdir(path): safe_rmtree(path) else: os.unlink(path) # Link all the isolated run/ dir contents back up to the stable workdir for name in os.listdir(output_dir): path = os.path.join(output_dir, name) os.symlink(path, os.path.join(self.workdir, name))
def _isolation(self, per_target, all_targets): run_dir = '_runs' mode_dir = 'isolated' if per_target else 'combined' batch_dir = str(self._batch_size) if self._batched else 'all' output_dir = os.path.join(self.workdir, run_dir, Target.identify(all_targets), mode_dir, batch_dir) safe_mkdir(output_dir, clean=False) if self._html_report: junit_html_report = JUnitHtmlReport.create( xml_dir=output_dir, open_report=self.get_options().open, logger=self.context.log, error_on_conflict=self.get_options( ).html_report_error_on_conflict) else: junit_html_report = NoJunitHtmlReport() coverage = CodeCoverage.global_instance().get_coverage_engine( self, output_dir, all_targets, self.execute_java_for_coverage) reports = self.Reports(junit_html_report, coverage) self.context.release_lock() try: yield output_dir, reports, coverage finally: lock_file = '.file_lock' preserve = (run_dir, lock_file) dist_dir = os.path.join( self.get_options().pants_distdir, os.path.relpath(self.workdir, self.get_options().pants_workdir)) with OwnerPrintingInterProcessFileLock( os.path.join(dist_dir, lock_file)): self._link_current_reports(report_dir=output_dir, link_dir=dist_dir, preserve=preserve)
def _isolation(self, per_target, all_targets): run_dir = '_runs' mode_dir = 'isolated' if per_target else 'combined' batch_dir = str(self._batch_size) if self._batched else 'all' output_dir = os.path.join(self.workdir, run_dir, Target.identify(all_targets), mode_dir, batch_dir) safe_mkdir(output_dir, clean=False) if self._html_report: junit_html_report = JUnitHtmlReport.create(xml_dir=output_dir, open_report=self.get_options().open, logger=self.context.log, error_on_conflict=True) else: junit_html_report = NoJunitHtmlReport() coverage = CodeCoverage.global_instance().get_coverage_engine( self, output_dir, all_targets, self.execute_java_for_coverage) reports = self.Reports(junit_html_report, coverage) self.context.release_lock() try: yield output_dir, reports, coverage finally: lock_file = '.file_lock' preserve = (run_dir, lock_file) dist_dir = os.path.join(self.get_options().pants_distdir, os.path.relpath(self.workdir, self.get_options().pants_workdir)) with OwnerPrintingInterProcessFileLock(os.path.join(dist_dir, lock_file)): self._link_current_reports(report_dir=output_dir, link_dir=dist_dir, preserve=preserve)
def test_merged_conflict_error(self): with self.merge_conflict() as xml_dir: report = JUnitHtmlReport.create(xml_dir, error_on_conflict=True) with self.assertRaises(ReportTestSuite.MergeError): report._parse_xml_files()
def test_no_open_report(self): with temporary_dir() as output_dir: junit_html_report = JUnitHtmlReport.create(xml_dir=self._JUNIT_XML_DIR, open_report=False) report_file_path = junit_html_report.report(output_dir) self.assertIsNone(report_file_path)
def parse_xml_file(self, basename): xml_file_path = os.path.join(self._JUNIT_XML_DIR, basename) return JUnitHtmlReport._parse_xml_file(xml_file_path)
def test_empty(self): testsuites = JUnitHtmlReport().parse_xml_file(self.xml_file_path('TEST-org.pantsbuild.EmptyTestSuite.xml')) self.assertEqual(1, len(testsuites)) self.assertEqual(0, len(testsuites[0].testcases))