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 inspect 16import io 17import os 18import shutil 19import sys 20import tempfile 21import unittest 22from unittest import mock 23 24from mobly import base_suite 25from mobly import base_test 26from mobly import config_parser 27from mobly import test_runner 28from mobly import suite_runner 29from tests.lib import integration2_test 30from tests.lib import integration_test 31 32 33class FakeTest1(base_test.BaseTestClass): 34 pass 35 36 37class SuiteRunnerTest(unittest.TestCase): 38 39 def setUp(self): 40 self.tmp_dir = tempfile.mkdtemp() 41 42 def tearDown(self): 43 shutil.rmtree(self.tmp_dir) 44 45 def test_select_no_args(self): 46 identifiers = suite_runner.compute_selected_tests(test_classes=[ 47 integration_test.IntegrationTest, integration2_test.Integration2Test 48 ], 49 selected_tests=None) 50 self.assertEqual( 51 { 52 integration_test.IntegrationTest: None, 53 integration2_test.Integration2Test: None, 54 }, identifiers) 55 56 def test_select_by_class(self): 57 identifiers = suite_runner.compute_selected_tests( 58 test_classes=[ 59 integration_test.IntegrationTest, integration2_test.Integration2Test 60 ], 61 selected_tests=['IntegrationTest']) 62 self.assertEqual({integration_test.IntegrationTest: None}, identifiers) 63 64 def test_select_by_method(self): 65 identifiers = suite_runner.compute_selected_tests( 66 test_classes=[ 67 integration_test.IntegrationTest, integration2_test.Integration2Test 68 ], 69 selected_tests=['IntegrationTest.test_a', 'IntegrationTest.test_b']) 70 self.assertEqual({integration_test.IntegrationTest: ['test_a', 'test_b']}, 71 identifiers) 72 73 def test_select_all_clobbers_method(self): 74 identifiers = suite_runner.compute_selected_tests( 75 test_classes=[ 76 integration_test.IntegrationTest, integration2_test.Integration2Test 77 ], 78 selected_tests=['IntegrationTest.test_a', 'IntegrationTest']) 79 self.assertEqual({integration_test.IntegrationTest: None}, identifiers) 80 81 identifiers = suite_runner.compute_selected_tests( 82 test_classes=[ 83 integration_test.IntegrationTest, integration2_test.Integration2Test 84 ], 85 selected_tests=['IntegrationTest', 'IntegrationTest.test_a']) 86 self.assertEqual({integration_test.IntegrationTest: None}, identifiers) 87 88 @mock.patch('sys.exit') 89 def test_run_suite(self, mock_exit): 90 tmp_file_path = os.path.join(self.tmp_dir, 'config.yml') 91 with io.open(tmp_file_path, 'w', encoding='utf-8') as f: 92 f.write(u""" 93 TestBeds: 94 # A test bed where adb will find Android devices. 95 - Name: SampleTestBed 96 Controllers: 97 MagicDevice: '*' 98 TestParams: 99 icecream: 42 100 extra_param: 'haha' 101 """) 102 suite_runner.run_suite([integration_test.IntegrationTest], 103 argv=['-c', tmp_file_path]) 104 mock_exit.assert_not_called() 105 106 @mock.patch('sys.exit') 107 def test_run_suite_with_failures(self, mock_exit): 108 tmp_file_path = os.path.join(self.tmp_dir, 'config.yml') 109 with io.open(tmp_file_path, 'w', encoding='utf-8') as f: 110 f.write(u""" 111 TestBeds: 112 # A test bed where adb will find Android devices. 113 - Name: SampleTestBed 114 Controllers: 115 MagicDevice: '*' 116 """) 117 suite_runner.run_suite([integration_test.IntegrationTest], 118 argv=['-c', tmp_file_path]) 119 mock_exit.assert_called_once_with(1) 120 121 @mock.patch('sys.exit') 122 @mock.patch.object(suite_runner, '_find_suite_class', autospec=True) 123 def test_run_suite_class(self, mock_find_suite_class, mock_exit): 124 mock_called = mock.MagicMock() 125 126 class FakeTestSuite(base_suite.BaseSuite): 127 128 def setup_suite(self, config): 129 mock_called.setup_suite() 130 super().setup_suite(config) 131 self.add_test_class(FakeTest1) 132 133 def teardown_suite(self): 134 mock_called.teardown_suite() 135 super().teardown_suite() 136 137 mock_find_suite_class.return_value = FakeTestSuite 138 139 tmp_file_path = os.path.join(self.tmp_dir, 'config.yml') 140 with io.open(tmp_file_path, 'w', encoding='utf-8') as f: 141 f.write(u""" 142 TestBeds: 143 # A test bed where adb will find Android devices. 144 - Name: SampleTestBed 145 Controllers: 146 MagicDevice: '*' 147 """) 148 149 mock_cli_args = ['test_binary', f'--config={tmp_file_path}'] 150 151 with mock.patch.object(sys, 'argv', new=mock_cli_args): 152 suite_runner.run_suite_class() 153 154 mock_find_suite_class.assert_called_once() 155 mock_called.setup_suite.assert_called_once_with() 156 mock_called.teardown_suite.assert_called_once_with() 157 mock_exit.assert_not_called() 158 159 def test_print_test_names(self): 160 mock_test_class = mock.MagicMock() 161 mock_cls_instance = mock.MagicMock() 162 mock_test_class.return_value = mock_cls_instance 163 suite_runner._print_test_names([mock_test_class]) 164 mock_cls_instance._pre_run.assert_called_once() 165 mock_cls_instance._clean_up.assert_called_once() 166 167 def test_print_test_names_with_exception(self): 168 mock_test_class = mock.MagicMock() 169 mock_cls_instance = mock.MagicMock() 170 mock_test_class.return_value = mock_cls_instance 171 suite_runner._print_test_names([mock_test_class]) 172 mock_cls_instance._pre_run.side_effect = Exception( 173 'Something went wrong.') 174 mock_cls_instance._clean_up.assert_called_once() 175 176 177if __name__ == "__main__": 178 unittest.main() 179