Generate Html and Xunit Behave reports 10/71910/1
authorCédric Ollivier <cedric.ollivier@orange.com>
Sat, 9 Nov 2019 11:28:24 +0000 (12:28 +0100)
committerCédric Ollivier <cedric.ollivier@orange.com>
Tue, 9 Feb 2021 18:22:35 +0000 (19:22 +0100)
Change-Id: I7d5f31502ba61b61a0b1c885fe8828211bc0bc0a
Signed-off-by: Cédric Ollivier <cedric.ollivier@orange.com>
(cherry picked from commit 728f5c95df4d3edbe6b3f814a270cdf3b532aef9)

requirements.txt
upper-constraints.txt
xtesting/core/behaveframework.py
xtesting/tests/unit/core/test_behaveframework.py

index 5ea7116..ea776ba 100644 (file)
@@ -8,6 +8,7 @@ enum34;python_version=='2.7' or python_version=='2.6' or python_version=='3.3' #
 requests!=2.20.0 # Apache-2.0
 robotframework>=3.0
 behave>=1.2.6
+behave-html-formatter>=0.9.4;python_version>='3.5'
 mock # BSD
 PrettyTable<0.8 # BSD
 six # MIT
index b7c0086..1867de9 100644 (file)
@@ -1,5 +1,7 @@
 robotframework===3.0.2
 bandit===1.1.0
+behave===1.2.6
+behave-html-formatter===0.9.4;python_version>='3.5'
 pylint===1.9.5;python_version=='2.7'
 pylint===2.3.1;python_version=='3.6'
 boto3===1.7.62
index d8a61ef..2b41614 100644 (file)
@@ -14,7 +14,9 @@ from __future__ import division
 import logging
 import os
 import time
+
 import json
+import six
 
 from behave.__main__ import main as behave_main
 
@@ -32,7 +34,6 @@ class BehaveFramework(testcase.TestCase):
 
     def __init__(self, **kwargs):
         super(BehaveFramework, self).__init__(**kwargs)
-        self.res_dir = os.path.join(self.dir_results, self.case_name)
         self.json_file = os.path.join(self.res_dir, 'output.json')
         self.total_tests = 0
         self.pass_tests = 0
@@ -42,14 +43,8 @@ class BehaveFramework(testcase.TestCase):
 
     def parse_results(self):
         """Parse output.json and get the details in it."""
-
-        try:
-            with open(self.json_file) as stream_:
-                self.response = json.load(stream_)
-        except IOError:
-            self.__logger.error("Error reading the file %s", self.json_file)
-
-        try:
+        with open(self.json_file) as stream_:
+            self.response = json.load(stream_)
             if self.response:
                 self.total_tests = len(self.response)
             for item in self.response:
@@ -59,21 +54,14 @@ class BehaveFramework(testcase.TestCase):
                     self.fail_tests += 1
                 elif item['status'] == 'skipped':
                     self.skip_tests += 1
-        except KeyError:
-            self.__logger.error("Error in json - %s", self.response)
-
-        try:
             self.result = 100 * (
                 self.pass_tests / self.total_tests)
