From f42e4276414e492afde19deb368c1e77d4dffbeb Mon Sep 17 00:00:00 2001 From: Cédric Ollivier Date: Tue, 7 Aug 2018 07:16:57 +0200 Subject: Generate robot reports MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: Ib9efe14bce6227f9609200c12ded4470bd0be969 Signed-off-by: Cédric Ollivier (cherry picked from commit b7f4eaa213b65a266f527d9def7679eac7e0353b) --- xtesting/core/robotframework.py | 15 +++- xtesting/tests/unit/core/test_robotframework.py | 104 +++++++++++++++++++++++- 2 files changed, 113 insertions(+), 6 deletions(-) diff --git a/xtesting/core/robotframework.py b/xtesting/core/robotframework.py index 007b9629..4cba7bbb 100644 --- a/xtesting/core/robotframework.py +++ b/xtesting/core/robotframework.py @@ -17,6 +17,7 @@ import os import robot.api from robot.errors import RobotError +from robot.reporting import resultwriter import robot.run from robot.utils.robottime import timestamp_to_secs from six import StringIO @@ -77,6 +78,15 @@ class RobotFramework(testcase.TestCase): self.details['description'] = result.suite.name self.details['tests'] = visitor.get_data() + def generate_report(self): + """Generate html and xunit outputs""" + result = robot.api.ExecutionResult(self.xml_file) + writer = resultwriter.ResultWriter(result) + return writer.write_results( + report='{}/report.html'.format(self.res_dir), + log='{}/log.html'.format(self.res_dir), + xunit='{}/xunit.xml'.format(self.res_dir)) + def run(self, **kwargs): """Run the RobotFramework suites @@ -113,11 +123,12 @@ class RobotFramework(testcase.TestCase): robot.run(*suites, variable=variable, variablefile=variablefile, include=include, output=self.xml_file, log='NONE', report='NONE', stdout=stream) - self.__logger.info("\n" + stream.getvalue()) - self.__logger.info("Results were successfully generated") + self.__logger.info("\n%s", stream.getvalue()) try: self.parse_results() self.__logger.info("Results were successfully parsed") + assert self.generate_report() == 0 + self.__logger.info("Results were successfully generated") except RobotError as ex: self.__logger.error("Run suites before publishing: %s", ex.message) return self.EX_RUN_ERROR diff --git a/xtesting/tests/unit/core/test_robotframework.py b/xtesting/tests/unit/core/test_robotframework.py index e01ada21..4cda171c 100644 --- a/xtesting/tests/unit/core/test_robotframework.py +++ b/xtesting/tests/unit/core/test_robotframework.py @@ -110,6 +110,59 @@ class ParseResultTesting(unittest.TestCase): self._test_result(self._config, 100) +class GenerateReportTesting(unittest.TestCase): + + """The class testing RobotFramework.generate_report().""" + # pylint: disable=missing-docstring + + def setUp(self): + self.test = robotframework.RobotFramework( + case_name='robot', project_name='xtesting') + + @mock.patch('robot.api.ExecutionResult', side_effect=Exception) + def test_exc1(self, *args): + with self.assertRaises(Exception): + self.test.generate_report() + args[0].assert_called_once_with(self.test.xml_file) + + @mock.patch('robot.reporting.resultwriter.ResultWriter.__init__', + return_value=mock.Mock(side_effect=Exception)) + @mock.patch('robot.api.ExecutionResult') + def test_exc2(self, *args): # pylint: disable=unused-argument + with self.assertRaises(Exception): + self.test.generate_report() + args[0].assert_called_once_with(self.test.xml_file) + args[1].assert_called_once_with(args[0].return_value) + + @mock.patch('robot.reporting.resultwriter.ResultWriter.write_results', + return_value=1) + @mock.patch('robot.reporting.resultwriter.ResultWriter.__init__', + return_value=None) + @mock.patch('robot.api.ExecutionResult') + def test_err(self, *args): + self.assertEqual(self.test.generate_report(), 1) + args[0].assert_called_once_with(self.test.xml_file) + args[1].assert_called_once_with(args[0].return_value) + args[2].assert_called_once_with( + report='{}/report.html'.format(self.test.res_dir), + log='{}/log.html'.format(self.test.res_dir), + xunit='{}/xunit.xml'.format(self.test.res_dir)) + + @mock.patch('robot.reporting.resultwriter.ResultWriter.write_results', + return_value=0) + @mock.patch('robot.reporting.resultwriter.ResultWriter.__init__', + return_value=None) + @mock.patch('robot.api.ExecutionResult') + def test_ok(self, *args): # pylint: disable=unused-argument + self.assertEqual(self.test.generate_report(), 0) + args[0].assert_called_once_with(self.test.xml_file) + args[1].assert_called_once_with(args[0].return_value) + args[2].assert_called_once_with( + report='{}/report.html'.format(self.test.res_dir), + log='{}/log.html'.format(self.test.res_dir), + xunit='{}/xunit.xml'.format(self.test.res_dir)) + + class RunTesting(unittest.TestCase): """The class testing RobotFramework.run().""" @@ -129,7 +182,8 @@ class RunTesting(unittest.TestCase): @mock.patch('robot.run') def _test_makedirs_exc(self, *args): - with mock.patch.object(self.test, 'parse_results') as mock_method: + with mock.patch.object(self.test, 'parse_results') as mock_method, \ + mock.patch.object(self.test, 'generate_report') as mmethod: self.assertEqual( self.test.run( suites=self.suites, variable=self.variable, @@ -137,6 +191,7 @@ class RunTesting(unittest.TestCase): self.test.EX_RUN_ERROR) args[0].assert_not_called() mock_method.asser_not_called() + mmethod.asser_not_called() @mock.patch('os.makedirs', side_effect=Exception) def test_makedirs_exc(self, *args): @@ -150,7 +205,9 @@ class RunTesting(unittest.TestCase): @mock.patch('robot.run') def _test_makedirs(self, *args): - with mock.patch.object(self.test, 'parse_results') as mock_method: + with mock.patch.object(self.test, 'parse_results') as mock_method, \ + mock.patch.object(self.test, 'generate_report', + return_value=0) as mmethod: self.assertEqual( self.test.run(suites=self.suites, variable=self.variable), self.test.EX_OK) @@ -159,6 +216,7 @@ class RunTesting(unittest.TestCase): report='NONE', stdout=mock.ANY, variable=self.variable, variablefile=self.variablefile, include=self.include) mock_method.assert_called_once_with() + mmethod.assert_called_once_with() @mock.patch('os.makedirs', side_effect=OSError(errno.EEXIST, '')) def test_makedirs_oserror17(self, *args): @@ -186,15 +244,53 @@ class RunTesting(unittest.TestCase): def test_parse_results_exc(self): with mock.patch.object(self.test, 'parse_results', - side_effect=Exception) as mock_method: + side_effect=Exception) as mock_method, \ + mock.patch.object(self.test, 'generate_report') as mmethod: self._test_parse_results(self.test.EX_RUN_ERROR) mock_method.assert_called_once_with() + mmethod.asser_not_called() def test_parse_results_robot_error(self): with mock.patch.object(self.test, 'parse_results', - side_effect=RobotError('foo')) as mock_method: + side_effect=RobotError('foo')) as mock_method, \ + mock.patch.object(self.test, 'generate_report') as mmethod: self._test_parse_results(self.test.EX_RUN_ERROR) mock_method.assert_called_once_with() + mmethod.asser_not_called() + + @mock.patch('os.makedirs') + @mock.patch('robot.run') + def _test_generate_report(self, status, *args): + with mock.patch.object(self.test, 'parse_results') as mock_method: + self.assertEqual( + self.test.run( + suites=self.suites, variable=self.variable, + variablefile=self.variablefile, include=self.include), + status) + args[0].assert_called_once_with( + *self.suites, log='NONE', output=self.test.xml_file, + report='NONE', stdout=mock.ANY, variable=self.variable, + variablefile=self.variablefile, include=self.include) + args[1].assert_called_once_with(self.test.res_dir) + mock_method.assert_called_once_with() + + def test_generate_report_exc(self): + with mock.patch.object(self.test, 'generate_report', + side_effect=Exception) as mmethod: + self._test_generate_report(self.test.EX_RUN_ERROR) + mmethod.assert_called_once_with() + + def test_generate_report_err(self): + with mock.patch.object(self.test, 'generate_report', + return_value=1) as mmethod: + self._test_generate_report(self.test.EX_RUN_ERROR) + mmethod.assert_called_once_with() + + def test_generate_report(self): + with mock.patch.object(self.test, 'generate_report', + return_value=0) as mmethod: + self._test_generate_report(self.test.EX_OK) + mmethod.assert_called_once_with() if __name__ == "__main__": -- cgit 1.2.3-korg