1# Copyright 2017 Google Inc. 2# 3# Licensed under the Apache License, Version 2.0 (the "License"); 4# you may not use this file except in compliance with the License. 5# You may obtain a copy of the License at 6# 7# http://www.apache.org/licenses/LICENSE-2.0 8# 9# Unless required by applicable law or agreed to in writing, software 10# distributed under the License is distributed on an "AS IS" BASIS, 11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12# See the License for the specific language governing permissions and 13# limitations under the License. 14 15import io 16import os 17import shutil 18import sys 19import tempfile 20import unittest 21from unittest import mock 22 23from mobly import base_suite 24from mobly import base_test 25from mobly import suite_runner 26from tests.lib import integration2_test 27from tests.lib import integration_test 28 29 30class FakeTest1(base_test.BaseTestClass): 31 pass 32 33 34class SuiteRunnerTest(unittest.TestCase): 35 36 def setUp(self): 37 self.tmp_dir = tempfile.mkdtemp() 38 39 def tearDown(self): 40 shutil.rmtree(self.tmp_dir) 41 42 def test_select_no_args(self): 43 identifiers = suite_runner.compute_selected_tests( 44 test_classes=[ 45 integration_test.IntegrationTest, 46 integration2_test.Integration2Test, 47 ], 48 selected_tests=None, 49 ) 50 self.assertEqual( 51 { 52 integration_test.IntegrationTest: None, 53 integration2_test.Integration2Test: None, 54 }, 55 identifiers, 56 ) 57 58 def test_select_by_class(self): 59 identifiers = suite_runner.compute_selected_tests( 60 test_classes=[ 61 integration_test.IntegrationTest, 62 integration2_test.Integration2Test, 63 ], 64 selected_tests=['IntegrationTest'], 65 ) 66 self.assertEqual({integration_test.IntegrationTest: None}, identifiers) 67 68 def test_select_by_method(self): 69 identifiers = suite_runner.compute_selected_tests( 70 test_classes=[ 71 integration_test.IntegrationTest, 72 integration2_test.Integration2Test, 73 ], 74 selected_tests=['IntegrationTest.test_a', 'IntegrationTest.test_b'], 75 ) 76 self.assertEqual( 77 {integration_test.IntegrationTest: ['test_a', 'test_b']}, identifiers 78 ) 79 80 def test_select_all_clobbers_method(self): 81 identifiers = suite_runner.compute_selected_tests( 82 test_classes=[ 83 integration_test.IntegrationTest, 84 integration2_test.Integration2Test, 85 ], 86 selected_tests=['IntegrationTest.test_a', 'IntegrationTest'], 87 ) 88 self.assertEqual({integration_test.IntegrationTest: None}, identifiers) 89 90 identifiers = suite_runner.compute_selected_tests( 91 test_classes=[ 92 integration_test.IntegrationTest, 93 integration2_test.Integration2Test, 94 ], 95 selected_tests=['IntegrationTest', 'IntegrationTest.test_a'], 96 ) 97 self.assertEqual({integration_test.IntegrationTest: None}, identifiers) 98 99 @mock.patch('sys.exit') 100 def test_run_suite(self, mock_exit): 101 tmp_file_path = os.path.join(self.tmp_dir, 'config.yml') 102 with io.open(tmp_file_path, 'w', encoding='utf-8') as f: 103 f.write(""" 104 TestBeds: 105 # A test bed where adb will find Android devices. 106 - Name: SampleTestBed 107 Controllers: 108 MagicDevice: '*' 109 TestParams: 110 icecream: 42 111 extra_param: 'haha' 112 """) 113 suite_runner.run_suite( 114 [integration_test.IntegrationTest], argv=['-c', tmp_file_path] 115 ) 116 mock_exit.assert_not_called() 117 118 @mock.patch('sys.exit') 119 def test_run_suite_with_failures(self, mock_exit): 120 tmp_file_path = os.path.join(self.tmp_dir, 'config.yml') 121 with io.open(tmp_file_path, 'w', encoding='utf-8') as f: 122 f.write(""" 123 TestBeds: 124 # A test bed where adb will find Android devices. 125 - Name: SampleTestBed 126 Controllers: 127 MagicDevice: '*' 128 """) 129 suite_runner.run_suite( 130 [integration_test.IntegrationTest], argv=['-c', tmp_file_path] 131 ) 132 mock_exit.assert_called_once_with(1) 133 134 @mock.patch('sys.exit') 135 @mock.patch.object(suite_runner, '_find_suite_class', autospec=True) 136 def test_run_suite_class(self, mock_find_suite_class, mock_exit): 137 mock_called = mock.MagicMock() 138 139 class FakeTestSuite(base_suite.BaseSuite): 140 141 def setup_suite(self, config): 142 mock_called.setup_suite() 143 super().setup_suite(config) 144 self.add_test_class(FakeTest1) 145 146 def teardown_suite(self): 147 mock_called.teardown_suite() 148 super().teardown_suite() 149 150 mock_find_suite_class.return_value = FakeTestSuite 151 152 tmp_file_path = os.path.join(self.tmp_dir, 'config.yml') 153 with io.open(tmp_file_path, 'w', encoding='utf-8') as f: 154 f.write(""" 155 TestBeds: 156 # A test bed where adb will find Android devices. 157 - Name: SampleTestBed 158 Controllers: 159 MagicDevice: '*' 160 """) 161 162 mock_cli_args = ['test_binary', f'--config={tmp_file_path}'] 163 164 with mock.patch.object(sys, 'argv', new=mock_cli_args): 165 suite_runner.run_suite_class() 166 167 mock_find_suite_class.assert_called_once() 168 mock_called.setup_suite.assert_called_once_with() 169 mock_called.teardown_suite.assert_called_once_with() 170 mock_exit.assert_not_called() 171 172 def test_print_test_names(self): 173 mock_test_class = mock.MagicMock() 174 mock_cls_instance = mock.MagicMock() 175 mock_test_class.return_value = mock_cls_instance 176 suite_runner._print_test_names([mock_test_class]) 177 mock_cls_instance._pre_run.assert_called_once() 178 mock_cls_instance._clean_up.assert_called_once() 179 180 def test_print_test_names_with_exception(self): 181 mock_test_class = mock.MagicMock() 182 mock_cls_instance = mock.MagicMock() 183 mock_test_class.return_value = mock_cls_instance 184 suite_runner._print_test_names([mock_test_class]) 185 mock_cls_instance._pre_run.side_effect = Exception('Something went wrong.') 186 mock_cls_instance._clean_up.assert_called_once() 187 188 189if __name__ == '__main__': 190 unittest.main() 191