-        except ZeroDivisionError:
-            self.__logger.error("No test has been run")
-
-        self.details = {}
-        self.details['total_tests'] = self.total_tests
-        self.details['pass_tests'] = self.pass_tests
-        self.details['fail_tests'] = self.fail_tests
-        self.details['skip_tests'] = self.skip_tests
-        self.details['tests'] = self.response
+            self.details = {}
+            self.details['total_tests'] = self.total_tests
+            self.details['pass_tests'] = self.pass_tests
+            self.details['fail_tests'] = self.fail_tests
+            self.details['skip_tests'] = self.skip_tests
+            self.details['tests'] = self.response
 
     def run(self, **kwargs):
         """Run the BehaveFramework feature files
@@ -103,8 +91,12 @@ class BehaveFramework(testcase.TestCase):
                 self.__logger.exception("Cannot create %s", self.res_dir)
                 return self.EX_RUN_ERROR
         config = ['--tags='+','.join(tags),
-                  '--format=json',
-                  '--outfile='+self.json_file]
+                  '--junit', '--junit-directory={}'.format(self.res_dir),
+                  '--format=json', '--outfile={}'.format(self.json_file)]
+        if six.PY3:
+            html_file = os.path.join(self.res_dir, 'output.html')
+            config += ['--format=behave_html_formatter:HTMLFormatter',
+                       '--outfile={}'.format(html_file)]
         for feature in suites:
             config.append(feature)
         self.start_time = time.time()
index f18cac0..414d96b 100644 (file)
 """Define the classes required to fully cover behave."""
 
 import logging
+import os
 import unittest
 
 import mock
+import six
+
 from xtesting.core import behaveframework
 
 __author__ = "Deepak Chandella <deepak.chandella@orange.com>"
@@ -29,28 +32,27 @@ class ParseResultTesting(unittest.TestCase):
         self.test = behaveframework.BehaveFramework(
             case_name='behave', project_name='xtesting')
 
-    def test_raises_exc_open(self):
-        self.test.json_file = 'dummy_file'
-        self.test.response = self._response
-        with mock.patch('six.moves.builtins.open',
-                        mock.mock_open()) as mock_file:
-            mock_file.side_effect = IOError()
-            self.assertRaises(IOError, self.test.parse_results())
-        mock_file.assert_called_once_with('dummy_file')
+    @mock.patch('six.moves.builtins.open', side_effect=OSError)
+    def test_raises_exc_open(self, *args):  # pylint: disable=unused-argument
+        with self.assertRaises(OSError):
+            self.test.parse_results()
 
-    def test_raises_exc_key(self):
-        with mock.patch('six.moves.builtins.open', mock.mock_open()), \
-                mock.patch('json.load', return_value=[{'foo': 'bar'}]):
-            self.assertRaises(KeyError, self.test.parse_results())
+    @mock.patch('json.load', return_value=[{'foo': 'bar'}])
+    @mock.patch('six.moves.builtins.open', mock.mock_open())
+    def test_raises_exc_key(self, *args):  # pylint: disable=unused-argument
+        with self.assertRaises(KeyError):
+            self.test.parse_results()
 
-    def test_raises_exe_zerodivision(self):
-        with mock.patch('six.moves.builtins.open', mock.mock_open()), \
-                mock.patch('json.load', mock.Mock(return_value=[])):
-            self.assertRaises(ZeroDivisionError, self.test.parse_results())
+    @mock.patch('json.load', return_value=[])
+    @mock.patch('six.moves.builtins.open', mock.mock_open())
+    def test_raises_exe_zerodivision(self, *args):
+        # pylint: disable=unused-argument
+        with self.assertRaises(ZeroDivisionError):
+            self.test.parse_results()
 
     def _test_result(self, response, result):
         with mock.patch('six.moves.builtins.open', mock.mock_open()), \
-                mock.patch('json.load', mock.Mock(return_value=response)):
+                mock.patch('json.load', return_value=response):
             self.test.parse_results()
             self.assertEqual(self.test.result, result)
 
@@ -66,11 +68,10 @@ class ParseResultTesting(unittest.TestCase):
         data = [{'status': 'passed'}, {'status': 'passed'}]
         self._test_result(data, 100)
 
-    def test_count(self):
+    @mock.patch('six.moves.builtins.open', mock.mock_open())
+    def test_count(self, *args):  # pylint: disable=unused-argument
         self._response.extend([{'status': 'failed'}, {'status': 'skipped'}])
-        with mock.patch('six.moves.builtins.open', mock.mock_open()), \
-                mock.patch('json.load', mock.Mock(
-                    return_value=self._response)):
+        with mock.patch('json.load', mock.Mock(return_value=self._response)):
             self.test.parse_results()
             self.assertEqual(self.test.details['pass_tests'], 1)
             self.assertEqual(self.test.details['fail_tests'], 1)
@@ -116,11 +117,17 @@ class RunTesting(unittest.TestCase):
             self.assertEqual(
                 self.test.run(suites=self.suites, tags=self.tags),
                 self.test.EX_OK)
-            args[0].assert_called_once_with(
-                ['--tags=',
-                 '--format=json',
-                 '--outfile={}'.format(self.test.json_file),
-                 'foo'])
+            html_file = os.path.join(self.test.res_dir, 'output.html')
+            args_list = [
+                '--tags=', '--junit',
+                '--junit-directory={}'.format(self.test.res_dir),
+                '--format=json', '--outfile={}'.format(self.test.json_file)]
+            if six.PY3:
+                args_list += [
+                    '--format=behave_html_formatter:HTMLFormatter',
+                    '--outfile={}'.format(html_file)]
+            args_list.append('foo')
+            args[0].assert_called_once_with(args_list)
             mock_method.assert_called_once_with()
 
     @mock.patch('os.makedirs')
@@ -144,11 +151,17 @@ class RunTesting(unittest.TestCase):
             self.test.run(
                 suites=self.suites, tags=self.tags),
             status)
-        args[0].assert_called_once_with(
-            ['--tags=',
-             '--format=json',
-             '--outfile={}'.format(self.test.json_file),
-             'foo'])
+        html_file = os.path.join(self.test.res_dir, 'output.html')
+        args_list = [
+            '--tags=', '--junit',
+            '--junit-directory={}'.format(self.test.res_dir),
+            '--format=json', '--outfile={}'.format(self.test.json_file)]
+        if six.PY3:
+            args_list += [
+                '--format=behave_html_formatter:HTMLFormatter',
+                '--outfile={}'.format(html_file)]
+        args_list.append('foo')
+        args[0].assert_called_once_with(args_list)
         args[1].assert_called_once_with(self.test.res_dir)
 
     def test_parse_results_exc(self):
@@ -157,6 +170,7 @@ class RunTesting(unittest.TestCase):
             self._test_parse_results(self.test.EX_RUN_ERROR)
             mock_method.assert_called_once_with()
 
+
 if __name__ == "__main__":
     logging.disable(logging.CRITICAL)
     unittest.main(verbosity=2)