785f6e1682c8614e493a38f5855c22c8fd4c54dd
[functest-xtesting.git] / xtesting / tests / unit / core / test_feature.py
1 #!/usr/bin/env python
2
3 # Copyright (c) 2017 Orange and others.
4 #
5 # All rights reserved. This program and the accompanying materials
6 # are made available under the terms of the Apache License, Version 2.0
7 # which accompanies this distribution, and is available at
8 # http://www.apache.org/licenses/LICENSE-2.0
9
10 # pylint: disable=missing-docstring
11
12 import logging
13 import subprocess
14 import unittest
15
16 import mock
17 import six
18
19 from xtesting.core import feature
20 from xtesting.core import testcase
21
22
23 class FakeTestCase(feature.Feature):
24
25     def execute(self, **kwargs):
26         pass
27
28
29 class AbstractFeatureTesting(unittest.TestCase):
30
31     def test_run_unimplemented(self):
32         # pylint: disable=abstract-class-instantiated
33         with self.assertRaises(TypeError):
34             feature.Feature(case_name="feature", project_name="xtesting")
35
36
37 class FeatureTestingBase(unittest.TestCase):
38
39     _case_name = "foo"
40     _project_name = "bar"
41     _repo = "dir_repo_bar"
42     _cmd = "run_bar_tests.py"
43     _output_file = '/var/lib/xtesting/results/foo/foo.log'
44     feature = None
45
46     @mock.patch('time.time', side_effect=[1, 2])
47     def _test_run(self, status, mock_method=None):
48         self.assertEqual(self.feature.run(cmd=self._cmd), status)
49         if status == testcase.TestCase.EX_OK:
50             self.assertEqual(self.feature.result, 100)
51         else:
52             self.assertEqual(self.feature.result, 0)
53         mock_method.assert_has_calls([mock.call(), mock.call()])
54         self.assertEqual(self.feature.start_time, 1)
55         self.assertEqual(self.feature.stop_time, 2)
56
57     @mock.patch('time.time', side_effect=[1, 2])
58     def _test_run_console(self, console, status, mock_method=None):
59         self.assertEqual(
60             self.feature.run(cmd=self._cmd, console=console), status)
61         self.assertEqual(self.feature.result, 100)
62         mock_method.assert_has_calls([mock.call(), mock.call()])
63         self.assertEqual(self.feature.start_time, 1)
64         self.assertEqual(self.feature.stop_time, 2)
65
66
67 class FeatureTesting(FeatureTestingBase):
68
69     def setUp(self):
70         # logging must be disabled else it calls time.time()
71         # what will break these unit tests.
72         logging.disable(logging.CRITICAL)
73         with mock.patch('six.moves.builtins.open'):
74             self.feature = FakeTestCase(
75                 project_name=self._project_name, case_name=self._case_name)
76
77     def test_run_exc(self):
78         # pylint: disable=bad-continuation
79         with mock.patch.object(
80                 self.feature, 'execute',
81                 side_effect=Exception) as mock_method:
82             self._test_run(testcase.TestCase.EX_RUN_ERROR)
83             mock_method.assert_called_once_with(cmd=self._cmd)
84
85     def test_run(self):
86         self._test_run(testcase.TestCase.EX_RUN_ERROR)
87
88
89 class BashFeatureTesting(FeatureTestingBase):
90
91     def setUp(self):
92         # logging must be disabled else it calls time.time()
93         # what will break these unit tests.
94         logging.disable(logging.CRITICAL)
95         with mock.patch('six.moves.builtins.open'):
96             self.feature = feature.BashFeature(
97                 project_name=self._project_name, case_name=self._case_name)
98
99     @mock.patch('subprocess.Popen')
100     def test_run_no_cmd(self, mock_subproc):
101         self.assertEqual(
102             self.feature.run(), testcase.TestCase.EX_RUN_ERROR)
103         mock_subproc.assert_not_called()
104
105     @mock.patch('os.path.isdir', return_value=True)
106     @mock.patch('subprocess.Popen',
107                 side_effect=subprocess.CalledProcessError(0, '', ''))
108     def test_run_ko1(self, *args):
109         with mock.patch('six.moves.builtins.open', mock.mock_open()) as mopen:
110             self._test_run(testcase.TestCase.EX_RUN_ERROR)
111         mopen.assert_called_once_with(self._output_file, "w")
112         args[0].assert_called_once_with(
113             self._cmd, shell=True, stderr=mock.ANY, stdout=mock.ANY)
114         args[1].assert_called_once_with(self.feature.res_dir)
115
116     @mock.patch('os.path.isdir', return_value=True)
117     @mock.patch('subprocess.Popen')
118     def test_run_ko2(self, *args):
119         stream = six.BytesIO()
120         stream.write(b"foo")
121         stream.seek(0)
122         attrs = {'return_value.stdout': stream, 'return_value.returncode': 1}
123         args[0].configure_mock(**attrs)
124         with mock.patch('six.moves.builtins.open', mock.mock_open()) as mopen:
125             self._test_run(testcase.TestCase.EX_RUN_ERROR)
126         self.assertIn(mock.call(self._output_file, 'w'), mopen.mock_calls)
127         self.assertIn(mock.call(self._output_file, 'r'), mopen.mock_calls)
128         args[0].assert_called_once_with(
129             self._cmd, shell=True, stderr=mock.ANY, stdout=mock.ANY)
130         args[1].assert_called_once_with(self.feature.res_dir)
131
132     @mock.patch('os.path.isdir', return_value=True)
133     @mock.patch('subprocess.Popen')
134     def test_run1(self, *args):
135         stream = six.BytesIO()
136         stream.write(b"foo")
137         stream.seek(0)
138         attrs = {'return_value.stdout': stream, 'return_value.returncode': 0}
139         args[0].configure_mock(**attrs)
140         with mock.patch('six.moves.builtins.open', mock.mock_open()) as mopen:
141             self._test_run(testcase.TestCase.EX_OK)
142         self.assertIn(mock.call(self._output_file, 'w'), mopen.mock_calls)
143         self.assertIn(mock.call(self._output_file, 'r'), mopen.mock_calls)
144         args[0].assert_called_once_with(
145             self._cmd, shell=True, stderr=mock.ANY, stdout=mock.ANY)
146         args[1].assert_called_once_with(self.feature.res_dir)
147
148     @mock.patch('os.path.isdir', return_value=True)
149     @mock.patch('subprocess.Popen')
150     def test_run2(self, *args):
151         stream = six.BytesIO()
152         stream.write(b"foo")
153         stream.seek(0)
154         attrs = {'return_value.stdout': stream, 'return_value.returncode': 0}
155         args[0].configure_mock(**attrs)
156         with mock.patch('six.moves.builtins.open', mock.mock_open()) as mopen:
157             self._test_run_console(True, testcase.TestCase.EX_OK)
158         self.assertIn(mock.call(self._output_file, 'w'), mopen.mock_calls)
159         self.assertIn(mock.call(self._output_file, 'r'), mopen.mock_calls)
160         args[0].assert_called_once_with(
161             self._cmd, shell=True, stderr=mock.ANY, stdout=mock.ANY)
162         args[1].assert_called_once_with(self.feature.res_dir)
163
164     @mock.patch('os.path.isdir', return_value=True)
165     @mock.patch('subprocess.Popen')
166     def test_run3(self, *args):
167         stream = six.BytesIO()
168         stream.write(b"foo")
169         stream.seek(0)
170         attrs = {'return_value.stdout': stream, 'return_value.returncode': 0}
171         args[0].configure_mock(**attrs)
172         with mock.patch('six.moves.builtins.open', mock.mock_open()) as mopen:
173             self._test_run_console(False, testcase.TestCase.EX_OK)
174         self.assertIn(mock.call(self._output_file, 'w'), mopen.mock_calls)
175         self.assertIn(mock.call(self._output_file, 'r'), mopen.mock_calls)
176         args[0].assert_called_once_with(
177             self._cmd, shell=True, stderr=mock.ANY, stdout=mock.ANY)
178         args[1].assert_called_once_with(self.feature.res_dir)
179
180     @mock.patch('os.makedirs')
181     @mock.patch('os.path.isdir', return_value=False)
182     @mock.patch('subprocess.Popen')
183     def test_run4(self, *args):
184         stream = six.BytesIO()
185         stream.write(b"foo")
186         stream.seek(0)
187         attrs = {'return_value.stdout': stream, 'return_value.returncode': 0}
188         args[0].configure_mock(**attrs)
189         with mock.patch('six.moves.builtins.open', mock.mock_open()) as mopen:
190             self._test_run_console(False, testcase.TestCase.EX_OK)
191         self.assertIn(mock.call(self._output_file, 'w'), mopen.mock_calls)
192         self.assertIn(mock.call(self._output_file, 'r'), mopen.mock_calls)
193         args[0].assert_called_once_with(
194             self._cmd, shell=True, stderr=mock.ANY, stdout=mock.ANY)
195         args[1].assert_called_once_with(self.feature.res_dir)
196         args[2].assert_called_once_with(self.feature.res_dir)
197
198
199 if __name__ == "__main__":
200     unittest.main(verbosity=2)