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