1#!/usr/bin/env python3 2# 3# Copyright 2016 - The Android Open Source Project 4# 5# Licensed under the Apache License, Version 2.0 (the "License"); 6# you may not use this file except in compliance with the License. 7# You may obtain a copy of the License at 8# 9# http://www.apache.org/licenses/LICENSE-2.0 10# 11# Unless required by applicable law or agreed to in writing, software 12# distributed under the License is distributed on an "AS IS" BASIS, 13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14# See the License for the specific language governing permissions and 15# limitations under the License. 16 17import shutil 18import tempfile 19import unittest 20 21import mock 22import mock_controller 23 24from acts import asserts 25from acts import base_test 26from acts import signals 27 28from mobly import base_test as mobly_base_test 29import mobly.config_parser as mobly_config_parser 30 31MSG_EXPECTED_EXCEPTION = 'This is an expected exception.' 32MSG_EXPECTED_TEST_FAILURE = 'This is an expected test failure.' 33MSG_UNEXPECTED_EXCEPTION = 'Unexpected exception!' 34 35MOCK_EXTRA = {'key': 'value', 'answer_to_everything': 42} 36 37 38def never_call(): 39 raise Exception(MSG_UNEXPECTED_EXCEPTION) 40 41 42class SomeError(Exception): 43 """A custom exception class used for tests in this module.""" 44 45 46class ActsBaseClassTest(unittest.TestCase): 47 def setUp(self): 48 self.tmp_dir = tempfile.mkdtemp() 49 self.tb_key = 'testbed_configs' 50 self.test_run_config = mobly_config_parser.TestRunConfig() 51 self.test_run_config.testbed_name = 'SampleTestBed' 52 self.test_run_config.controller_configs = { 53 self.tb_key: { 54 'name': self.test_run_config.testbed_name, 55 }, 56 } 57 self.test_run_config.log_path = self.tmp_dir 58 self.test_run_config.user_params = {'some_param': 'hahaha'} 59 self.test_run_config.summary_writer = mock.MagicMock() 60 self.mock_test_name = 'test_something' 61 62 def tearDown(self): 63 shutil.rmtree(self.tmp_dir) 64 65 def test_current_test_case_name(self): 66 class MockBaseTest(base_test.BaseTestClass): 67 def test_func(self): 68 asserts.assert_true( 69 self.current_test_name == 'test_func', 70 'Got unexpected test name %s.' % self.current_test_name) 71 72 bt_cls = MockBaseTest(self.test_run_config) 73 bt_cls.run(test_names=['test_func']) 74 actual_record = bt_cls.results.passed[0] 75 self.assertEqual(actual_record.test_name, 'test_func') 76 self.assertIsNone(actual_record.details) 77 self.assertIsNone(actual_record.extras) 78 79 def test_self_tests_list(self): 80 class MockBaseTest(base_test.BaseTestClass): 81 def __init__(self, controllers): 82 super(MockBaseTest, self).__init__(controllers) 83 self.tests = ('test_something', ) 84 85 def test_something(self): 86 pass 87 88 def test_never(self): 89 # This should not execute it's not on default test list. 90 never_call() 91 92 bt_cls = MockBaseTest(self.test_run_config) 93 bt_cls.run() 94 actual_record = bt_cls.results.passed[0] 95 self.assertEqual(actual_record.test_name, 'test_something') 96 97 def test_cli_test_selection_match_self_tests_list(self): 98 class MockBaseTest(base_test.BaseTestClass): 99 def __init__(self, controllers): 100 super(MockBaseTest, self).__init__(controllers) 101 self.tests = ('test_star1', 'test_star2', 'test_question_mark', 102 'test_char_seq', 'test_no_match') 103 104 def test_star1(self): 105 pass 106 107 def test_star2(self): 108 pass 109 110 def test_question_mark(self): 111 pass 112 113 def test_char_seq(self): 114 pass 115 116 def test_no_match(self): 117 # This should not execute because it does not match any regex 118 # in the cmd line input. 119 never_call() 120 121 bt_cls = MockBaseTest(self.test_run_config) 122 test_names = [ 123 'test_st*r1', 'test_*2', 'test_?uestion_mark', 'test_c[fghi]ar_seq' 124 ] 125 bt_cls.run(test_names=test_names) 126 passed_names = [p.test_name for p in bt_cls.results.passed] 127 self.assertEqual(len(passed_names), len(test_names)) 128 for test in [ 129 'test_star1', 'test_star2', 'test_question_mark', 130 'test_char_seq' 131 ]: 132 self.assertIn(test, passed_names) 133 134 def test_default_execution_of_all_tests(self): 135 class MockBaseTest(base_test.BaseTestClass): 136 def test_something(self): 137 pass 138 139 def not_a_test(self): 140 # This should not execute its name doesn't follow test case 141 # naming convention. 142 never_call() 143 144 bt_cls = MockBaseTest(self.test_run_config) 145 bt_cls.run() 146 actual_record = bt_cls.results.passed[0] 147 self.assertEqual(actual_record.test_name, 'test_something') 148 149 def test_setup_class_fail_by_exception(self): 150 call_check = mock.MagicMock() 151 152 class MockBaseTest(base_test.BaseTestClass): 153 def setup_class(self): 154 raise Exception(MSG_EXPECTED_EXCEPTION) 155 156 def test_something(self): 157 # This should not execute because setup_class failed. 158 never_call() 159 160 def on_skip(self, test_name, begin_time): 161 call_check('haha') 162 163 bt_cls = MockBaseTest(self.test_run_config) 164 bt_cls.run() 165 actual_record = bt_cls.results.error[0] 166 self.assertEqual(actual_record.test_name, 'test_something') 167 expected_summary = { 168 'Error': 1, 169 'Executed': 1, 170 'Failed': 0, 171 'Passed': 0, 172 'Requested': 1, 173 'Skipped': 0 174 } 175 self.assertEqual(bt_cls.results.summary_dict(), expected_summary) 176 call_check.assert_called_once_with('haha') 177 178 def test_setup_test_fail_by_exception(self): 179 class MockBaseTest(base_test.BaseTestClass): 180 def setup_test(self): 181 raise Exception(MSG_EXPECTED_EXCEPTION) 182 183 def test_something(self): 184 # This should not execute because setup_test failed. 185 never_call() 186 187 bt_cls = MockBaseTest(self.test_run_config) 188 bt_cls.run(test_names=['test_something']) 189 actual_record = bt_cls.results.error[0] 190 self.assertEqual(actual_record.test_name, self.mock_test_name) 191 self.assertEqual(actual_record.details, MSG_EXPECTED_EXCEPTION) 192 self.assertIsNone(actual_record.extras) 193 expected_summary = { 194 'Error': 1, 195 'Executed': 1, 196 'Failed': 0, 197 'Passed': 0, 198 'Requested': 1, 199 'Skipped': 0 200 } 201 self.assertEqual(bt_cls.results.summary_dict(), expected_summary) 202 203 def test_setup_test_fail_by_test_signal(self): 204 class MockBaseTest(base_test.BaseTestClass): 205 def setup_test(self): 206 raise signals.TestFailure(MSG_EXPECTED_EXCEPTION) 207 208 def test_something(self): 209 # This should not execute because setup_test failed. 210 never_call() 211 212 bt_cls = MockBaseTest(self.test_run_config) 213 bt_cls.run(test_names=['test_something']) 214 actual_record = bt_cls.results.failed[0] 215 self.assertEqual(actual_record.test_name, self.mock_test_name) 216 self.assertEqual(actual_record.details, MSG_EXPECTED_EXCEPTION) 217 self.assertIsNone(actual_record.extras) 218 expected_summary = { 219 'Error': 0, 220 'Executed': 1, 221 'Failed': 1, 222 'Passed': 0, 223 'Requested': 1, 224 'Skipped': 0 225 } 226 self.assertEqual(bt_cls.results.summary_dict(), expected_summary) 227 228 def test_setup_test_fail_by_return_False(self): 229 class MockBaseTest(base_test.BaseTestClass): 230 def setup_test(self): 231 return False 232 233 def test_something(self): 234 # This should not execute because setup_test failed. 235 never_call() 236 237 bt_cls = MockBaseTest(self.test_run_config) 238 bt_cls.run(test_names=['test_something']) 239 actual_record = bt_cls.results.failed[0] 240 expected_msg = 'Setup for %s failed.' % self.mock_test_name 241 self.assertEqual(actual_record.test_name, self.mock_test_name) 242 self.assertEqual(actual_record.details, expected_msg) 243 self.assertIsNone(actual_record.extras) 244 expected_summary = { 245 'Error': 0, 246 'Executed': 1, 247 'Failed': 1, 248 'Passed': 0, 249 'Requested': 1, 250 'Skipped': 0 251 } 252 self.assertEqual(bt_cls.results.summary_dict(), expected_summary) 253 254 def test_teardown_test_assert_fail(self): 255 class MockBaseTest(base_test.BaseTestClass): 256 def teardown_test(self): 257 asserts.assert_true(False, MSG_EXPECTED_EXCEPTION) 258 259 def test_something(self): 260 pass 261 262 bt_cls = MockBaseTest(self.test_run_config) 263 bt_cls.run() 264 actual_record = bt_cls.results.error[0] 265 self.assertEqual(actual_record.test_name, self.mock_test_name) 266 self.assertEqual(actual_record.details, MSG_EXPECTED_EXCEPTION) 267 self.assertIsNone(actual_record.extras) 268 expected_summary = { 269 'Error': 1, 270 'Executed': 1, 271 'Failed': 0, 272 'Passed': 0, 273 'Requested': 1, 274 'Skipped': 0 275 } 276 self.assertEqual(bt_cls.results.summary_dict(), expected_summary) 277 278 def test_teardown_test_raise_exception(self): 279 class MockBaseTest(base_test.BaseTestClass): 280 def teardown_test(self): 281 raise Exception(MSG_EXPECTED_EXCEPTION) 282 283 def test_something(self): 284 pass 285 286 bt_cls = MockBaseTest(self.test_run_config) 287 bt_cls.run() 288 actual_record = bt_cls.results.error[0] 289 self.assertEqual(actual_record.test_name, self.mock_test_name) 290 self.assertEqual(actual_record.details, MSG_EXPECTED_EXCEPTION) 291 self.assertIsNone(actual_record.extras) 292 expected_summary = { 293 'Error': 1, 294 'Executed': 1, 295 'Failed': 0, 296 'Passed': 0, 297 'Requested': 1, 298 'Skipped': 0 299 } 300 self.assertEqual(bt_cls.results.summary_dict(), expected_summary) 301 302 def test_teardown_test_executed_if_test_pass(self): 303 my_mock = mock.MagicMock() 304 305 class MockBaseTest(base_test.BaseTestClass): 306 def teardown_test(self): 307 my_mock('teardown_test') 308 309 def test_something(self): 310 pass 311 312 bt_cls = MockBaseTest(self.test_run_config) 313 bt_cls.run() 314 actual_record = bt_cls.results.passed[0] 315 my_mock.assert_called_once_with('teardown_test') 316 self.assertEqual(actual_record.test_name, self.mock_test_name) 317 self.assertIsNone(actual_record.details) 318 self.assertIsNone(actual_record.extras) 319 expected_summary = { 320 'Error': 0, 321 'Executed': 1, 322 'Failed': 0, 323 'Passed': 1, 324 'Requested': 1, 325 'Skipped': 0 326 } 327 self.assertEqual(bt_cls.results.summary_dict(), expected_summary) 328 329 def test_teardown_test_executed_if_setup_test_fails(self): 330 my_mock = mock.MagicMock() 331 332 class MockBaseTest(base_test.BaseTestClass): 333 def setup_test(self): 334 raise Exception(MSG_EXPECTED_EXCEPTION) 335 336 def teardown_test(self): 337 my_mock('teardown_test') 338 339 def test_something(self): 340 pass 341 342 bt_cls = MockBaseTest(self.test_run_config) 343 bt_cls.run() 344 actual_record = bt_cls.results.error[0] 345 my_mock.assert_called_once_with('teardown_test') 346 self.assertEqual(actual_record.test_name, self.mock_test_name) 347 self.assertEqual(actual_record.details, MSG_EXPECTED_EXCEPTION) 348 self.assertIsNone(actual_record.extras) 349 expected_summary = { 350 'Error': 1, 351 'Executed': 1, 352 'Failed': 0, 353 'Passed': 0, 354 'Requested': 1, 355 'Skipped': 0 356 } 357 self.assertEqual(bt_cls.results.summary_dict(), expected_summary) 358 359 def test_teardown_test_executed_if_test_fails(self): 360 my_mock = mock.MagicMock() 361 362 class MockBaseTest(base_test.BaseTestClass): 363 def teardown_test(self): 364 my_mock('teardown_test') 365 366 def test_something(self): 367 raise Exception(MSG_EXPECTED_EXCEPTION) 368 369 bt_cls = MockBaseTest(self.test_run_config) 370 bt_cls.run() 371 actual_record = bt_cls.results.error[0] 372 my_mock.assert_called_once_with('teardown_test') 373 self.assertEqual(actual_record.test_name, self.mock_test_name) 374 self.assertEqual(actual_record.details, MSG_EXPECTED_EXCEPTION) 375 self.assertIsNone(actual_record.extras) 376 expected_summary = { 377 'Error': 1, 378 'Executed': 1, 379 'Failed': 0, 380 'Passed': 0, 381 'Requested': 1, 382 'Skipped': 0 383 } 384 self.assertEqual(bt_cls.results.summary_dict(), expected_summary) 385 386 def test_on_exception_executed_if_teardown_test_fails(self): 387 my_mock = mock.MagicMock() 388 389 class MockBaseTest(base_test.BaseTestClass): 390 def on_exception(self, test_name, begin_time): 391 my_mock('on_exception') 392 393 def teardown_test(self): 394 raise Exception(MSG_EXPECTED_EXCEPTION) 395 396 def test_something(self): 397 pass 398 399 bt_cls = MockBaseTest(self.test_run_config) 400 bt_cls.run() 401 my_mock.assert_called_once_with('on_exception') 402 actual_record = bt_cls.results.error[0] 403 self.assertEqual(actual_record.test_name, self.mock_test_name) 404 self.assertEqual(actual_record.details, MSG_EXPECTED_EXCEPTION) 405 self.assertIsNone(actual_record.extras) 406 expected_summary = { 407 'Error': 1, 408 'Executed': 1, 409 'Failed': 0, 410 'Passed': 0, 411 'Requested': 1, 412 'Skipped': 0 413 } 414 self.assertEqual(bt_cls.results.summary_dict(), expected_summary) 415 416 def test_on_fail_executed_if_test_fails(self): 417 my_mock = mock.MagicMock() 418 419 class MockBaseTest(base_test.BaseTestClass): 420 def on_fail(self, test_name, begin_time): 421 my_mock('on_fail') 422 423 def test_something(self): 424 asserts.assert_true(False, MSG_EXPECTED_EXCEPTION) 425 426 bt_cls = MockBaseTest(self.test_run_config) 427 bt_cls.run() 428 my_mock.assert_called_once_with('on_fail') 429 actual_record = bt_cls.results.failed[0] 430 self.assertEqual(actual_record.test_name, self.mock_test_name) 431 self.assertEqual(actual_record.details, MSG_EXPECTED_EXCEPTION) 432 self.assertIsNone(actual_record.extras) 433 expected_summary = { 434 'Error': 0, 435 'Executed': 1, 436 'Failed': 1, 437 'Passed': 0, 438 'Requested': 1, 439 'Skipped': 0 440 } 441 self.assertEqual(bt_cls.results.summary_dict(), expected_summary) 442 443 def test_on_fail_executed_if_test_setup_fails_by_exception(self): 444 my_mock = mock.MagicMock() 445 446 class MockBaseTest(base_test.BaseTestClass): 447 def setup_test(self): 448 raise Exception(MSG_EXPECTED_EXCEPTION) 449 450 def on_fail(self, test_name, begin_time): 451 my_mock('on_fail') 452 453 def test_something(self): 454 pass 455 456 bt_cls = MockBaseTest(self.test_run_config) 457 bt_cls.run() 458 my_mock.assert_called_once_with('on_fail') 459 actual_record = bt_cls.results.error[0] 460 self.assertEqual(actual_record.test_name, self.mock_test_name) 461 self.assertEqual(actual_record.details, MSG_EXPECTED_EXCEPTION) 462 self.assertIsNone(actual_record.extras) 463 expected_summary = { 464 'Error': 1, 465 'Executed': 1, 466 'Failed': 0, 467 'Passed': 0, 468 'Requested': 1, 469 'Skipped': 0 470 } 471 self.assertEqual(bt_cls.results.summary_dict(), expected_summary) 472 473 def test_on_fail_executed_if_test_setup_fails_by_return_False(self): 474 my_mock = mock.MagicMock() 475 476 class MockBaseTest(base_test.BaseTestClass): 477 def setup_test(self): 478 return False 479 480 def on_fail(self, test_name, begin_time): 481 my_mock('on_fail') 482 483 def test_something(self): 484 pass 485 486 bt_cls = MockBaseTest(self.test_run_config) 487 bt_cls.run() 488 my_mock.assert_called_once_with('on_fail') 489 actual_record = bt_cls.results.failed[0] 490 self.assertEqual(actual_record.test_name, self.mock_test_name) 491 self.assertEqual(actual_record.details, 492 'Setup for test_something failed.') 493 self.assertIsNone(actual_record.extras) 494 expected_summary = { 495 'Error': 0, 496 'Executed': 1, 497 'Failed': 1, 498 'Passed': 0, 499 'Requested': 1, 500 'Skipped': 0 501 } 502 self.assertEqual(bt_cls.results.summary_dict(), expected_summary) 503 504 def test_failure_to_call_procedure_function_is_recorded(self): 505 class MockBaseTest(base_test.BaseTestClass): 506 # Wrong method signature; will raise exception 507 def on_pass(self): 508 pass 509 510 def test_something(self): 511 asserts.explicit_pass(MSG_EXPECTED_EXCEPTION) 512 513 bt_cls = MockBaseTest(self.test_run_config) 514 bt_cls.run() 515 actual_record = bt_cls.results.error[0] 516 self.assertIn('_on_pass', actual_record.extra_errors) 517 self.assertEqual(actual_record.test_name, self.mock_test_name) 518 self.assertEqual(actual_record.details, MSG_EXPECTED_EXCEPTION) 519 self.assertIsNone(actual_record.extras) 520 expected_summary = { 521 'Error': 1, 522 'Executed': 1, 523 'Failed': 0, 524 'Passed': 0, 525 'Requested': 1, 526 'Skipped': 0 527 } 528 self.assertEqual(bt_cls.results.summary_dict(), expected_summary) 529 530 def test_failure_in_procedure_functions_is_recorded(self): 531 expected_msg = 'Something failed in on_pass.' 532 533 class MockBaseTest(base_test.BaseTestClass): 534 def on_pass(self, test_name, begin_time): 535 raise Exception(expected_msg) 536 537 def test_something(self): 538 asserts.explicit_pass(MSG_EXPECTED_EXCEPTION) 539 540 bt_cls = MockBaseTest(self.test_run_config) 541 bt_cls.run() 542 actual_record = bt_cls.results.error[0] 543 self.assertEqual(actual_record.test_name, self.mock_test_name) 544 self.assertEqual(actual_record.details, MSG_EXPECTED_EXCEPTION) 545 self.assertIsNone(actual_record.extras) 546 expected_summary = { 547 'Error': 1, 548 'Executed': 1, 549 'Failed': 0, 550 'Passed': 0, 551 'Requested': 1, 552 'Skipped': 0 553 } 554 self.assertEqual(bt_cls.results.summary_dict(), expected_summary) 555 556 def test_both_teardown_and_test_body_raise_exceptions(self): 557 class MockBaseTest(base_test.BaseTestClass): 558 def teardown_test(self): 559 asserts.assert_true(False, MSG_EXPECTED_EXCEPTION) 560 561 def test_something(self): 562 raise Exception('Test Body Exception.') 563 564 bt_cls = MockBaseTest(self.test_run_config) 565 bt_cls.run() 566 actual_record = bt_cls.results.error[0] 567 self.assertEqual(actual_record.test_name, self.mock_test_name) 568 self.assertEqual(actual_record.details, 'Test Body Exception.') 569 self.assertIsNone(actual_record.extras) 570 self.assertEqual(actual_record.extra_errors['teardown_test'].details, 571 'This is an expected exception.') 572 expected_summary = { 573 'Error': 1, 574 'Executed': 1, 575 'Failed': 0, 576 'Passed': 0, 577 'Requested': 1, 578 'Skipped': 0 579 } 580 self.assertEqual(bt_cls.results.summary_dict(), expected_summary) 581 582 def test_explicit_pass_but_teardown_test_raises_an_exception(self): 583 """Test record result should be marked as UNKNOWN as opposed to PASS. 584 """ 585 class MockBaseTest(base_test.BaseTestClass): 586 def teardown_test(self): 587 asserts.assert_true(False, MSG_EXPECTED_EXCEPTION) 588 589 def test_something(self): 590 asserts.explicit_pass('Test Passed!') 591 592 bt_cls = MockBaseTest(self.test_run_config) 593 bt_cls.run() 594 actual_record = bt_cls.results.error[0] 595 self.assertEqual(actual_record.test_name, self.mock_test_name) 596 self.assertEqual(actual_record.details, 'Test Passed!') 597 self.assertIsNone(actual_record.extras) 598 self.assertEqual(actual_record.extra_errors['teardown_test'].details, 599 'This is an expected exception.') 600 expected_summary = { 601 'Error': 1, 602 'Executed': 1, 603 'Failed': 0, 604 'Passed': 0, 605 'Requested': 1, 606 'Skipped': 0 607 } 608 self.assertEqual(bt_cls.results.summary_dict(), expected_summary) 609 610 def test_on_pass_raise_exception(self): 611 class MockBaseTest(base_test.BaseTestClass): 612 def on_pass(self, test_name, begin_time): 613 raise Exception(MSG_EXPECTED_EXCEPTION) 614 615 def test_something(self): 616 asserts.explicit_pass(MSG_EXPECTED_EXCEPTION, 617 extras=MOCK_EXTRA) 618 619 bt_cls = MockBaseTest(self.test_run_config) 620 bt_cls.run() 621 actual_record = bt_cls.results.error[0] 622 self.assertEqual(actual_record.test_name, self.mock_test_name) 623 self.assertEqual(actual_record.details, MSG_EXPECTED_EXCEPTION) 624 self.assertEqual(actual_record.extras, MOCK_EXTRA) 625 expected_summary = { 626 'Error': 1, 627 'Executed': 1, 628 'Failed': 0, 629 'Passed': 0, 630 'Requested': 1, 631 'Skipped': 0 632 } 633 self.assertEqual(bt_cls.results.summary_dict(), expected_summary) 634 635 def test_on_fail_raise_exception(self): 636 class MockBaseTest(base_test.BaseTestClass): 637 def on_fail(self, test_name, begin_time): 638 raise Exception(MSG_EXPECTED_EXCEPTION) 639 640 def test_something(self): 641 asserts.fail(MSG_EXPECTED_EXCEPTION, extras=MOCK_EXTRA) 642 643 bt_cls = MockBaseTest(self.test_run_config) 644 bt_cls.run() 645 actual_record = bt_cls.results.failed[0] 646 self.assertEqual(bt_cls.results.error, []) 647 self.assertEqual(actual_record.test_name, self.mock_test_name) 648 self.assertEqual(actual_record.details, MSG_EXPECTED_EXCEPTION) 649 self.assertEqual(actual_record.extras, MOCK_EXTRA) 650 expected_summary = { 651 'Error': 0, 652 'Executed': 1, 653 'Failed': 1, 654 'Passed': 0, 655 'Requested': 1, 656 'Skipped': 0 657 } 658 self.assertEqual(bt_cls.results.summary_dict(), expected_summary) 659 660 def test_abort_class(self): 661 class MockBaseTest(base_test.BaseTestClass): 662 def test_1(self): 663 pass 664 665 def test_2(self): 666 asserts.abort_class(MSG_EXPECTED_EXCEPTION) 667 never_call() 668 669 def test_3(self): 670 never_call() 671 672 bt_cls = MockBaseTest(self.test_run_config) 673 bt_cls.run(test_names=['test_1', 'test_2', 'test_3']) 674 self.assertEqual(bt_cls.results.passed[0].test_name, 'test_1') 675 self.assertEqual(bt_cls.results.failed[0].details, 676 MSG_EXPECTED_EXCEPTION) 677 expected_summary = { 678 'Error': 0, 679 'Executed': 2, 680 'Failed': 1, 681 'Passed': 1, 682 'Requested': 3, 683 'Skipped': 0 684 } 685 self.assertEqual(bt_cls.results.summary_dict(), expected_summary) 686 687 def test_uncaught_exception(self): 688 class MockBaseTest(base_test.BaseTestClass): 689 def test_func(self): 690 raise Exception(MSG_EXPECTED_EXCEPTION) 691 never_call() 692 693 bt_cls = MockBaseTest(self.test_run_config) 694 bt_cls.run(test_names=['test_func']) 695 actual_record = bt_cls.results.error[0] 696 self.assertEqual(actual_record.test_name, 'test_func') 697 self.assertEqual(actual_record.details, MSG_EXPECTED_EXCEPTION) 698 self.assertIsNone(actual_record.extras) 699 700 def test_fail(self): 701 class MockBaseTest(base_test.BaseTestClass): 702 def test_func(self): 703 asserts.fail(MSG_EXPECTED_EXCEPTION, extras=MOCK_EXTRA) 704 never_call() 705 706 bt_cls = MockBaseTest(self.test_run_config) 707 bt_cls.run(test_names=['test_func']) 708 actual_record = bt_cls.results.failed[0] 709 self.assertEqual(actual_record.test_name, 'test_func') 710 self.assertEqual(actual_record.details, MSG_EXPECTED_EXCEPTION) 711 self.assertEqual(actual_record.extras, MOCK_EXTRA) 712 713 def test_assert_true(self): 714 class MockBaseTest(base_test.BaseTestClass): 715 def test_func(self): 716 asserts.assert_true(False, 717 MSG_EXPECTED_EXCEPTION, 718 extras=MOCK_EXTRA) 719 never_call() 720 721 bt_cls = MockBaseTest(self.test_run_config) 722 bt_cls.run(test_names=['test_func']) 723 actual_record = bt_cls.results.failed[0] 724 self.assertEqual(actual_record.test_name, 'test_func') 725 self.assertEqual(actual_record.details, MSG_EXPECTED_EXCEPTION) 726 self.assertEqual(actual_record.extras, MOCK_EXTRA) 727 728 def test_assert_equal_pass(self): 729 class MockBaseTest(base_test.BaseTestClass): 730 def test_func(self): 731 asserts.assert_equal(1, 1, extras=MOCK_EXTRA) 732 733 bt_cls = MockBaseTest(self.test_run_config) 734 bt_cls.run() 735 actual_record = bt_cls.results.passed[0] 736 self.assertEqual(actual_record.test_name, 'test_func') 737 self.assertIsNone(actual_record.details) 738 self.assertIsNone(actual_record.extras) 739 740 def test_assert_equal_fail(self): 741 class MockBaseTest(base_test.BaseTestClass): 742 def test_func(self): 743 asserts.assert_equal(1, 2, extras=MOCK_EXTRA) 744 745 bt_cls = MockBaseTest(self.test_run_config) 746 bt_cls.run() 747 actual_record = bt_cls.results.failed[0] 748 self.assertEqual(actual_record.test_name, 'test_func') 749 self.assertIn('1 != 2', actual_record.details) 750 self.assertEqual(actual_record.extras, MOCK_EXTRA) 751 752 def test_assert_equal_fail_with_msg(self): 753 class MockBaseTest(base_test.BaseTestClass): 754 def test_func(self): 755 asserts.assert_equal(1, 756 2, 757 msg=MSG_EXPECTED_EXCEPTION, 758 extras=MOCK_EXTRA) 759 760 bt_cls = MockBaseTest(self.test_run_config) 761 bt_cls.run() 762 actual_record = bt_cls.results.failed[0] 763 self.assertEqual(actual_record.test_name, 'test_func') 764 expected_msg = '1 != 2 ' + MSG_EXPECTED_EXCEPTION 765 self.assertIn(expected_msg, actual_record.details) 766 self.assertEqual(actual_record.extras, MOCK_EXTRA) 767 768 def test_assert_raises_pass(self): 769 class MockBaseTest(base_test.BaseTestClass): 770 def test_func(self): 771 with asserts.assert_raises(SomeError, extras=MOCK_EXTRA): 772 raise SomeError(MSG_EXPECTED_EXCEPTION) 773 774 bt_cls = MockBaseTest(self.test_run_config) 775 bt_cls.run() 776 actual_record = bt_cls.results.passed[0] 777 self.assertEqual(actual_record.test_name, 'test_func') 778 self.assertIsNone(actual_record.details) 779 self.assertIsNone(actual_record.extras) 780 781 def test_assert_raises_regex_pass(self): 782 class MockBaseTest(base_test.BaseTestClass): 783 def test_func(self): 784 with asserts.assert_raises_regex( 785 SomeError, 786 expected_regex=MSG_EXPECTED_EXCEPTION, 787 extras=MOCK_EXTRA): 788 raise SomeError(MSG_EXPECTED_EXCEPTION) 789 790 bt_cls = MockBaseTest(self.test_run_config) 791 bt_cls.run() 792 actual_record = bt_cls.results.passed[0] 793 self.assertEqual(actual_record.test_name, 'test_func') 794 self.assertIsNone(actual_record.details) 795 self.assertIsNone(actual_record.extras) 796 797 def test_assert_raises_fail_with_noop(self): 798 class MockBaseTest(base_test.BaseTestClass): 799 def test_func(self): 800 with asserts.assert_raises_regex( 801 SomeError, 802 expected_regex=MSG_EXPECTED_EXCEPTION, 803 extras=MOCK_EXTRA): 804 pass 805 806 bt_cls = MockBaseTest(self.test_run_config) 807 bt_cls.run() 808 actual_record = bt_cls.results.failed[0] 809 self.assertEqual(actual_record.test_name, 'test_func') 810 self.assertEqual(actual_record.details, 'SomeError not raised') 811 self.assertEqual(actual_record.extras, MOCK_EXTRA) 812 813 def test_assert_raises_fail_with_wrong_regex(self): 814 wrong_msg = 'ha' 815 816 class MockBaseTest(base_test.BaseTestClass): 817 def test_func(self): 818 with asserts.assert_raises_regex( 819 SomeError, 820 expected_regex=MSG_EXPECTED_EXCEPTION, 821 extras=MOCK_EXTRA): 822 raise SomeError(wrong_msg) 823 824 bt_cls = MockBaseTest(self.test_run_config) 825 bt_cls.run() 826 actual_record = bt_cls.results.failed[0] 827 self.assertEqual(actual_record.test_name, 'test_func') 828 expected_details = ('"This is an expected exception." does not match ' 829 '"%s"') % wrong_msg 830 self.assertEqual(actual_record.details, expected_details) 831 self.assertEqual(actual_record.extras, MOCK_EXTRA) 832 833 def test_assert_raises_fail_with_wrong_error(self): 834 class MockBaseTest(base_test.BaseTestClass): 835 def test_func(self): 836 with asserts.assert_raises_regex( 837 SomeError, 838 expected_regex=MSG_EXPECTED_EXCEPTION, 839 extras=MOCK_EXTRA): 840 raise AttributeError(MSG_UNEXPECTED_EXCEPTION) 841 842 bt_cls = MockBaseTest(self.test_run_config) 843 bt_cls.run() 844 actual_record = bt_cls.results.error[0] 845 self.assertEqual(actual_record.test_name, 'test_func') 846 self.assertEqual(actual_record.details, MSG_UNEXPECTED_EXCEPTION) 847 self.assertIsNone(actual_record.extras) 848 849 def test_explicit_pass(self): 850 class MockBaseTest(base_test.BaseTestClass): 851 def test_func(self): 852 asserts.explicit_pass(MSG_EXPECTED_EXCEPTION, 853 extras=MOCK_EXTRA) 854 never_call() 855 856 bt_cls = MockBaseTest(self.test_run_config) 857 bt_cls.run(test_names=['test_func']) 858 actual_record = bt_cls.results.passed[0] 859 self.assertEqual(actual_record.test_name, 'test_func') 860 self.assertEqual(actual_record.details, MSG_EXPECTED_EXCEPTION) 861 self.assertEqual(actual_record.extras, MOCK_EXTRA) 862 863 def test_implicit_pass(self): 864 class MockBaseTest(base_test.BaseTestClass): 865 def test_func(self): 866 pass 867 868 bt_cls = MockBaseTest(self.test_run_config) 869 bt_cls.run(test_names=['test_func']) 870 actual_record = bt_cls.results.passed[0] 871 self.assertEqual(actual_record.test_name, 'test_func') 872 self.assertIsNone(actual_record.details) 873 self.assertIsNone(actual_record.extras) 874 875 def test_skip(self): 876 class MockBaseTest(base_test.BaseTestClass): 877 def test_func(self): 878 asserts.skip(MSG_EXPECTED_EXCEPTION, extras=MOCK_EXTRA) 879 never_call() 880 881 bt_cls = MockBaseTest(self.test_run_config) 882 bt_cls.run(test_names=['test_func']) 883 actual_record = bt_cls.results.skipped[0] 884 self.assertEqual(actual_record.test_name, 'test_func') 885 self.assertEqual(actual_record.details, MSG_EXPECTED_EXCEPTION) 886 self.assertEqual(actual_record.extras, MOCK_EXTRA) 887 888 def test_skip_if(self): 889 class MockBaseTest(base_test.BaseTestClass): 890 def test_func(self): 891 asserts.skip_if(False, MSG_UNEXPECTED_EXCEPTION) 892 asserts.skip_if(True, 893 MSG_EXPECTED_EXCEPTION, 894 extras=MOCK_EXTRA) 895 never_call() 896 897 bt_cls = MockBaseTest(self.test_run_config) 898 bt_cls.run(test_names=['test_func']) 899 actual_record = bt_cls.results.skipped[0] 900 self.assertEqual(actual_record.test_name, 'test_func') 901 self.assertEqual(actual_record.details, MSG_EXPECTED_EXCEPTION) 902 self.assertEqual(actual_record.extras, MOCK_EXTRA) 903 904 def test_unpack_userparams_required(self): 905 """Missing a required param should raise an error.""" 906 required = ['some_param'] 907 bc = base_test.BaseTestClass(self.test_run_config) 908 bc.unpack_userparams(required) 909 expected_value = self.test_run_config.user_params['some_param'] 910 self.assertEqual(bc.some_param, expected_value) 911 912 def test_unpack_userparams_required_missing(self): 913 """Missing a required param should raise an error.""" 914 required = ['something'] 915 bc = base_test.BaseTestClass(self.test_run_config) 916 expected_msg = ('Missing required user param "%s" in test ' 917 'configuration.') % required[0] 918 with self.assertRaises(mobly_base_test.Error, msg=expected_msg): 919 bc.unpack_userparams(required) 920 921 def test_unpack_userparams_optional(self): 922 """If an optional param is specified, the value should be what's in the 923 config. 924 """ 925 opt = ['some_param'] 926 bc = base_test.BaseTestClass(self.test_run_config) 927 bc.unpack_userparams(opt_param_names=opt) 928 expected_value = self.test_run_config.user_params['some_param'] 929 self.assertEqual(bc.some_param, expected_value) 930 931 def test_unpack_userparams_optional_with_default(self): 932 """If an optional param is specified with a default value, and the 933 param is not in the config, the value should be the default value. 934 """ 935 bc = base_test.BaseTestClass(self.test_run_config) 936 bc.unpack_userparams(optional_thing='whatever') 937 self.assertEqual(bc.optional_thing, 'whatever') 938 939 def test_unpack_userparams_default_overwrite_by_optional_param_list(self): 940 """If an optional param is specified in kwargs, and the param is in the 941 config, the value should be the one in the config. 942 """ 943 bc = base_test.BaseTestClass(self.test_run_config) 944 bc.unpack_userparams(some_param='whatever') 945 expected_value = self.test_run_config.user_params['some_param'] 946 self.assertEqual(bc.some_param, expected_value) 947 948 def test_unpack_userparams_default_overwrite_by_required_param_list(self): 949 """If an optional param is specified in kwargs, the param is in the 950 required param list, and the param is not specified in the config, the 951 param's alue should be the default value and there should be no error 952 thrown. 953 """ 954 bc = base_test.BaseTestClass(self.test_run_config) 955 bc.unpack_userparams(req_param_names=['a_kwarg_param'], 956 a_kwarg_param='whatever') 957 self.assertEqual(bc.a_kwarg_param, 'whatever') 958 959 def test_unpack_userparams_optional_missing(self): 960 """Missing an optional param should not raise an error.""" 961 opt = ['something'] 962 bc = base_test.BaseTestClass(self.test_run_config) 963 bc.unpack_userparams(opt_param_names=opt) 964 965 def test_unpack_userparams_basic(self): 966 """Required and optional params are unpacked properly.""" 967 required = ['something'] 968 optional = ['something_else'] 969 configs = self.test_run_config.copy() 970 configs.user_params['something'] = 42 971 configs.user_params['something_else'] = 53 972 bc = base_test.BaseTestClass(configs) 973 bc.unpack_userparams(req_param_names=required, 974 opt_param_names=optional) 975 self.assertEqual(bc.something, 42) 976 self.assertEqual(bc.something_else, 53) 977 978 def test_unpack_userparams_default_overwrite(self): 979 default_arg_val = 'haha' 980 actual_arg_val = 'wawa' 981 arg_name = 'arg1' 982 configs = self.test_run_config.copy() 983 configs.user_params[arg_name] = actual_arg_val 984 bc = base_test.BaseTestClass(configs) 985 bc.unpack_userparams(opt_param_names=[arg_name], arg1=default_arg_val) 986 self.assertEqual(bc.arg1, actual_arg_val) 987 988 def test_unpack_userparams_default_None(self): 989 bc = base_test.BaseTestClass(self.test_run_config) 990 bc.unpack_userparams(arg1='haha') 991 self.assertEqual(bc.arg1, 'haha') 992 993 def test_register_controller_no_config(self): 994 base_cls = base_test.BaseTestClass(self.test_run_config) 995 with self.assertRaisesRegexp(signals.ControllerError, 996 'No corresponding config found for'): 997 base_cls.register_controller(mock_controller) 998 999 def test_register_optional_controller_no_config(self): 1000 base_cls = base_test.BaseTestClass(self.test_run_config) 1001 self.assertIsNone( 1002 base_cls.register_controller(mock_controller, required=False)) 1003 1004 def test_register_controller_third_party_dup_register(self): 1005 """Verifies correctness of registration, internal tally of controllers 1006 objects, and the right error happen when a controller module is 1007 registered twice. 1008 """ 1009 mock_test_config = self.test_run_config.copy() 1010 mock_ctrlr_config_name = mock_controller.MOBLY_CONTROLLER_CONFIG_NAME 1011 mock_test_config.controller_configs[mock_ctrlr_config_name] = [ 1012 'magic1', 'magic2' 1013 ] 1014 base_cls = base_test.BaseTestClass(mock_test_config) 1015 base_cls.register_controller(mock_controller) 1016 registered_name = 'mock_controller' 1017 controller_objects = base_cls._controller_manager._controller_objects 1018 self.assertTrue(registered_name in controller_objects) 1019 mock_ctrlrs = controller_objects[registered_name] 1020 self.assertEqual(mock_ctrlrs[0].magic, 'magic1') 1021 self.assertEqual(mock_ctrlrs[1].magic, 'magic2') 1022 expected_msg = 'Controller module .* has already been registered.' 1023 with self.assertRaisesRegexp(signals.ControllerError, expected_msg): 1024 base_cls.register_controller(mock_controller) 1025 1026 def test_register_optional_controller_third_party_dup_register(self): 1027 """Verifies correctness of registration, internal tally of controllers 1028 objects, and the right error happen when an optional controller module 1029 is registered twice. 1030 """ 1031 mock_test_config = self.test_run_config.copy() 1032 mock_ctrlr_config_name = mock_controller.MOBLY_CONTROLLER_CONFIG_NAME 1033 mock_test_config.controller_configs[mock_ctrlr_config_name] = [ 1034 'magic1', 'magic2' 1035 ] 1036 base_cls = base_test.BaseTestClass(mock_test_config) 1037 base_cls.register_controller(mock_controller, required=False) 1038 expected_msg = 'Controller module .* has already been registered.' 1039 with self.assertRaisesRegexp(signals.ControllerError, expected_msg): 1040 base_cls.register_controller(mock_controller, required=False) 1041 1042 def test_register_controller_builtin_dup_register(self): 1043 """Same as test_register_controller_third_party_dup_register, except 1044 this is for a builtin controller module. 1045 """ 1046 mock_test_config = self.test_run_config.copy() 1047 mock_ctrlr_config_name = mock_controller.MOBLY_CONTROLLER_CONFIG_NAME 1048 mock_ref_name = 'haha' 1049 setattr(mock_controller, 'ACTS_CONTROLLER_REFERENCE_NAME', 1050 mock_ref_name) 1051 try: 1052 mock_ctrlr_ref_name = mock_controller.ACTS_CONTROLLER_REFERENCE_NAME 1053 mock_test_config.controller_configs[mock_ctrlr_config_name] = [ 1054 'magic1', 'magic2' 1055 ] 1056 base_cls = base_test.BaseTestClass(mock_test_config) 1057 base_cls.register_controller(mock_controller, builtin=True) 1058 self.assertTrue(hasattr(base_cls, mock_ref_name)) 1059 self.assertTrue(mock_controller.__name__ in 1060 base_cls._controller_manager._controller_objects) 1061 mock_ctrlrs = getattr(base_cls, mock_ctrlr_ref_name) 1062 self.assertEqual(mock_ctrlrs[0].magic, 'magic1') 1063 self.assertEqual(mock_ctrlrs[1].magic, 'magic2') 1064 expected_msg = 'Controller module .* has already been registered.' 1065 with self.assertRaisesRegexp(signals.ControllerError, 1066 expected_msg): 1067 base_cls.register_controller(mock_controller, builtin=True) 1068 finally: 1069 delattr(mock_controller, 'ACTS_CONTROLLER_REFERENCE_NAME') 1070 1071 def test_register_controller_no_get_info(self): 1072 mock_test_config = self.test_run_config.copy() 1073 mock_ctrlr_config_name = mock_controller.MOBLY_CONTROLLER_CONFIG_NAME 1074 mock_ref_name = 'haha' 1075 get_info = getattr(mock_controller, 'get_info') 1076 delattr(mock_controller, 'get_info') 1077 try: 1078 mock_test_config.controller_configs[mock_ctrlr_config_name] = [ 1079 'magic1', 'magic2' 1080 ] 1081 base_cls = base_test.BaseTestClass(mock_test_config) 1082 base_cls.register_controller(mock_controller) 1083 self.assertEqual(base_cls.results.controller_info, []) 1084 finally: 1085 setattr(mock_controller, 'get_info', get_info) 1086 1087 def test_register_controller_return_value(self): 1088 mock_test_config = self.test_run_config.copy() 1089 mock_ctrlr_config_name = mock_controller.MOBLY_CONTROLLER_CONFIG_NAME 1090 mock_test_config.controller_configs[mock_ctrlr_config_name] = [ 1091 'magic1', 'magic2' 1092 ] 1093 base_cls = base_test.BaseTestClass(mock_test_config) 1094 magic_devices = base_cls.register_controller(mock_controller) 1095 self.assertEqual(magic_devices[0].magic, 'magic1') 1096 self.assertEqual(magic_devices[1].magic, 'magic2') 1097 1098 def test_handle_file_user_params_does_not_overwrite_existing_params(self): 1099 test_run_config = self.test_run_config.copy() 1100 test_run_config.user_params = { 1101 'foo': ['good_value'], 1102 'local_files': { 1103 'foo': ['bad_value'] 1104 } 1105 } 1106 test = base_test.BaseTestClass(test_run_config) 1107 1108 self.assertEqual(test.user_params['foo'], ['good_value']) 1109 1110 def test_handle_file_user_params_dumps_files_dict(self): 1111 test_run_config = self.test_run_config.copy() 1112 test_run_config.user_params = { 1113 'my_files': { 1114 'foo': ['good_value'] 1115 } 1116 } 1117 test = base_test.BaseTestClass(test_run_config) 1118 1119 self.assertEqual(test.user_params['foo'], ['good_value']) 1120 1121 def test_handle_file_user_params_is_called_in_init(self): 1122 test_run_config = self.test_run_config.copy() 1123 test_run_config.user_params['files'] = { 1124 'file_a': ['/some/path'] 1125 } 1126 test = base_test.BaseTestClass(test_run_config) 1127 1128 self.assertEqual(test.user_params['file_a'], ['/some/path']) 1129 1130 1131if __name__ == '__main__': 1132 unittest.main() 1133