def testParsePytestSomeFail(): """Parse a report from pytest where some tests fail.""" xml = ''' <?xml version="1.0" encoding="utf-8"?> <testsuites> <testsuite errors="0" failures="1" hostname="hyperion" name="pytest" skipped="0" tests="3" time="1.234" timestamp="2020-08-13T13:03:59.945171"> <testcase classname="test_databaselib" file="test_databaselib.py" line="117" name="testEmpty[Database]" time="0.216"/> <testcase classname="test_databaselib" file="test_databaselib.py" line="117" name="testEmpty[VersionedDatabase]" time="0.001"/> <testcase classname="test_joblib.TestJobs" file="test_joblib.py" line="444" name="test0110TRSetRandomRun" time="0.000"> <failure message="RuntimeError: forced">self = <test_joblib.TestJobs testMethod=test0110TRSetRandomRun> def setUp(self): > raise RuntimeError('forced') E RuntimeError: forced test_joblib.py:45: RuntimeError</failure> </testcase> </testsuite> </testsuites> '''.lstrip() report = parseReport(lambda: StringIO(xml), 'report.xml') assert report is not None assert report.errors == 0 assert report.failures == 1 assert report.skipped == 0 assert report.numTestcases == 3 assert report.result is ResultCode.WARNING assert report.summary == '1 failed' data = report.data assert data['testcases'] == '3' assert data['checks'] == '3' assert data['failures'] == '1' assert data['errors'] == '0' assert data['skipped'] == '0' assert len(report.testsuite) == 1 suite, = report.testsuite assert suite.tests == 3 assert suite.failures == 1 assert suite.errors == 0 assert suite.skipped == 0 assert suite.time == 1.234 assert suite.result is ResultCode.WARNING assert len(suite.testcase) == 3 for index, case in enumerate(suite.testcase): if index == 2: assert case.result is ResultCode.WARNING assert case.failure else: assert case.result is ResultCode.OK assert not case.failure assert not case.error assert not case.skipped
def createPresenter(opener: Callable[[], IO[bytes]], fileName: str) -> Optional[ReportPresenter]: """Attempt to create a custom presenter for the given artifact. Return a resource that handles the presentation, or None if no custom presentation is available or desired for this artifact. """ message: Optional[str] try: report = parseReport(opener, fileName) except ValueError as ex: message = str(ex) else: if isinstance(report, JUnitReport): return JUnitPresenter(report) message = None # TODO: Perform file type detection to see if we want to do custom # presentation. # We can probably combine mimetypes.guess_type with the info # from Pygments into a new detection function that's also used # by the 'artifacts' module. # Only use source highlighting for text formats, except for HTML. if message is None: contentType, contentEncoding_ = guess_type(fileName, strict=False) if not contentType or not contentType.startswith('text/'): return None if contentType == 'text/html': return None # Load file contents into a string. # TODO: Use encoding information from the XML parsing, if available. # TODO: Do we want to display the original text or pretty-print the # parsed version? with opener() as stream: with UTF8Reader(stream, errors='replace') as reader: text = reader.read() if text.count('\n') >= 1000: # Workaround for slow rendering (both server and client side) # of long text files: returning None will show the raw text file # in an iframe instead of formatting it as HTML. # https://github.com/boxingbeetle/softfab/issues/31 return None try: lexer = guess_lexer_for_filename(fileName, text) except ClassNotFound: return None else: return PygmentedPresenter(message, text, lexer)
def testParsePytestSomeSkipped(): """Parse a report from pytest where some tests were skipped.""" xml = ''' <?xml version="1.0" encoding="utf-8"?> <testsuites> <testsuite errors="0" failures="0" hostname="hyperion" name="pytest" skipped="1" tests="3" time="1.234" timestamp="2020-08-13T13:03:59.945171"> <testcase classname="test_databaselib" file="test_databaselib.py" line="117" name="testEmpty[Database]" time="0.216"/> <testcase classname="test_databaselib" file="test_databaselib.py" line="117" name="testEmpty[VersionedDatabase]" time="0.001"/> <testcase classname="test_taskrunnerlib" file="test_taskrunnerlib.py" line="211" name="testTaskRunnerToXML[data0]" time="0.000"> <skipped message="test fails if there is a module reload between collection and execution, as it breaks isinstance() inside __eq__()" type="pytest.skip">test_taskrunnerlib.py:211: test fails if there is a module reload between collection and execution, as it breaks isinstance() inside __eq__()</skipped> </testcase> </testsuite> </testsuites> '''.lstrip() report = parseReport(lambda: StringIO(xml), 'report.xml') assert report is not None assert report.errors == 0 assert report.failures == 0 assert report.skipped == 1 assert report.numTestcases == 3 assert report.result is ResultCode.OK assert report.summary == '0 failed, 1 skipped' data = report.data assert data['testcases'] == '3' assert data['checks'] == '3' assert data['failures'] == '0' assert data['errors'] == '0' assert data['skipped'] == '1' assert len(report.testsuite) == 1 suite, = report.testsuite assert suite.tests == 3 assert suite.failures == 0 assert suite.errors == 0 assert suite.skipped == 1 assert suite.time == 1.234 assert suite.result is ResultCode.OK assert len(suite.testcase) == 3 for index, case in enumerate(suite.testcase): if index == 2: assert case.result is ResultCode.CANCELLED assert case.skipped else: assert case.result is ResultCode.OK assert not case.skipped assert not case.error assert not case.failure
def testParsePytestAllPass(): """Parse a report from pytest where all tests pass.""" xml = ''' <?xml version="1.0" encoding="utf-8"?> <testsuites> <testsuite errors="0" failures="0" hostname="hyperion" name="pytest" skipped="0" tests="3" time="1.234" timestamp="2020-08-13T13:03:59.945171"> <testcase classname="test_databaselib" file="test_databaselib.py" line="117" name="testEmpty[Database]" time="0.216"/> <testcase classname="test_databaselib" file="test_databaselib.py" line="117" name="testEmpty[VersionedDatabase]" time="0.001"/> <testcase classname="test_databaselib" file="test_databaselib.py" line="338" name="testMixedRandom" time="0.749"> <system-out>Random seed: 1597316644 </system-out> </testcase> </testsuite> </testsuites> '''.lstrip() report = parseReport(lambda: StringIO(xml), 'report.xml') assert report is not None assert report.errors == 0 assert report.failures == 0 assert report.skipped == 0 assert report.numTestcases == 3 assert report.result is ResultCode.OK assert report.summary == '0 failed' data = report.data assert data['testcases'] == '3' assert data['checks'] == '3' assert data['failures'] == '0' assert data['errors'] == '0' assert data['skipped'] == '0' assert len(report.testsuite) == 1 suite, = report.testsuite assert suite.tests == 3 assert suite.failures == 0 assert suite.errors == 0 assert suite.skipped == 0 assert suite.time == 1.234 assert suite.result is ResultCode.OK assert len(suite.testcase) == 3 for case in suite.testcase: assert case.result is ResultCode.OK assert not case.error assert not case.failure assert not case.skipped
def parseReports(self) -> Iterator[Report]: for fileName in self.__reports: opener = self.reportOpener(fileName) if opener is not None: try: report = parseReport(opener, fileName) except ValueError as ex: logging.info( 'Failed to parse report "%s": %s', fileName, ex ) except OSError as ex: logging.error( 'Failed to read report "%s": %s', fileName, ex ) else: if report is not None: yield report
def testParsePytestEmpty(): """Parse a report from pytest that contains no test cases.""" xml = ''' <?xml version="1.0" encoding="utf-8"?> <testsuites> <testsuite errors="0" failures="0" hostname="hyperion" name="pytest" skipped="0" tests="0" time="0.569" timestamp="2020-08-14T01:10:52.311169"/> </testsuites> '''.lstrip() report = parseReport(lambda: StringIO(xml), 'report.xml') assert report is not None assert report.errors == 0 assert report.failures == 0 assert report.skipped == 0 assert report.numTestcases == 0 assert report.result is ResultCode.CANCELLED assert report.summary == 'no test cases found' data = report.data assert data['testcases'] == '0' assert data['checks'] == '0' assert data['failures'] == '0' assert data['errors'] == '0' assert data['skipped'] == '0' assert len(report.testsuite) == 1 suite, = report.testsuite assert suite.tests == 0 assert suite.failures == 0 assert suite.errors == 0 assert suite.skipped == 0 assert suite.time == 0.569 assert suite.result is ResultCode.CANCELLED assert not suite.testcase