1# Copyright 2017 The Abseil Authors. 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 15"""Tests for absltest.""" 16 17import collections 18import contextlib 19import dataclasses 20import io 21import os 22import pathlib 23import re 24import stat 25import string 26import subprocess 27import sys 28import tempfile 29import textwrap 30from typing import Optional 31import unittest 32 33from absl.testing import _bazelize_command 34from absl.testing import absltest 35from absl.testing import parameterized 36from absl.testing.tests import absltest_env 37 38 39class BaseTestCase(absltest.TestCase): 40 41 def _get_helper_exec_path(self, helper_name): 42 helper = 'absl/testing/tests/' + helper_name 43 return _bazelize_command.get_executable_path(helper) 44 45 def run_helper( 46 self, 47 test_id, 48 args, 49 env_overrides, 50 expect_success, 51 helper_name=None, 52 ): 53 env = absltest_env.inherited_env() 54 for key, value in env_overrides.items(): 55 if value is None: 56 if key in env: 57 del env[key] 58 else: 59 env[key] = value 60 61 if helper_name is None: 62 helper_name = 'absltest_test_helper' 63 command = [self._get_helper_exec_path(helper_name)] 64 if test_id is not None: 65 command.append('--test_id={}'.format(test_id)) 66 command.extend(args) 67 process = subprocess.Popen( 68 command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=env, 69 universal_newlines=True) 70 stdout, stderr = process.communicate() 71 if expect_success: 72 self.assertEqual( 73 0, 74 process.returncode, 75 'Expected success, but failed with exit code {},' 76 ' stdout:\n{}\nstderr:\n{}\n'.format( 77 process.returncode, stdout, stderr 78 ), 79 ) 80 else: 81 self.assertGreater( 82 process.returncode, 83 0, 84 'Expected failure, but succeeded with ' 85 'stdout:\n{}\nstderr:\n{}\n'.format(stdout, stderr), 86 ) 87 return stdout, stderr, process.returncode 88 89 90class TestCaseTest(BaseTestCase): 91 longMessage = True 92 93 def run_helper( 94 self, test_id, args, env_overrides, expect_success, helper_name=None 95 ): 96 return super(TestCaseTest, self).run_helper( 97 test_id, 98 args + ['HelperTest'], 99 env_overrides, 100 expect_success, 101 helper_name, 102 ) 103 104 def test_flags_no_env_var_no_flags(self): 105 self.run_helper( 106 1, 107 [], 108 {'TEST_RANDOM_SEED': None, 109 'TEST_SRCDIR': None, 110 'TEST_TMPDIR': None, 111 }, 112 expect_success=True) 113 114 def test_flags_env_var_no_flags(self): 115 tmpdir = tempfile.mkdtemp(dir=absltest.TEST_TMPDIR.value) 116 srcdir = tempfile.mkdtemp(dir=absltest.TEST_TMPDIR.value) 117 self.run_helper( 118 2, 119 [], 120 {'TEST_RANDOM_SEED': '321', 121 'TEST_SRCDIR': srcdir, 122 'TEST_TMPDIR': tmpdir, 123 'ABSLTEST_TEST_HELPER_EXPECTED_TEST_SRCDIR': srcdir, 124 'ABSLTEST_TEST_HELPER_EXPECTED_TEST_TMPDIR': tmpdir, 125 }, 126 expect_success=True) 127 128 def test_flags_no_env_var_flags(self): 129 tmpdir = tempfile.mkdtemp(dir=absltest.TEST_TMPDIR.value) 130 srcdir = tempfile.mkdtemp(dir=absltest.TEST_TMPDIR.value) 131 self.run_helper( 132 3, 133 ['--test_random_seed=123', '--test_srcdir={}'.format(srcdir), 134 '--test_tmpdir={}'.format(tmpdir)], 135 {'TEST_RANDOM_SEED': None, 136 'TEST_SRCDIR': None, 137 'TEST_TMPDIR': None, 138 'ABSLTEST_TEST_HELPER_EXPECTED_TEST_SRCDIR': srcdir, 139 'ABSLTEST_TEST_HELPER_EXPECTED_TEST_TMPDIR': tmpdir, 140 }, 141 expect_success=True) 142 143 def test_flags_env_var_flags(self): 144 tmpdir_from_flag = tempfile.mkdtemp(dir=absltest.TEST_TMPDIR.value) 145 srcdir_from_flag = tempfile.mkdtemp(dir=absltest.TEST_TMPDIR.value) 146 tmpdir_from_env_var = tempfile.mkdtemp(dir=absltest.TEST_TMPDIR.value) 147 srcdir_from_env_var = tempfile.mkdtemp(dir=absltest.TEST_TMPDIR.value) 148 self.run_helper( 149 4, 150 ['--test_random_seed=221', '--test_srcdir={}'.format(srcdir_from_flag), 151 '--test_tmpdir={}'.format(tmpdir_from_flag)], 152 {'TEST_RANDOM_SEED': '123', 153 'TEST_SRCDIR': srcdir_from_env_var, 154 'TEST_TMPDIR': tmpdir_from_env_var, 155 'ABSLTEST_TEST_HELPER_EXPECTED_TEST_SRCDIR': srcdir_from_flag, 156 'ABSLTEST_TEST_HELPER_EXPECTED_TEST_TMPDIR': tmpdir_from_flag, 157 }, 158 expect_success=True) 159 160 def test_xml_output_file_from_xml_output_file_env(self): 161 xml_dir = tempfile.mkdtemp(dir=absltest.TEST_TMPDIR.value) 162 xml_output_file_env = os.path.join(xml_dir, 'xml_output_file.xml') 163 random_dir = tempfile.mkdtemp(dir=absltest.TEST_TMPDIR.value) 164 self.run_helper( 165 6, 166 [], 167 {'XML_OUTPUT_FILE': xml_output_file_env, 168 'RUNNING_UNDER_TEST_DAEMON': '1', 169 'TEST_XMLOUTPUTDIR': random_dir, 170 'ABSLTEST_TEST_HELPER_EXPECTED_XML_OUTPUT_FILE': xml_output_file_env, 171 }, 172 expect_success=True) 173 174 def test_xml_output_file_from_daemon(self): 175 tmpdir = os.path.join(tempfile.mkdtemp( 176 dir=absltest.TEST_TMPDIR.value), 'sub_dir') 177 random_dir = tempfile.mkdtemp(dir=absltest.TEST_TMPDIR.value) 178 self.run_helper( 179 6, 180 ['--test_tmpdir', tmpdir], 181 {'XML_OUTPUT_FILE': None, 182 'RUNNING_UNDER_TEST_DAEMON': '1', 183 'TEST_XMLOUTPUTDIR': random_dir, 184 'ABSLTEST_TEST_HELPER_EXPECTED_XML_OUTPUT_FILE': os.path.join( 185 os.path.dirname(tmpdir), 'test_detail.xml'), 186 }, 187 expect_success=True) 188 189 def test_xml_output_file_from_test_xmloutputdir_env(self): 190 xml_output_dir = tempfile.mkdtemp(dir=absltest.TEST_TMPDIR.value) 191 expected_xml_file = 'absltest_test_helper.xml' 192 self.run_helper( 193 6, 194 [], 195 {'XML_OUTPUT_FILE': None, 196 'RUNNING_UNDER_TEST_DAEMON': None, 197 'TEST_XMLOUTPUTDIR': xml_output_dir, 198 'ABSLTEST_TEST_HELPER_EXPECTED_XML_OUTPUT_FILE': os.path.join( 199 xml_output_dir, expected_xml_file), 200 }, 201 expect_success=True) 202 203 def test_xml_output_file_from_flag(self): 204 random_dir = tempfile.mkdtemp(dir=absltest.TEST_TMPDIR.value) 205 flag_file = os.path.join( 206 tempfile.mkdtemp(dir=absltest.TEST_TMPDIR.value), 'output.xml') 207 self.run_helper( 208 6, 209 ['--xml_output_file', flag_file], 210 {'XML_OUTPUT_FILE': os.path.join(random_dir, 'output.xml'), 211 'RUNNING_UNDER_TEST_DAEMON': '1', 212 'TEST_XMLOUTPUTDIR': random_dir, 213 'ABSLTEST_TEST_HELPER_EXPECTED_XML_OUTPUT_FILE': flag_file, 214 }, 215 expect_success=True) 216 217 def test_app_run(self): 218 stdout, _, _ = self.run_helper( 219 7, 220 ['--name=cat', '--name=dog'], 221 {'ABSLTEST_TEST_HELPER_USE_APP_RUN': '1'}, 222 expect_success=True, 223 ) 224 self.assertIn('Names in main() are: cat dog', stdout) 225 self.assertIn('Names in test_name_flag() are: cat dog', stdout) 226 227 def test_assert_in(self): 228 animals = {'monkey': 'banana', 'cow': 'grass', 'seal': 'fish'} 229 230 self.assertIn('a', 'abc') 231 self.assertIn(2, [1, 2, 3]) 232 self.assertIn('monkey', animals) 233 234 self.assertNotIn('d', 'abc') 235 self.assertNotIn(0, [1, 2, 3]) 236 self.assertNotIn('otter', animals) 237 238 self.assertRaises(AssertionError, self.assertIn, 'x', 'abc') 239 self.assertRaises(AssertionError, self.assertIn, 4, [1, 2, 3]) 240 self.assertRaises(AssertionError, self.assertIn, 'elephant', animals) 241 242 self.assertRaises(AssertionError, self.assertNotIn, 'c', 'abc') 243 self.assertRaises(AssertionError, self.assertNotIn, 1, [1, 2, 3]) 244 self.assertRaises(AssertionError, self.assertNotIn, 'cow', animals) 245 246 @absltest.expectedFailure 247 def test_expected_failure(self): 248 self.assertEqual(1, 2) # the expected failure 249 250 @absltest.expectedFailureIf(True, 'always true') 251 def test_expected_failure_if(self): 252 self.assertEqual(1, 2) # the expected failure 253 254 def test_expected_failure_success(self): 255 _, stderr, _ = self.run_helper(5, ['--', '-v'], {}, expect_success=False) 256 self.assertRegex(stderr, r'FAILED \(.*unexpected successes=1\)') 257 258 def test_assert_equal(self): 259 self.assertListEqual([], []) 260 self.assertTupleEqual((), ()) 261 self.assertSequenceEqual([], ()) 262 263 a = [0, 'a', []] 264 b = [] 265 self.assertRaises(absltest.TestCase.failureException, 266 self.assertListEqual, a, b) 267 self.assertRaises(absltest.TestCase.failureException, 268 self.assertListEqual, tuple(a), tuple(b)) 269 self.assertRaises(absltest.TestCase.failureException, 270 self.assertSequenceEqual, a, tuple(b)) 271 272 b.extend(a) 273 self.assertListEqual(a, b) 274 self.assertTupleEqual(tuple(a), tuple(b)) 275 self.assertSequenceEqual(a, tuple(b)) 276 self.assertSequenceEqual(tuple(a), b) 277 278 self.assertRaises(AssertionError, self.assertListEqual, a, tuple(b)) 279 self.assertRaises(AssertionError, self.assertTupleEqual, tuple(a), b) 280 self.assertRaises(AssertionError, self.assertListEqual, None, b) 281 self.assertRaises(AssertionError, self.assertTupleEqual, None, tuple(b)) 282 self.assertRaises(AssertionError, self.assertSequenceEqual, None, tuple(b)) 283 self.assertRaises(AssertionError, self.assertListEqual, 1, 1) 284 self.assertRaises(AssertionError, self.assertTupleEqual, 1, 1) 285 self.assertRaises(AssertionError, self.assertSequenceEqual, 1, 1) 286 287 self.assertSameElements([1, 2, 3], [3, 2, 1]) 288 self.assertSameElements([1, 2] + [3] * 100, [1] * 100 + [2, 3]) 289 self.assertSameElements(['foo', 'bar', 'baz'], ['bar', 'baz', 'foo']) 290 self.assertRaises(AssertionError, self.assertSameElements, [10], [10, 11]) 291 self.assertRaises(AssertionError, self.assertSameElements, [10, 11], [10]) 292 293 # Test that sequences of unhashable objects can be tested for sameness: 294 self.assertSameElements([[1, 2], [3, 4]], [[3, 4], [1, 2]]) 295 self.assertRaises(AssertionError, self.assertSameElements, [[1]], [[2]]) 296 297 def test_assert_items_equal_hotfix(self): 298 """Confirm that http://bugs.python.org/issue14832 - b/10038517 is gone.""" 299 for assert_items_method in (self.assertItemsEqual, self.assertCountEqual): 300 with self.assertRaises(self.failureException) as error_context: 301 assert_items_method([4], [2]) 302 error_message = str(error_context.exception) 303 # Confirm that the bug is either no longer present in Python or that our 304 # assertItemsEqual patching version of the method in absltest.TestCase 305 # doesn't get used. 306 self.assertIn('First has 1, Second has 0: 4', error_message) 307 self.assertIn('First has 0, Second has 1: 2', error_message) 308 309 def test_assert_dict_equal(self): 310 self.assertDictEqual({}, {}) 311 312 c = {'x': 1} 313 d = {} 314 self.assertRaises(absltest.TestCase.failureException, 315 self.assertDictEqual, c, d) 316 317 d.update(c) 318 self.assertDictEqual(c, d) 319 320 d['x'] = 0 321 self.assertRaises(absltest.TestCase.failureException, 322 self.assertDictEqual, c, d, 'These are unequal') 323 324 self.assertRaises(AssertionError, self.assertDictEqual, None, d) 325 self.assertRaises(AssertionError, self.assertDictEqual, [], d) 326 self.assertRaises(AssertionError, self.assertDictEqual, 1, 1) 327 328 try: 329 # Ensure we use equality as the sole measure of elements, not type, since 330 # that is consistent with dict equality. 331 self.assertDictEqual({1: 1.0, 2: 2}, {1: 1, 2: 3}) 332 except AssertionError as e: 333 self.assertMultiLineEqual('{1: 1.0, 2: 2} != {1: 1, 2: 3}\n' 334 'repr() of differing entries:\n2: 2 != 3\n', 335 str(e)) 336 337 try: 338 self.assertDictEqual({}, {'x': 1}) 339 except AssertionError as e: 340 self.assertMultiLineEqual("{} != {'x': 1}\n" 341 "Unexpected, but present entries:\n'x': 1\n", 342 str(e)) 343 else: 344 self.fail('Expecting AssertionError') 345 346 try: 347 self.assertDictEqual({}, {'x': 1}, 'a message') 348 except AssertionError as e: 349 self.assertIn('a message', str(e)) 350 else: 351 self.fail('Expecting AssertionError') 352 353 expected = {'a': 1, 'b': 2, 'c': 3} 354 seen = {'a': 2, 'c': 3, 'd': 4} 355 try: 356 self.assertDictEqual(expected, seen) 357 except AssertionError as e: 358 self.assertMultiLineEqual("""\ 359{'a': 1, 'b': 2, 'c': 3} != {'a': 2, 'c': 3, 'd': 4} 360Unexpected, but present entries: 361'd': 4 362 363repr() of differing entries: 364'a': 1 != 2 365 366Missing entries: 367'b': 2 368""", str(e)) 369 else: 370 self.fail('Expecting AssertionError') 371 372 self.assertRaises(AssertionError, self.assertDictEqual, (1, 2), {}) 373 self.assertRaises(AssertionError, self.assertDictEqual, {}, (1, 2)) 374 375 # Ensure deterministic output of keys in dictionaries whose sort order 376 # doesn't match the lexical ordering of repr -- this is most Python objects, 377 # which are keyed by memory address. 378 class Obj(object): 379 380 def __init__(self, name): 381 self.name = name 382 383 def __repr__(self): 384 return self.name 385 386 try: 387 self.assertDictEqual( 388 {'a': Obj('A'), Obj('b'): Obj('B'), Obj('c'): Obj('C')}, 389 {'a': Obj('A'), Obj('d'): Obj('D'), Obj('e'): Obj('E')}) 390 except AssertionError as e: 391 # Do as best we can not to be misleading when objects have the same repr 392 # but aren't equal. 393 err_str = str(e) 394 self.assertStartsWith(err_str, 395 "{'a': A, b: B, c: C} != {'a': A, d: D, e: E}\n") 396 self.assertRegex( 397 err_str, r'(?ms).*^Unexpected, but present entries:\s+' 398 r'^(d: D$\s+^e: E|e: E$\s+^d: D)$') 399 self.assertRegex( 400 err_str, r'(?ms).*^repr\(\) of differing entries:\s+' 401 r'^.a.: A != A$', err_str) 402 self.assertRegex( 403 err_str, r'(?ms).*^Missing entries:\s+' 404 r'^(b: B$\s+^c: C|c: C$\s+^b: B)$') 405 else: 406 self.fail('Expecting AssertionError') 407 408 # Confirm that safe_repr, not repr, is being used. 409 class RaisesOnRepr(object): 410 411 def __repr__(self): 412 return 1/0 # Intentionally broken __repr__ implementation. 413 414 try: 415 self.assertDictEqual( 416 {RaisesOnRepr(): RaisesOnRepr()}, 417 {RaisesOnRepr(): RaisesOnRepr()} 418 ) 419 self.fail('Expected dicts not to match') 420 except AssertionError as e: 421 # Depending on the testing environment, the object may get a __main__ 422 # prefix or a absltest_test prefix, so strip that for comparison. 423 error_msg = re.sub( 424 r'( at 0x[^>]+)|__main__\.|absltest_test\.', '', str(e)) 425 self.assertRegex(error_msg, """(?m)\ 426{<.*RaisesOnRepr object.*>: <.*RaisesOnRepr object.*>} != \ 427{<.*RaisesOnRepr object.*>: <.*RaisesOnRepr object.*>} 428Unexpected, but present entries: 429<.*RaisesOnRepr object.*>: <.*RaisesOnRepr object.*> 430 431Missing entries: 432<.*RaisesOnRepr object.*>: <.*RaisesOnRepr object.*> 433""") 434 435 # Confirm that safe_repr, not repr, is being used. 436 class RaisesOnLt(object): 437 438 def __lt__(self, unused_other): 439 raise TypeError('Object is unordered.') 440 441 def __repr__(self): 442 return '<RaisesOnLt object>' 443 444 try: 445 self.assertDictEqual( 446 {RaisesOnLt(): RaisesOnLt()}, 447 {RaisesOnLt(): RaisesOnLt()}) 448 except AssertionError as e: 449 self.assertIn('Unexpected, but present entries:\n<RaisesOnLt', str(e)) 450 self.assertIn('Missing entries:\n<RaisesOnLt', str(e)) 451 452 def test_assert_set_equal(self): 453 set1 = set() 454 set2 = set() 455 self.assertSetEqual(set1, set2) 456 457 self.assertRaises(AssertionError, self.assertSetEqual, None, set2) 458 self.assertRaises(AssertionError, self.assertSetEqual, [], set2) 459 self.assertRaises(AssertionError, self.assertSetEqual, set1, None) 460 self.assertRaises(AssertionError, self.assertSetEqual, set1, []) 461 462 set1 = set(['a']) 463 set2 = set() 464 self.assertRaises(AssertionError, self.assertSetEqual, set1, set2) 465 466 set1 = set(['a']) 467 set2 = set(['a']) 468 self.assertSetEqual(set1, set2) 469 470 set1 = set(['a']) 471 set2 = set(['a', 'b']) 472 self.assertRaises(AssertionError, self.assertSetEqual, set1, set2) 473 474 set1 = set(['a']) 475 set2 = frozenset(['a', 'b']) 476 self.assertRaises(AssertionError, self.assertSetEqual, set1, set2) 477 478 set1 = set(['a', 'b']) 479 set2 = frozenset(['a', 'b']) 480 self.assertSetEqual(set1, set2) 481 482 set1 = set() 483 set2 = 'foo' 484 self.assertRaises(AssertionError, self.assertSetEqual, set1, set2) 485 self.assertRaises(AssertionError, self.assertSetEqual, set2, set1) 486 487 # make sure any string formatting is tuple-safe 488 set1 = set([(0, 1), (2, 3)]) 489 set2 = set([(4, 5)]) 490 self.assertRaises(AssertionError, self.assertSetEqual, set1, set2) 491 492 def test_assert_sequence_almost_equal(self): 493 actual = (1.1, 1.2, 1.4) 494 495 # Test across sequence types. 496 self.assertSequenceAlmostEqual((1.1, 1.2, 1.4), actual) 497 self.assertSequenceAlmostEqual([1.1, 1.2, 1.4], actual) 498 499 # Test sequence size mismatch. 500 with self.assertRaises(AssertionError): 501 self.assertSequenceAlmostEqual([1.1, 1.2], actual) 502 with self.assertRaises(AssertionError): 503 self.assertSequenceAlmostEqual([1.1, 1.2, 1.4, 1.5], actual) 504 505 # Test delta. 506 with self.assertRaises(AssertionError): 507 self.assertSequenceAlmostEqual((1.15, 1.15, 1.4), actual) 508 self.assertSequenceAlmostEqual((1.15, 1.15, 1.4), actual, delta=0.1) 509 510 # Test places. 511 with self.assertRaises(AssertionError): 512 self.assertSequenceAlmostEqual((1.1001, 1.2001, 1.3999), actual) 513 self.assertSequenceAlmostEqual((1.1001, 1.2001, 1.3999), actual, places=3) 514 515 def test_assert_contains_subset(self): 516 # sets, lists, tuples, dicts all ok. Types of set and subset do not have to 517 # match. 518 actual = ('a', 'b', 'c') 519 self.assertContainsSubset({'a', 'b'}, actual) 520 self.assertContainsSubset(('b', 'c'), actual) 521 self.assertContainsSubset({'b': 1, 'c': 2}, list(actual)) 522 self.assertContainsSubset(['c', 'a'], set(actual)) 523 self.assertContainsSubset([], set()) 524 self.assertContainsSubset([], {'a': 1}) 525 526 self.assertRaises(AssertionError, self.assertContainsSubset, ('d',), actual) 527 self.assertRaises(AssertionError, self.assertContainsSubset, ['d'], 528 set(actual)) 529 self.assertRaises(AssertionError, self.assertContainsSubset, {'a': 1}, []) 530 531 with self.assertRaisesRegex(AssertionError, 'Missing elements'): 532 self.assertContainsSubset({1, 2, 3}, {1, 2}) 533 534 with self.assertRaisesRegex( 535 AssertionError, 536 re.compile('Missing elements .* Custom message', re.DOTALL)): 537 self.assertContainsSubset({1, 2}, {1}, 'Custom message') 538 539 def test_assert_no_common_elements(self): 540 actual = ('a', 'b', 'c') 541 self.assertNoCommonElements((), actual) 542 self.assertNoCommonElements(('d', 'e'), actual) 543 self.assertNoCommonElements({'d', 'e'}, actual) 544 545 with self.assertRaisesRegex( 546 AssertionError, 547 re.compile('Common elements .* Custom message', re.DOTALL)): 548 self.assertNoCommonElements({1, 2}, {1}, 'Custom message') 549 550 with self.assertRaises(AssertionError): 551 self.assertNoCommonElements(['a'], actual) 552 553 with self.assertRaises(AssertionError): 554 self.assertNoCommonElements({'a', 'b', 'c'}, actual) 555 556 with self.assertRaises(AssertionError): 557 self.assertNoCommonElements({'b', 'c'}, set(actual)) 558 559 def test_assert_almost_equal(self): 560 self.assertAlmostEqual(1.00000001, 1.0) 561 self.assertNotAlmostEqual(1.0000001, 1.0) 562 563 def test_assert_almost_equals_with_delta(self): 564 self.assertAlmostEqual(3.14, 3, delta=0.2) 565 self.assertAlmostEqual(2.81, 3.14, delta=1) 566 self.assertAlmostEqual(-1, 1, delta=3) 567 self.assertRaises(AssertionError, self.assertAlmostEqual, 568 3.14, 2.81, delta=0.1) 569 self.assertRaises(AssertionError, self.assertAlmostEqual, 570 1, 2, delta=0.5) 571 self.assertNotAlmostEqual(3.14, 2.81, delta=0.1) 572 573 def test_assert_starts_with(self): 574 self.assertStartsWith('foobar', 'foo') 575 self.assertStartsWith('foobar', 'foobar') 576 msg = 'This is a useful message' 577 whole_msg = "'foobar' does not start with 'bar' : This is a useful message" 578 self.assertRaisesWithLiteralMatch(AssertionError, whole_msg, 579 self.assertStartsWith, 580 'foobar', 'bar', msg) 581 self.assertRaises(AssertionError, self.assertStartsWith, 'foobar', 'blah') 582 583 def test_assert_not_starts_with(self): 584 self.assertNotStartsWith('foobar', 'bar') 585 self.assertNotStartsWith('foobar', 'blah') 586 msg = 'This is a useful message' 587 whole_msg = "'foobar' does start with 'foo' : This is a useful message" 588 self.assertRaisesWithLiteralMatch(AssertionError, whole_msg, 589 self.assertNotStartsWith, 590 'foobar', 'foo', msg) 591 self.assertRaises(AssertionError, self.assertNotStartsWith, 'foobar', 592 'foobar') 593 594 def test_assert_ends_with(self): 595 self.assertEndsWith('foobar', 'bar') 596 self.assertEndsWith('foobar', 'foobar') 597 msg = 'This is a useful message' 598 whole_msg = "'foobar' does not end with 'foo' : This is a useful message" 599 self.assertRaisesWithLiteralMatch(AssertionError, whole_msg, 600 self.assertEndsWith, 601 'foobar', 'foo', msg) 602 self.assertRaises(AssertionError, self.assertEndsWith, 'foobar', 'blah') 603 604 def test_assert_not_ends_with(self): 605 self.assertNotEndsWith('foobar', 'foo') 606 self.assertNotEndsWith('foobar', 'blah') 607 msg = 'This is a useful message' 608 whole_msg = "'foobar' does end with 'bar' : This is a useful message" 609 self.assertRaisesWithLiteralMatch(AssertionError, whole_msg, 610 self.assertNotEndsWith, 611 'foobar', 'bar', msg) 612 self.assertRaises(AssertionError, self.assertNotEndsWith, 'foobar', 613 'foobar') 614 615 def test_assert_regex_backports(self): 616 self.assertRegex('regex', 'regex') 617 self.assertNotRegex('not-regex', 'no-match') 618 with self.assertRaisesRegex(ValueError, 'pattern'): 619 raise ValueError('pattern') 620 621 def test_assert_regex_match_matches(self): 622 self.assertRegexMatch('str', ['str']) 623 624 def test_assert_regex_match_matches_substring(self): 625 self.assertRegexMatch('pre-str-post', ['str']) 626 627 def test_assert_regex_match_multiple_regex_matches(self): 628 self.assertRegexMatch('str', ['rts', 'str']) 629 630 def test_assert_regex_match_empty_list_fails(self): 631 expected_re = re.compile(r'No regexes specified\.', re.MULTILINE) 632 633 with self.assertRaisesRegex(AssertionError, expected_re): 634 self.assertRegexMatch('str', regexes=[]) 635 636 def test_assert_regex_match_bad_arguments(self): 637 with self.assertRaisesRegex(AssertionError, 638 'regexes is string or bytes;.*'): 639 self.assertRegexMatch('1.*2', '1 2') 640 641 def test_assert_regex_match_unicode_vs_bytes(self): 642 """Ensure proper utf-8 encoding or decoding happens automatically.""" 643 self.assertRegexMatch(u'str', [b'str']) 644 self.assertRegexMatch(b'str', [u'str']) 645 646 def test_assert_regex_match_unicode(self): 647 self.assertRegexMatch(u'foo str', [u'str']) 648 649 def test_assert_regex_match_bytes(self): 650 self.assertRegexMatch(b'foo str', [b'str']) 651 652 def test_assert_regex_match_all_the_same_type(self): 653 with self.assertRaisesRegex(AssertionError, 'regexes .* same type'): 654 self.assertRegexMatch('foo str', [b'str', u'foo']) 655 656 def test_assert_command_fails_stderr(self): 657 tmpdir = tempfile.mkdtemp(dir=absltest.TEST_TMPDIR.value) 658 self.assertCommandFails( 659 ['cat', os.path.join(tmpdir, 'file.txt')], 660 ['No such file or directory'], 661 env=_env_for_command_tests()) 662 663 def test_assert_command_fails_with_list_of_string(self): 664 self.assertCommandFails( 665 ['false'], [''], env=_env_for_command_tests()) 666 667 def test_assert_command_fails_with_list_of_unicode_string(self): 668 self.assertCommandFails( 669 [u'false'], [''], env=_env_for_command_tests()) 670 671 def test_assert_command_fails_with_unicode_string(self): 672 self.assertCommandFails( 673 u'false', [u''], env=_env_for_command_tests()) 674 675 def test_assert_command_fails_with_unicode_string_bytes_regex(self): 676 self.assertCommandFails( 677 u'false', [b''], env=_env_for_command_tests()) 678 679 def test_assert_command_fails_with_message(self): 680 msg = 'This is a useful message' 681 expected_re = re.compile('The following command succeeded while expected to' 682 ' fail:.* This is a useful message', re.DOTALL) 683 684 with self.assertRaisesRegex(AssertionError, expected_re): 685 self.assertCommandFails( 686 [u'true'], [''], msg=msg, env=_env_for_command_tests()) 687 688 def test_assert_command_succeeds_stderr(self): 689 expected_re = re.compile('No such file or directory') 690 tmpdir = tempfile.mkdtemp(dir=absltest.TEST_TMPDIR.value) 691 692 with self.assertRaisesRegex(AssertionError, expected_re): 693 self.assertCommandSucceeds( 694 ['cat', os.path.join(tmpdir, 'file.txt')], 695 env=_env_for_command_tests()) 696 697 def test_assert_command_succeeds_with_matching_unicode_regexes(self): 698 self.assertCommandSucceeds( 699 ['echo', 'SUCCESS'], regexes=[u'SUCCESS'], 700 env=_env_for_command_tests()) 701 702 def test_assert_command_succeeds_with_matching_bytes_regexes(self): 703 self.assertCommandSucceeds( 704 ['echo', 'SUCCESS'], regexes=[b'SUCCESS'], 705 env=_env_for_command_tests()) 706 707 def test_assert_command_succeeds_with_non_matching_regexes(self): 708 expected_re = re.compile('Running command.* This is a useful message', 709 re.DOTALL) 710 msg = 'This is a useful message' 711 712 with self.assertRaisesRegex(AssertionError, expected_re): 713 self.assertCommandSucceeds( 714 ['echo', 'FAIL'], regexes=['SUCCESS'], msg=msg, 715 env=_env_for_command_tests()) 716 717 def test_assert_command_succeeds_with_list_of_string(self): 718 self.assertCommandSucceeds( 719 ['true'], env=_env_for_command_tests()) 720 721 def test_assert_command_succeeds_with_list_of_unicode_string(self): 722 self.assertCommandSucceeds( 723 [u'true'], env=_env_for_command_tests()) 724 725 def test_assert_command_succeeds_with_unicode_string(self): 726 self.assertCommandSucceeds( 727 u'true', env=_env_for_command_tests()) 728 729 def test_inequality(self): 730 # Try ints 731 self.assertGreater(2, 1) 732 self.assertGreaterEqual(2, 1) 733 self.assertGreaterEqual(1, 1) 734 self.assertLess(1, 2) 735 self.assertLessEqual(1, 2) 736 self.assertLessEqual(1, 1) 737 self.assertRaises(AssertionError, self.assertGreater, 1, 2) 738 self.assertRaises(AssertionError, self.assertGreater, 1, 1) 739 self.assertRaises(AssertionError, self.assertGreaterEqual, 1, 2) 740 self.assertRaises(AssertionError, self.assertLess, 2, 1) 741 self.assertRaises(AssertionError, self.assertLess, 1, 1) 742 self.assertRaises(AssertionError, self.assertLessEqual, 2, 1) 743 744 # Try Floats 745 self.assertGreater(1.1, 1.0) 746 self.assertGreaterEqual(1.1, 1.0) 747 self.assertGreaterEqual(1.0, 1.0) 748 self.assertLess(1.0, 1.1) 749 self.assertLessEqual(1.0, 1.1) 750 self.assertLessEqual(1.0, 1.0) 751 self.assertRaises(AssertionError, self.assertGreater, 1.0, 1.1) 752 self.assertRaises(AssertionError, self.assertGreater, 1.0, 1.0) 753 self.assertRaises(AssertionError, self.assertGreaterEqual, 1.0, 1.1) 754 self.assertRaises(AssertionError, self.assertLess, 1.1, 1.0) 755 self.assertRaises(AssertionError, self.assertLess, 1.0, 1.0) 756 self.assertRaises(AssertionError, self.assertLessEqual, 1.1, 1.0) 757 758 # Try Strings 759 self.assertGreater('bug', 'ant') 760 self.assertGreaterEqual('bug', 'ant') 761 self.assertGreaterEqual('ant', 'ant') 762 self.assertLess('ant', 'bug') 763 self.assertLessEqual('ant', 'bug') 764 self.assertLessEqual('ant', 'ant') 765 self.assertRaises(AssertionError, self.assertGreater, 'ant', 'bug') 766 self.assertRaises(AssertionError, self.assertGreater, 'ant', 'ant') 767 self.assertRaises(AssertionError, self.assertGreaterEqual, 'ant', 'bug') 768 self.assertRaises(AssertionError, self.assertLess, 'bug', 'ant') 769 self.assertRaises(AssertionError, self.assertLess, 'ant', 'ant') 770 self.assertRaises(AssertionError, self.assertLessEqual, 'bug', 'ant') 771 772 # Try Unicode 773 self.assertGreater(u'bug', u'ant') 774 self.assertGreaterEqual(u'bug', u'ant') 775 self.assertGreaterEqual(u'ant', u'ant') 776 self.assertLess(u'ant', u'bug') 777 self.assertLessEqual(u'ant', u'bug') 778 self.assertLessEqual(u'ant', u'ant') 779 self.assertRaises(AssertionError, self.assertGreater, u'ant', u'bug') 780 self.assertRaises(AssertionError, self.assertGreater, u'ant', u'ant') 781 self.assertRaises(AssertionError, self.assertGreaterEqual, u'ant', u'bug') 782 self.assertRaises(AssertionError, self.assertLess, u'bug', u'ant') 783 self.assertRaises(AssertionError, self.assertLess, u'ant', u'ant') 784 self.assertRaises(AssertionError, self.assertLessEqual, u'bug', u'ant') 785 786 # Try Mixed String/Unicode 787 self.assertGreater('bug', u'ant') 788 self.assertGreater(u'bug', 'ant') 789 self.assertGreaterEqual('bug', u'ant') 790 self.assertGreaterEqual(u'bug', 'ant') 791 self.assertGreaterEqual('ant', u'ant') 792 self.assertGreaterEqual(u'ant', 'ant') 793 self.assertLess('ant', u'bug') 794 self.assertLess(u'ant', 'bug') 795 self.assertLessEqual('ant', u'bug') 796 self.assertLessEqual(u'ant', 'bug') 797 self.assertLessEqual('ant', u'ant') 798 self.assertLessEqual(u'ant', 'ant') 799 self.assertRaises(AssertionError, self.assertGreater, 'ant', u'bug') 800 self.assertRaises(AssertionError, self.assertGreater, u'ant', 'bug') 801 self.assertRaises(AssertionError, self.assertGreater, 'ant', u'ant') 802 self.assertRaises(AssertionError, self.assertGreater, u'ant', 'ant') 803 self.assertRaises(AssertionError, self.assertGreaterEqual, 'ant', u'bug') 804 self.assertRaises(AssertionError, self.assertGreaterEqual, u'ant', 'bug') 805 self.assertRaises(AssertionError, self.assertLess, 'bug', u'ant') 806 self.assertRaises(AssertionError, self.assertLess, u'bug', 'ant') 807 self.assertRaises(AssertionError, self.assertLess, 'ant', u'ant') 808 self.assertRaises(AssertionError, self.assertLess, u'ant', 'ant') 809 self.assertRaises(AssertionError, self.assertLessEqual, 'bug', u'ant') 810 self.assertRaises(AssertionError, self.assertLessEqual, u'bug', 'ant') 811 812 def test_assert_multi_line_equal(self): 813 sample_text = """\ 814http://www.python.org/doc/2.3/lib/module-unittest.html 815test case 816 A test case is the smallest unit of testing. [...] 817""" 818 revised_sample_text = """\ 819http://www.python.org/doc/2.4.1/lib/module-unittest.html 820test case 821 A test case is the smallest unit of testing. [...] You may provide your 822 own implementation that does not subclass from TestCase, of course. 823""" 824 sample_text_error = """ 825- http://www.python.org/doc/2.3/lib/module-unittest.html 826? ^ 827+ http://www.python.org/doc/2.4.1/lib/module-unittest.html 828? ^^^ 829 test case 830- A test case is the smallest unit of testing. [...] 831+ A test case is the smallest unit of testing. [...] You may provide your 832? +++++++++++++++++++++ 833+ own implementation that does not subclass from TestCase, of course. 834""" 835 self.assertRaisesWithLiteralMatch(AssertionError, sample_text_error, 836 self.assertMultiLineEqual, 837 sample_text, 838 revised_sample_text) 839 840 self.assertRaises(AssertionError, self.assertMultiLineEqual, (1, 2), 'str') 841 self.assertRaises(AssertionError, self.assertMultiLineEqual, 'str', (1, 2)) 842 843 def test_assert_multi_line_equal_adds_newlines_if_needed(self): 844 self.assertRaisesWithLiteralMatch( 845 AssertionError, 846 '\n' 847 ' line1\n' 848 '- line2\n' 849 '? ^\n' 850 '+ line3\n' 851 '? ^\n', 852 self.assertMultiLineEqual, 853 'line1\n' 854 'line2', 855 'line1\n' 856 'line3') 857 858 def test_assert_multi_line_equal_shows_missing_newlines(self): 859 self.assertRaisesWithLiteralMatch( 860 AssertionError, 861 '\n' 862 ' line1\n' 863 '- line2\n' 864 '? -\n' 865 '+ line2\n', 866 self.assertMultiLineEqual, 867 'line1\n' 868 'line2\n', 869 'line1\n' 870 'line2') 871 872 def test_assert_multi_line_equal_shows_extra_newlines(self): 873 self.assertRaisesWithLiteralMatch( 874 AssertionError, 875 '\n' 876 ' line1\n' 877 '- line2\n' 878 '+ line2\n' 879 '? +\n', 880 self.assertMultiLineEqual, 881 'line1\n' 882 'line2', 883 'line1\n' 884 'line2\n') 885 886 def test_assert_multi_line_equal_line_limit_limits(self): 887 self.assertRaisesWithLiteralMatch( 888 AssertionError, 889 '\n' 890 ' line1\n' 891 '(... and 4 more delta lines omitted for brevity.)\n', 892 self.assertMultiLineEqual, 893 'line1\n' 894 'line2\n', 895 'line1\n' 896 'line3\n', 897 line_limit=1) 898 899 def test_assert_multi_line_equal_line_limit_limits_with_message(self): 900 self.assertRaisesWithLiteralMatch( 901 AssertionError, 902 'Prefix:\n' 903 ' line1\n' 904 '(... and 4 more delta lines omitted for brevity.)\n', 905 self.assertMultiLineEqual, 906 'line1\n' 907 'line2\n', 908 'line1\n' 909 'line3\n', 910 'Prefix', 911 line_limit=1) 912 913 def test_assert_is_none(self): 914 self.assertIsNone(None) 915 self.assertRaises(AssertionError, self.assertIsNone, False) 916 self.assertIsNotNone('Google') 917 self.assertRaises(AssertionError, self.assertIsNotNone, None) 918 self.assertRaises(AssertionError, self.assertIsNone, (1, 2)) 919 920 def test_assert_is(self): 921 self.assertIs(object, object) 922 self.assertRaises(AssertionError, self.assertIsNot, object, object) 923 self.assertIsNot(True, False) 924 self.assertRaises(AssertionError, self.assertIs, True, False) 925 926 def test_assert_between(self): 927 self.assertBetween(3.14, 3.1, 3.141) 928 self.assertBetween(4, 4, 1e10000) 929 self.assertBetween(9.5, 9.4, 9.5) 930 self.assertBetween(-1e10, -1e10000, 0) 931 self.assertRaises(AssertionError, self.assertBetween, 9.4, 9.3, 9.3999) 932 self.assertRaises(AssertionError, self.assertBetween, -1e10000, -1e10, 0) 933 934 def test_assert_raises_with_predicate_match_no_raise(self): 935 with self.assertRaisesRegex(AssertionError, '^Exception not raised$'): 936 self.assertRaisesWithPredicateMatch(Exception, 937 lambda e: True, 938 lambda: 1) # don't raise 939 940 with self.assertRaisesRegex(AssertionError, '^Exception not raised$'): 941 with self.assertRaisesWithPredicateMatch(Exception, lambda e: True): 942 pass # don't raise 943 944 def test_assert_raises_with_predicate_match_raises_wrong_exception(self): 945 def _raise_value_error(): 946 raise ValueError 947 948 with self.assertRaises(ValueError): 949 self.assertRaisesWithPredicateMatch(IOError, 950 lambda e: True, 951 _raise_value_error) 952 953 with self.assertRaises(ValueError): 954 with self.assertRaisesWithPredicateMatch(IOError, lambda e: True): 955 raise ValueError 956 957 def test_assert_raises_with_predicate_match_predicate_fails(self): 958 def _raise_value_error(): 959 raise ValueError 960 with self.assertRaisesRegex(AssertionError, ' does not match predicate '): 961 self.assertRaisesWithPredicateMatch(ValueError, 962 lambda e: False, 963 _raise_value_error) 964 965 with self.assertRaisesRegex(AssertionError, ' does not match predicate '): 966 with self.assertRaisesWithPredicateMatch(ValueError, lambda e: False): 967 raise ValueError 968 969 def test_assert_raises_with_predicate_match_predicate_passes(self): 970 def _raise_value_error(): 971 raise ValueError 972 973 self.assertRaisesWithPredicateMatch(ValueError, 974 lambda e: True, 975 _raise_value_error) 976 977 with self.assertRaisesWithPredicateMatch(ValueError, lambda e: True): 978 raise ValueError 979 980 def test_assert_raises_with_predicate_match_exception_captured(self): 981 def _raise_value_error(): 982 raise ValueError 983 984 predicate = lambda e: e is not None 985 with self.assertRaisesWithPredicateMatch(ValueError, predicate) as ctx_mgr: 986 _raise_value_error() 987 988 expected = getattr(ctx_mgr, 'exception', None) 989 self.assertIsInstance(expected, ValueError) 990 991 def test_assert_raises_with_literal_match_exception_captured(self): 992 message = 'some value error' 993 def _raise_value_error(): 994 raise ValueError(message) 995 996 # predicate = lambda e: e is not None 997 with self.assertRaisesWithLiteralMatch(ValueError, message) as ctx_mgr: 998 _raise_value_error() 999 1000 expected = getattr(ctx_mgr, 'exception', None) 1001 self.assertIsInstance(expected, ValueError) 1002 1003 def test_assert_contains_in_order(self): 1004 # Valids 1005 self.assertContainsInOrder( 1006 ['fox', 'dog'], 'The quick brown fox jumped over the lazy dog.') 1007 self.assertContainsInOrder( 1008 ['quick', 'fox', 'dog'], 1009 'The quick brown fox jumped over the lazy dog.') 1010 self.assertContainsInOrder( 1011 ['The', 'fox', 'dog.'], 'The quick brown fox jumped over the lazy dog.') 1012 self.assertContainsInOrder( 1013 ['fox'], 'The quick brown fox jumped over the lazy dog.') 1014 self.assertContainsInOrder( 1015 'fox', 'The quick brown fox jumped over the lazy dog.') 1016 self.assertContainsInOrder( 1017 ['fox', 'dog'], 'fox dog fox') 1018 self.assertContainsInOrder( 1019 [], 'The quick brown fox jumped over the lazy dog.') 1020 self.assertContainsInOrder( 1021 [], '') 1022 1023 # Invalids 1024 msg = 'This is a useful message' 1025 whole_msg = ("Did not find 'fox' after 'dog' in 'The quick brown fox" 1026 " jumped over the lazy dog' : This is a useful message") 1027 self.assertRaisesWithLiteralMatch( 1028 AssertionError, whole_msg, self.assertContainsInOrder, 1029 ['dog', 'fox'], 'The quick brown fox jumped over the lazy dog', msg=msg) 1030 self.assertRaises( 1031 AssertionError, self.assertContainsInOrder, 1032 ['The', 'dog', 'fox'], 'The quick brown fox jumped over the lazy dog') 1033 self.assertRaises( 1034 AssertionError, self.assertContainsInOrder, ['dog'], '') 1035 1036 def test_assert_contains_subsequence_for_numbers(self): 1037 self.assertContainsSubsequence([1, 2, 3], [1]) 1038 self.assertContainsSubsequence([1, 2, 3], [1, 2]) 1039 self.assertContainsSubsequence([1, 2, 3], [1, 3]) 1040 1041 with self.assertRaises(AssertionError): 1042 self.assertContainsSubsequence([1, 2, 3], [4]) 1043 msg = 'This is a useful message' 1044 whole_msg = ('[3, 1] not a subsequence of [1, 2, 3]. ' 1045 'First non-matching element: 1 : This is a useful message') 1046 self.assertRaisesWithLiteralMatch(AssertionError, whole_msg, 1047 self.assertContainsSubsequence, 1048 [1, 2, 3], [3, 1], msg=msg) 1049 1050 def test_assert_contains_subsequence_for_strings(self): 1051 self.assertContainsSubsequence(['foo', 'bar', 'blorp'], ['foo', 'blorp']) 1052 with self.assertRaises(AssertionError): 1053 self.assertContainsSubsequence( 1054 ['foo', 'bar', 'blorp'], ['blorp', 'foo']) 1055 1056 def test_assert_contains_subsequence_with_empty_subsequence(self): 1057 self.assertContainsSubsequence([1, 2, 3], []) 1058 self.assertContainsSubsequence(['foo', 'bar', 'blorp'], []) 1059 self.assertContainsSubsequence([], []) 1060 1061 def test_assert_contains_subsequence_with_empty_container(self): 1062 with self.assertRaises(AssertionError): 1063 self.assertContainsSubsequence([], [1]) 1064 with self.assertRaises(AssertionError): 1065 self.assertContainsSubsequence([], ['foo']) 1066 1067 def test_assert_contains_exact_subsequence_for_numbers(self): 1068 self.assertContainsExactSubsequence([1, 2, 3], [1]) 1069 self.assertContainsExactSubsequence([1, 2, 3], [1, 2]) 1070 self.assertContainsExactSubsequence([1, 2, 3], [2, 3]) 1071 1072 with self.assertRaises(AssertionError): 1073 self.assertContainsExactSubsequence([1, 2, 3], [4]) 1074 msg = 'This is a useful message' 1075 whole_msg = ('[1, 2, 4] not an exact subsequence of [1, 2, 3, 4]. ' 1076 'Longest matching prefix: [1, 2] : This is a useful message') 1077 self.assertRaisesWithLiteralMatch(AssertionError, whole_msg, 1078 self.assertContainsExactSubsequence, 1079 [1, 2, 3, 4], [1, 2, 4], msg=msg) 1080 1081 def test_assert_contains_exact_subsequence_for_strings(self): 1082 self.assertContainsExactSubsequence( 1083 ['foo', 'bar', 'blorp'], ['foo', 'bar']) 1084 with self.assertRaises(AssertionError): 1085 self.assertContainsExactSubsequence( 1086 ['foo', 'bar', 'blorp'], ['blorp', 'foo']) 1087 1088 def test_assert_contains_exact_subsequence_with_empty_subsequence(self): 1089 self.assertContainsExactSubsequence([1, 2, 3], []) 1090 self.assertContainsExactSubsequence(['foo', 'bar', 'blorp'], []) 1091 self.assertContainsExactSubsequence([], []) 1092 1093 def test_assert_contains_exact_subsequence_with_empty_container(self): 1094 with self.assertRaises(AssertionError): 1095 self.assertContainsExactSubsequence([], [3]) 1096 with self.assertRaises(AssertionError): 1097 self.assertContainsExactSubsequence([], ['foo', 'bar']) 1098 self.assertContainsExactSubsequence([], []) 1099 1100 def test_assert_totally_ordered(self): 1101 # Valid. 1102 self.assertTotallyOrdered() 1103 self.assertTotallyOrdered([1]) 1104 self.assertTotallyOrdered([1], [2]) 1105 self.assertTotallyOrdered([1, 1, 1]) 1106 self.assertTotallyOrdered([(1, 1)], [(1, 2)], [(2, 1)]) 1107 1108 # From the docstring. 1109 class A(object): 1110 1111 def __init__(self, x, y): 1112 self.x = x 1113 self.y = y 1114 1115 def __hash__(self): 1116 return hash(self.x) 1117 1118 def __repr__(self): 1119 return 'A(%r, %r)' % (self.x, self.y) 1120 1121 def __eq__(self, other): 1122 try: 1123 return self.x == other.x 1124 except AttributeError: 1125 return NotImplemented 1126 1127 def __ne__(self, other): 1128 try: 1129 return self.x != other.x 1130 except AttributeError: 1131 return NotImplemented 1132 1133 def __lt__(self, other): 1134 try: 1135 return self.x < other.x 1136 except AttributeError: 1137 return NotImplemented 1138 1139 def __le__(self, other): 1140 try: 1141 return self.x <= other.x 1142 except AttributeError: 1143 return NotImplemented 1144 1145 def __gt__(self, other): 1146 try: 1147 return self.x > other.x 1148 except AttributeError: 1149 return NotImplemented 1150 1151 def __ge__(self, other): 1152 try: 1153 return self.x >= other.x 1154 except AttributeError: 1155 return NotImplemented 1156 1157 class B(A): 1158 """Like A, but not hashable.""" 1159 __hash__ = None 1160 1161 self.assertTotallyOrdered( 1162 [A(1, 'a')], 1163 [A(2, 'b')], # 2 is after 1. 1164 [ 1165 A(3, 'c'), 1166 B(3, 'd'), 1167 B(3, 'e') # The second argument is irrelevant. 1168 ], 1169 [A(4, 'z')]) 1170 1171 # Invalid. 1172 msg = 'This is a useful message' 1173 whole_msg = '2 not less than 1 : This is a useful message' 1174 self.assertRaisesWithLiteralMatch(AssertionError, whole_msg, 1175 self.assertTotallyOrdered, [2], [1], 1176 msg=msg) 1177 self.assertRaises(AssertionError, self.assertTotallyOrdered, [2], [1]) 1178 self.assertRaises(AssertionError, self.assertTotallyOrdered, [2], [1], [3]) 1179 self.assertRaises(AssertionError, self.assertTotallyOrdered, [1, 2]) 1180 1181 def test_short_description_without_docstring(self): 1182 self.assertEqual( 1183 self.shortDescription(), 1184 'TestCaseTest.test_short_description_without_docstring', 1185 ) 1186 1187 def test_short_description_with_one_line_docstring(self): 1188 """Tests shortDescription() for a method with a docstring.""" 1189 self.assertEqual( 1190 self.shortDescription(), 1191 'TestCaseTest.test_short_description_with_one_line_docstring\n' 1192 'Tests shortDescription() for a method with a docstring.', 1193 ) 1194 1195 def test_short_description_with_multi_line_docstring(self): 1196 """Tests shortDescription() for a method with a longer docstring. 1197 1198 This method ensures that only the first line of a docstring is 1199 returned used in the short description, no matter how long the 1200 whole thing is. 1201 """ 1202 self.assertEqual( 1203 self.shortDescription(), 1204 'TestCaseTest.test_short_description_with_multi_line_docstring\n' 1205 'Tests shortDescription() for a method with a longer docstring.', 1206 ) 1207 1208 def test_assert_url_equal_same(self): 1209 self.assertUrlEqual('http://a', 'http://a') 1210 self.assertUrlEqual('http://a/path/test', 'http://a/path/test') 1211 self.assertUrlEqual('#fragment', '#fragment') 1212 self.assertUrlEqual('http://a/?q=1', 'http://a/?q=1') 1213 self.assertUrlEqual('http://a/?q=1&v=5', 'http://a/?v=5&q=1') 1214 self.assertUrlEqual('/logs?v=1&a=2&t=labels&f=path%3A%22foo%22', 1215 '/logs?a=2&f=path%3A%22foo%22&v=1&t=labels') 1216 self.assertUrlEqual('http://a/path;p1', 'http://a/path;p1') 1217 self.assertUrlEqual('http://a/path;p2;p3;p1', 'http://a/path;p1;p2;p3') 1218 self.assertUrlEqual('sip:[email protected];maddr=239.255.255.1;ttl=15', 1219 'sip:[email protected];ttl=15;maddr=239.255.255.1') 1220 self.assertUrlEqual('http://nyan/cat?p=1&b=', 'http://nyan/cat?b=&p=1') 1221 1222 def test_assert_url_equal_different(self): 1223 msg = 'This is a useful message' 1224 whole_msg = 'This is a useful message:\n- a\n+ b\n' 1225 self.assertRaisesWithLiteralMatch(AssertionError, whole_msg, 1226 self.assertUrlEqual, 1227 'http://a', 'http://b', msg=msg) 1228 self.assertRaises(AssertionError, self.assertUrlEqual, 1229 'http://a/x', 'http://a:8080/x') 1230 self.assertRaises(AssertionError, self.assertUrlEqual, 1231 'http://a/x', 'http://a/y') 1232 self.assertRaises(AssertionError, self.assertUrlEqual, 1233 'http://a/?q=2', 'http://a/?q=1') 1234 self.assertRaises(AssertionError, self.assertUrlEqual, 1235 'http://a/?q=1&v=5', 'http://a/?v=2&q=1') 1236 self.assertRaises(AssertionError, self.assertUrlEqual, 1237 'http://a', 'sip://b') 1238 self.assertRaises(AssertionError, self.assertUrlEqual, 1239 'http://a#g', 'sip://a#f') 1240 self.assertRaises(AssertionError, self.assertUrlEqual, 1241 'http://a/path;p1;p3;p1', 'http://a/path;p1;p2;p3') 1242 self.assertRaises(AssertionError, self.assertUrlEqual, 1243 'http://nyan/cat?p=1&b=', 'http://nyan/cat?p=1') 1244 1245 def test_same_structure_same(self): 1246 self.assertSameStructure(0, 0) 1247 self.assertSameStructure(1, 1) 1248 self.assertSameStructure('', '') 1249 self.assertSameStructure('hello', 'hello', msg='This Should not fail') 1250 self.assertSameStructure(set(), set()) 1251 self.assertSameStructure(set([1, 2]), set([1, 2])) 1252 self.assertSameStructure(set(), frozenset()) 1253 self.assertSameStructure(set([1, 2]), frozenset([1, 2])) 1254 self.assertSameStructure([], []) 1255 self.assertSameStructure(['a'], ['a']) 1256 self.assertSameStructure([], ()) 1257 self.assertSameStructure(['a'], ('a',)) 1258 self.assertSameStructure({}, {}) 1259 self.assertSameStructure({'one': 1}, {'one': 1}) 1260 self.assertSameStructure(collections.defaultdict(None, {'one': 1}), 1261 {'one': 1}) 1262 self.assertSameStructure(collections.OrderedDict({'one': 1}), 1263 collections.defaultdict(None, {'one': 1})) 1264 1265 def test_same_structure_different(self): 1266 # Different type 1267 with self.assertRaisesRegex( 1268 AssertionError, 1269 r"a is a <(type|class) 'int'> but b is a <(type|class) 'str'>"): 1270 self.assertSameStructure(0, 'hello') 1271 with self.assertRaisesRegex( 1272 AssertionError, 1273 r"a is a <(type|class) 'int'> but b is a <(type|class) 'list'>"): 1274 self.assertSameStructure(0, []) 1275 with self.assertRaisesRegex( 1276 AssertionError, 1277 r"a is a <(type|class) 'int'> but b is a <(type|class) 'float'>"): 1278 self.assertSameStructure(2, 2.0) 1279 1280 with self.assertRaisesRegex( 1281 AssertionError, 1282 r"a is a <(type|class) 'list'> but b is a <(type|class) 'dict'>"): 1283 self.assertSameStructure([], {}) 1284 1285 with self.assertRaisesRegex( 1286 AssertionError, 1287 r"a is a <(type|class) 'list'> but b is a <(type|class) 'set'>"): 1288 self.assertSameStructure([], set()) 1289 1290 with self.assertRaisesRegex( 1291 AssertionError, 1292 r"a is a <(type|class) 'dict'> but b is a <(type|class) 'set'>"): 1293 self.assertSameStructure({}, set()) 1294 1295 # Different scalar values 1296 self.assertRaisesWithLiteralMatch( 1297 AssertionError, 'a is 0 but b is 1', 1298 self.assertSameStructure, 0, 1) 1299 self.assertRaisesWithLiteralMatch( 1300 AssertionError, "a is 'hello' but b is 'goodbye' : This was expected", 1301 self.assertSameStructure, 'hello', 'goodbye', msg='This was expected') 1302 1303 # Different sets 1304 self.assertRaisesWithLiteralMatch( 1305 AssertionError, 1306 r'AA has 2 but BB does not', 1307 self.assertSameStructure, 1308 set([1, 2]), 1309 set([1]), 1310 aname='AA', 1311 bname='BB') 1312 self.assertRaisesWithLiteralMatch( 1313 AssertionError, 1314 r'AA lacks 2 but BB has it', 1315 self.assertSameStructure, 1316 set([1]), 1317 set([1, 2]), 1318 aname='AA', 1319 bname='BB') 1320 1321 # Different lists 1322 self.assertRaisesWithLiteralMatch( 1323 AssertionError, "a has [2] with value 'z' but b does not", 1324 self.assertSameStructure, ['x', 'y', 'z'], ['x', 'y']) 1325 self.assertRaisesWithLiteralMatch( 1326 AssertionError, "a lacks [2] but b has it with value 'z'", 1327 self.assertSameStructure, ['x', 'y'], ['x', 'y', 'z']) 1328 self.assertRaisesWithLiteralMatch( 1329 AssertionError, "a[2] is 'z' but b[2] is 'Z'", 1330 self.assertSameStructure, ['x', 'y', 'z'], ['x', 'y', 'Z']) 1331 1332 # Different dicts 1333 self.assertRaisesWithLiteralMatch( 1334 AssertionError, "a has ['two'] with value 2 but it's missing in b", 1335 self.assertSameStructure, {'one': 1, 'two': 2}, {'one': 1}) 1336 self.assertRaisesWithLiteralMatch( 1337 AssertionError, "a lacks ['two'] but b has it with value 2", 1338 self.assertSameStructure, {'one': 1}, {'one': 1, 'two': 2}) 1339 self.assertRaisesWithLiteralMatch( 1340 AssertionError, "a['two'] is 2 but b['two'] is 3", 1341 self.assertSameStructure, {'one': 1, 'two': 2}, {'one': 1, 'two': 3}) 1342 1343 # String and byte types should not be considered equivalent to other 1344 # sequences 1345 self.assertRaisesRegex( 1346 AssertionError, 1347 r"a is a <(type|class) 'list'> but b is a <(type|class) 'str'>", 1348 self.assertSameStructure, [], '') 1349 self.assertRaisesRegex( 1350 AssertionError, 1351 r"a is a <(type|class) 'str'> but b is a <(type|class) 'tuple'>", 1352 self.assertSameStructure, '', ()) 1353 self.assertRaisesRegex( 1354 AssertionError, 1355 r"a is a <(type|class) 'list'> but b is a <(type|class) 'str'>", 1356 self.assertSameStructure, ['a', 'b', 'c'], 'abc') 1357 self.assertRaisesRegex( 1358 AssertionError, 1359 r"a is a <(type|class) 'str'> but b is a <(type|class) 'tuple'>", 1360 self.assertSameStructure, 'abc', ('a', 'b', 'c')) 1361 1362 # Deep key generation 1363 self.assertRaisesWithLiteralMatch( 1364 AssertionError, 1365 "a[0][0]['x']['y']['z'][0] is 1 but b[0][0]['x']['y']['z'][0] is 2", 1366 self.assertSameStructure, 1367 [[{'x': {'y': {'z': [1]}}}]], [[{'x': {'y': {'z': [2]}}}]]) 1368 1369 # Multiple problems 1370 self.assertRaisesWithLiteralMatch( 1371 AssertionError, 1372 'a[0] is 1 but b[0] is 3; a[1] is 2 but b[1] is 4', 1373 self.assertSameStructure, [1, 2], [3, 4]) 1374 with self.assertRaisesRegex( 1375 AssertionError, 1376 re.compile(r"^a\[0] is 'a' but b\[0] is 'A'; .*" 1377 r"a\[18] is 's' but b\[18] is 'S'; \.\.\.$")): 1378 self.assertSameStructure( 1379 list(string.ascii_lowercase), list(string.ascii_uppercase)) 1380 1381 # Verify same behavior with self.maxDiff = None 1382 self.maxDiff = None 1383 self.assertRaisesWithLiteralMatch( 1384 AssertionError, 1385 'a[0] is 1 but b[0] is 3; a[1] is 2 but b[1] is 4', 1386 self.assertSameStructure, [1, 2], [3, 4]) 1387 1388 def test_same_structure_mapping_unchanged(self): 1389 default_a = collections.defaultdict(lambda: 'BAD MODIFICATION', {}) 1390 dict_b = {'one': 'z'} 1391 self.assertRaisesWithLiteralMatch( 1392 AssertionError, 1393 r"a lacks ['one'] but b has it with value 'z'", 1394 self.assertSameStructure, default_a, dict_b) 1395 self.assertEmpty(default_a) 1396 1397 dict_a = {'one': 'z'} 1398 default_b = collections.defaultdict(lambda: 'BAD MODIFICATION', {}) 1399 self.assertRaisesWithLiteralMatch( 1400 AssertionError, 1401 r"a has ['one'] with value 'z' but it's missing in b", 1402 self.assertSameStructure, dict_a, default_b) 1403 self.assertEmpty(default_b) 1404 1405 def test_same_structure_uses_type_equality_func_for_leaves(self): 1406 class CustomLeaf(object): 1407 def __init__(self, n): 1408 self.n = n 1409 1410 def __repr__(self): 1411 return f'CustomLeaf({self.n})' 1412 1413 def assert_custom_leaf_equal(a, b, msg): 1414 del msg 1415 assert a.n % 5 == b.n % 5 1416 self.addTypeEqualityFunc(CustomLeaf, assert_custom_leaf_equal) 1417 1418 self.assertSameStructure(CustomLeaf(4), CustomLeaf(9)) 1419 self.assertRaisesWithLiteralMatch( 1420 AssertionError, 1421 r'a is CustomLeaf(4) but b is CustomLeaf(8)', 1422 self.assertSameStructure, CustomLeaf(4), CustomLeaf(8), 1423 ) 1424 1425 def test_assert_json_equal_same(self): 1426 self.assertJsonEqual('{"success": true}', '{"success": true}') 1427 self.assertJsonEqual('{"success": true}', '{"success":true}') 1428 self.assertJsonEqual('true', 'true') 1429 self.assertJsonEqual('null', 'null') 1430 self.assertJsonEqual('false', 'false') 1431 self.assertJsonEqual('34', '34') 1432 self.assertJsonEqual('[1, 2, 3]', '[1,2,3]', msg='please PASS') 1433 self.assertJsonEqual('{"sequence": [1, 2, 3], "float": 23.42}', 1434 '{"float": 23.42, "sequence": [1,2,3]}') 1435 self.assertJsonEqual('{"nest": {"spam": "eggs"}, "float": 23.42}', 1436 '{"float": 23.42, "nest": {"spam":"eggs"}}') 1437 1438 def test_assert_json_equal_different(self): 1439 with self.assertRaises(AssertionError): 1440 self.assertJsonEqual('{"success": true}', '{"success": false}') 1441 with self.assertRaises(AssertionError): 1442 self.assertJsonEqual('{"success": false}', '{"Success": false}') 1443 with self.assertRaises(AssertionError): 1444 self.assertJsonEqual('false', 'true') 1445 with self.assertRaises(AssertionError) as error_context: 1446 self.assertJsonEqual('null', '0', msg='I demand FAILURE') 1447 self.assertIn('I demand FAILURE', error_context.exception.args[0]) 1448 self.assertIn('None', error_context.exception.args[0]) 1449 with self.assertRaises(AssertionError): 1450 self.assertJsonEqual('[1, 0, 3]', '[1,2,3]') 1451 with self.assertRaises(AssertionError): 1452 self.assertJsonEqual('{"sequence": [1, 2, 3], "float": 23.42}', 1453 '{"float": 23.42, "sequence": [1,0,3]}') 1454 with self.assertRaises(AssertionError): 1455 self.assertJsonEqual('{"nest": {"spam": "eggs"}, "float": 23.42}', 1456 '{"float": 23.42, "nest": {"Spam":"beans"}}') 1457 1458 def test_assert_json_equal_bad_json(self): 1459 with self.assertRaises(ValueError) as error_context: 1460 self.assertJsonEqual("alhg'2;#", '{"a": true}') 1461 self.assertIn('first', error_context.exception.args[0]) 1462 self.assertIn('alhg', error_context.exception.args[0]) 1463 1464 with self.assertRaises(ValueError) as error_context: 1465 self.assertJsonEqual('{"a": true}', "alhg'2;#") 1466 self.assertIn('second', error_context.exception.args[0]) 1467 self.assertIn('alhg', error_context.exception.args[0]) 1468 1469 with self.assertRaises(ValueError) as error_context: 1470 self.assertJsonEqual('', '') 1471 1472 1473class GetCommandStderrTestCase(absltest.TestCase): 1474 1475 def test_return_status(self): 1476 tmpdir = tempfile.mkdtemp(dir=absltest.TEST_TMPDIR.value) 1477 returncode = ( 1478 absltest.get_command_stderr( 1479 ['cat', os.path.join(tmpdir, 'file.txt')], 1480 env=_env_for_command_tests())[0]) 1481 self.assertEqual(1, returncode) 1482 1483 def test_stderr(self): 1484 tmpdir = tempfile.mkdtemp(dir=absltest.TEST_TMPDIR.value) 1485 stderr = ( 1486 absltest.get_command_stderr( 1487 ['cat', os.path.join(tmpdir, 'file.txt')], 1488 env=_env_for_command_tests())[1]) 1489 stderr = stderr.decode('utf-8') 1490 self.assertRegex(stderr, 'No such file or directory') 1491 1492 1493@contextlib.contextmanager 1494def cm_for_test(obj): 1495 try: 1496 obj.cm_state = 'yielded' 1497 yield 'value' 1498 finally: 1499 obj.cm_state = 'exited' 1500 1501 1502class EnterContextTest(absltest.TestCase): 1503 1504 def setUp(self): 1505 self.cm_state = 'unset' 1506 self.cm_value = 'unset' 1507 1508 def assert_cm_exited(): 1509 self.assertEqual(self.cm_state, 'exited') 1510 1511 # Because cleanup functions are run in reverse order, we have to add 1512 # our assert-cleanup before the exit stack registers its own cleanup. 1513 # This ensures we see state after the stack cleanup runs. 1514 self.addCleanup(assert_cm_exited) 1515 1516 super(EnterContextTest, self).setUp() 1517 self.cm_value = self.enter_context(cm_for_test(self)) 1518 1519 def test_enter_context(self): 1520 self.assertEqual(self.cm_value, 'value') 1521 self.assertEqual(self.cm_state, 'yielded') 1522 1523 1524@absltest.skipIf(not hasattr(absltest.TestCase, 'addClassCleanup'), 1525 'Python 3.8 required for class-level enter_context') 1526class EnterContextClassmethodTest(absltest.TestCase): 1527 1528 cm_state = 'unset' 1529 cm_value = 'unset' 1530 1531 @classmethod 1532 def setUpClass(cls): 1533 1534 def assert_cm_exited(): 1535 assert cls.cm_state == 'exited' 1536 1537 # Because cleanup functions are run in reverse order, we have to add 1538 # our assert-cleanup before the exit stack registers its own cleanup. 1539 # This ensures we see state after the stack cleanup runs. 1540 cls.addClassCleanup(assert_cm_exited) 1541 1542 super(EnterContextClassmethodTest, cls).setUpClass() 1543 cls.cm_value = cls.enter_context(cm_for_test(cls)) 1544 1545 def test_enter_context(self): 1546 self.assertEqual(self.cm_value, 'value') 1547 self.assertEqual(self.cm_state, 'yielded') 1548 1549 1550class EqualityAssertionTest(absltest.TestCase): 1551 """This test verifies that absltest.failIfEqual actually tests __ne__. 1552 1553 If a user class implements __eq__, unittest.assertEqual will call it 1554 via first == second. However, failIfEqual also calls 1555 first == second. This means that while the caller may believe 1556 their __ne__ method is being tested, it is not. 1557 """ 1558 1559 class NeverEqual(object): 1560 """Objects of this class behave like NaNs.""" 1561 1562 def __eq__(self, unused_other): 1563 return False 1564 1565 def __ne__(self, unused_other): 1566 return False 1567 1568 class AllSame(object): 1569 """All objects of this class compare as equal.""" 1570 1571 def __eq__(self, unused_other): 1572 return True 1573 1574 def __ne__(self, unused_other): 1575 return False 1576 1577 class EqualityTestsWithEq(object): 1578 """Performs all equality and inequality tests with __eq__.""" 1579 1580 def __init__(self, value): 1581 self._value = value 1582 1583 def __eq__(self, other): 1584 return self._value == other._value 1585 1586 def __ne__(self, other): 1587 return not self.__eq__(other) 1588 1589 class EqualityTestsWithNe(object): 1590 """Performs all equality and inequality tests with __ne__.""" 1591 1592 def __init__(self, value): 1593 self._value = value 1594 1595 def __eq__(self, other): 1596 return not self.__ne__(other) 1597 1598 def __ne__(self, other): 1599 return self._value != other._value 1600 1601 class EqualityTestsWithCmp(object): 1602 1603 def __init__(self, value): 1604 self._value = value 1605 1606 def __cmp__(self, other): 1607 return cmp(self._value, other._value) 1608 1609 class EqualityTestsWithLtEq(object): 1610 1611 def __init__(self, value): 1612 self._value = value 1613 1614 def __eq__(self, other): 1615 return self._value == other._value 1616 1617 def __lt__(self, other): 1618 return self._value < other._value 1619 1620 def test_all_comparisons_fail(self): 1621 i1 = self.NeverEqual() 1622 i2 = self.NeverEqual() 1623 self.assertFalse(i1 == i2) 1624 self.assertFalse(i1 != i2) 1625 1626 # Compare two distinct objects 1627 self.assertFalse(i1 is i2) 1628 self.assertRaises(AssertionError, self.assertEqual, i1, i2) 1629 self.assertRaises(AssertionError, self.assertNotEqual, i1, i2) 1630 # A NeverEqual object should not compare equal to itself either. 1631 i2 = i1 1632 self.assertTrue(i1 is i2) 1633 self.assertFalse(i1 == i2) 1634 self.assertFalse(i1 != i2) 1635 self.assertRaises(AssertionError, self.assertEqual, i1, i2) 1636 self.assertRaises(AssertionError, self.assertNotEqual, i1, i2) 1637 1638 def test_all_comparisons_succeed(self): 1639 a = self.AllSame() 1640 b = self.AllSame() 1641 self.assertFalse(a is b) 1642 self.assertTrue(a == b) 1643 self.assertFalse(a != b) 1644 self.assertEqual(a, b) 1645 self.assertRaises(AssertionError, self.assertNotEqual, a, b) 1646 1647 def _perform_apple_apple_orange_checks(self, same_a, same_b, different): 1648 """Perform consistency checks with two apples and an orange. 1649 1650 The two apples should always compare as being the same (and inequality 1651 checks should fail). The orange should always compare as being different 1652 to each of the apples. 1653 1654 Args: 1655 same_a: the first apple 1656 same_b: the second apple 1657 different: the orange 1658 """ 1659 self.assertTrue(same_a == same_b) 1660 self.assertFalse(same_a != same_b) 1661 self.assertEqual(same_a, same_b) 1662 1663 self.assertFalse(same_a == different) 1664 self.assertTrue(same_a != different) 1665 self.assertNotEqual(same_a, different) 1666 1667 self.assertFalse(same_b == different) 1668 self.assertTrue(same_b != different) 1669 self.assertNotEqual(same_b, different) 1670 1671 def test_comparison_with_eq(self): 1672 same_a = self.EqualityTestsWithEq(42) 1673 same_b = self.EqualityTestsWithEq(42) 1674 different = self.EqualityTestsWithEq(1769) 1675 self._perform_apple_apple_orange_checks(same_a, same_b, different) 1676 1677 def test_comparison_with_ne(self): 1678 same_a = self.EqualityTestsWithNe(42) 1679 same_b = self.EqualityTestsWithNe(42) 1680 different = self.EqualityTestsWithNe(1769) 1681 self._perform_apple_apple_orange_checks(same_a, same_b, different) 1682 1683 def test_comparison_with_cmp_or_lt_eq(self): 1684 same_a = self.EqualityTestsWithLtEq(42) 1685 same_b = self.EqualityTestsWithLtEq(42) 1686 different = self.EqualityTestsWithLtEq(1769) 1687 self._perform_apple_apple_orange_checks(same_a, same_b, different) 1688 1689 1690class AssertSequenceStartsWithTest(parameterized.TestCase): 1691 1692 def setUp(self): 1693 super().setUp() 1694 self.a = [5, 'foo', {'c': 'd'}, None] 1695 1696 def test_empty_sequence_starts_with_empty_prefix(self): 1697 self.assertSequenceStartsWith([], ()) 1698 1699 def test_sequence_prefix_is_an_empty_list(self): 1700 self.assertSequenceStartsWith([[]], ([], 'foo')) 1701 1702 def test_raise_if_empty_prefix_with_non_empty_whole(self): 1703 with self.assertRaisesRegex( 1704 AssertionError, 'Prefix length is 0 but whole length is %d: %s' % (len( 1705 self.a), r"\[5, 'foo', \{'c': 'd'\}, None\]")): 1706 self.assertSequenceStartsWith([], self.a) 1707 1708 def test_single_element_prefix(self): 1709 self.assertSequenceStartsWith([5], self.a) 1710 1711 def test_two_element_prefix(self): 1712 self.assertSequenceStartsWith((5, 'foo'), self.a) 1713 1714 def test_prefix_is_full_sequence(self): 1715 self.assertSequenceStartsWith([5, 'foo', {'c': 'd'}, None], self.a) 1716 1717 def test_string_prefix(self): 1718 self.assertSequenceStartsWith('abc', 'abc123') 1719 1720 def test_convert_non_sequence_prefix_to_sequence_and_try_again(self): 1721 self.assertSequenceStartsWith(5, self.a) 1722 1723 def test_whole_not_asequence(self): 1724 msg = (r'For whole: len\(5\) is not supported, it appears to be type: ' 1725 '<(type|class) \'int\'>') 1726 with self.assertRaisesRegex(AssertionError, msg): 1727 self.assertSequenceStartsWith(self.a, 5) 1728 1729 def test_raise_if_sequence_does_not_start_with_prefix(self): 1730 msg = (r"prefix: \['foo', \{'c': 'd'\}\] not found at start of whole: " 1731 r"\[5, 'foo', \{'c': 'd'\}, None\].") 1732 with self.assertRaisesRegex(AssertionError, msg): 1733 self.assertSequenceStartsWith(['foo', {'c': 'd'}], self.a) 1734 1735 @parameterized.named_parameters( 1736 ('dict', {'a': 1, 2: 'b'}, {'a': 1, 2: 'b', 'c': '3'}), 1737 ('set', {1, 2}, {1, 2, 3}), 1738 ) 1739 def test_raise_if_set_or_dict(self, prefix, whole): 1740 with self.assertRaisesRegex( 1741 AssertionError, 'For whole: Mapping or Set objects are not supported' 1742 ): 1743 self.assertSequenceStartsWith(prefix, whole) 1744 1745 1746class TestAssertEmpty(absltest.TestCase): 1747 longMessage = True 1748 1749 def test_raises_if_not_asized_object(self): 1750 msg = "Expected a Sized object, got: 'int'" 1751 with self.assertRaisesRegex(AssertionError, msg): 1752 self.assertEmpty(1) 1753 1754 def test_calls_len_not_bool(self): 1755 1756 class BadList(list): 1757 1758 def __bool__(self): 1759 return False 1760 1761 __nonzero__ = __bool__ 1762 1763 bad_list = BadList() 1764 self.assertEmpty(bad_list) 1765 self.assertFalse(bad_list) 1766 1767 def test_passes_when_empty(self): 1768 empty_containers = [ 1769 list(), 1770 tuple(), 1771 dict(), 1772 set(), 1773 frozenset(), 1774 b'', 1775 u'', 1776 bytearray(), 1777 ] 1778 for container in empty_containers: 1779 self.assertEmpty(container) 1780 1781 def test_raises_with_not_empty_containers(self): 1782 not_empty_containers = [ 1783 [1], 1784 (1,), 1785 {'foo': 'bar'}, 1786 {1}, 1787 frozenset([1]), 1788 b'a', 1789 u'a', 1790 bytearray(b'a'), 1791 ] 1792 regexp = r'.* has length of 1\.$' 1793 for container in not_empty_containers: 1794 with self.assertRaisesRegex(AssertionError, regexp): 1795 self.assertEmpty(container) 1796 1797 def test_user_message_added_to_default(self): 1798 msg = 'This is a useful message' 1799 whole_msg = re.escape('[1] has length of 1. : This is a useful message') 1800 with self.assertRaisesRegex(AssertionError, whole_msg): 1801 self.assertEmpty([1], msg=msg) 1802 1803 1804class TestAssertNotEmpty(absltest.TestCase): 1805 longMessage = True 1806 1807 def test_raises_if_not_asized_object(self): 1808 msg = "Expected a Sized object, got: 'int'" 1809 with self.assertRaisesRegex(AssertionError, msg): 1810 self.assertNotEmpty(1) 1811 1812 def test_calls_len_not_bool(self): 1813 1814 class BadList(list): 1815 1816 def __bool__(self): 1817 return False 1818 1819 __nonzero__ = __bool__ 1820 1821 bad_list = BadList([1]) 1822 self.assertNotEmpty(bad_list) 1823 self.assertFalse(bad_list) 1824 1825 def test_passes_when_not_empty(self): 1826 not_empty_containers = [ 1827 [1], 1828 (1,), 1829 {'foo': 'bar'}, 1830 {1}, 1831 frozenset([1]), 1832 b'a', 1833 u'a', 1834 bytearray(b'a'), 1835 ] 1836 for container in not_empty_containers: 1837 self.assertNotEmpty(container) 1838 1839 def test_raises_with_empty_containers(self): 1840 empty_containers = [ 1841 list(), 1842 tuple(), 1843 dict(), 1844 set(), 1845 frozenset(), 1846 b'', 1847 u'', 1848 bytearray(), 1849 ] 1850 regexp = r'.* has length of 0\.$' 1851 for container in empty_containers: 1852 with self.assertRaisesRegex(AssertionError, regexp): 1853 self.assertNotEmpty(container) 1854 1855 def test_user_message_added_to_default(self): 1856 msg = 'This is a useful message' 1857 whole_msg = re.escape('[] has length of 0. : This is a useful message') 1858 with self.assertRaisesRegex(AssertionError, whole_msg): 1859 self.assertNotEmpty([], msg=msg) 1860 1861 1862class TestAssertLen(absltest.TestCase): 1863 longMessage = True 1864 1865 def test_raises_if_not_asized_object(self): 1866 msg = "Expected a Sized object, got: 'int'" 1867 with self.assertRaisesRegex(AssertionError, msg): 1868 self.assertLen(1, 1) 1869 1870 def test_passes_when_expected_len(self): 1871 containers = [ 1872 [[1], 1], 1873 [(1, 2), 2], 1874 [{'a': 1, 'b': 2, 'c': 3}, 3], 1875 [{1, 2, 3, 4}, 4], 1876 [frozenset([1]), 1], 1877 [b'abc', 3], 1878 [u'def', 3], 1879 [bytearray(b'ghij'), 4], 1880 ] 1881 for container, expected_len in containers: 1882 self.assertLen(container, expected_len) 1883 1884 def test_raises_when_unexpected_len(self): 1885 containers = [ 1886 [1], 1887 (1, 2), 1888 {'a': 1, 'b': 2, 'c': 3}, 1889 {1, 2, 3, 4}, 1890 frozenset([1]), 1891 b'abc', 1892 u'def', 1893 bytearray(b'ghij'), 1894 ] 1895 for container in containers: 1896 regexp = r'.* has length of %d, expected 100\.$' % len(container) 1897 with self.assertRaisesRegex(AssertionError, regexp): 1898 self.assertLen(container, 100) 1899 1900 def test_user_message_added_to_default(self): 1901 msg = 'This is a useful message' 1902 whole_msg = ( 1903 r'\[1\] has length of 1, expected 100. : This is a useful message') 1904 with self.assertRaisesRegex(AssertionError, whole_msg): 1905 self.assertLen([1], 100, msg) 1906 1907 1908class TestLoaderTest(absltest.TestCase): 1909 """Tests that the TestLoader bans methods named TestFoo.""" 1910 1911 # pylint: disable=invalid-name 1912 class Valid(absltest.TestCase): 1913 """Test case containing a variety of valid names.""" 1914 1915 test_property = 1 1916 TestProperty = 2 1917 1918 @staticmethod 1919 def TestStaticMethod(): 1920 pass 1921 1922 @staticmethod 1923 def TestStaticMethodWithArg(foo): 1924 pass 1925 1926 @classmethod 1927 def TestClassMethod(cls): 1928 pass 1929 1930 def Test(self): 1931 pass 1932 1933 def TestingHelper(self): 1934 pass 1935 1936 def testMethod(self): 1937 pass 1938 1939 def TestHelperWithParams(self, a, b): 1940 pass 1941 1942 def TestHelperWithVarargs(self, *args, **kwargs): 1943 pass 1944 1945 def TestHelperWithDefaults(self, a=5): 1946 pass 1947 1948 def TestHelperWithKeywordOnly(self, *, arg): 1949 pass 1950 1951 class Invalid(absltest.TestCase): 1952 """Test case containing a suspicious method.""" 1953 1954 def testMethod(self): 1955 pass 1956 1957 def TestSuspiciousMethod(self): 1958 pass 1959 # pylint: enable=invalid-name 1960 1961 def setUp(self): 1962 self.loader = absltest.TestLoader() 1963 1964 def test_valid(self): 1965 suite = self.loader.loadTestsFromTestCase(TestLoaderTest.Valid) 1966 self.assertEqual(1, suite.countTestCases()) 1967 1968 def testInvalid(self): 1969 with self.assertRaisesRegex(TypeError, 'TestSuspiciousMethod'): 1970 self.loader.loadTestsFromTestCase(TestLoaderTest.Invalid) 1971 1972 1973class InitNotNecessaryForAssertsTest(absltest.TestCase): 1974 """TestCase assertions should work even if __init__ wasn't correctly called. 1975 1976 This is a workaround, see comment in 1977 absltest.TestCase._getAssertEqualityFunc. We know that not calling 1978 __init__ of a superclass is a bad thing, but people keep doing them, 1979 and this (even if a little bit dirty) saves them from shooting 1980 themselves in the foot. 1981 """ 1982 1983 def test_subclass(self): 1984 1985 class Subclass(absltest.TestCase): 1986 1987 def __init__(self): # pylint: disable=super-init-not-called 1988 pass 1989 1990 Subclass().assertEqual({}, {}) 1991 1992 def test_multiple_inheritance(self): 1993 1994 class Foo(object): 1995 1996 def __init__(self, *args, **kwargs): 1997 pass 1998 1999 class Subclass(Foo, absltest.TestCase): 2000 pass 2001 2002 Subclass().assertEqual({}, {}) 2003 2004 2005@dataclasses.dataclass 2006class _ExampleDataclass: 2007 comparable: str 2008 not_comparable: str = dataclasses.field(compare=False) 2009 comparable2: str = 'comparable2' 2010 2011 2012@dataclasses.dataclass 2013class _ExampleCustomEqualDataclass: 2014 value: str 2015 2016 def __eq__(self, other): 2017 return False 2018 2019 2020class TestAssertDataclassEqual(absltest.TestCase): 2021 2022 def test_assert_dataclass_equal_checks_a_for_dataclass(self): 2023 b = _ExampleDataclass('a', 'b') 2024 2025 message = 'First argument is not a dataclass instance.' 2026 with self.assertRaisesWithLiteralMatch(AssertionError, message): 2027 self.assertDataclassEqual('a', b) 2028 2029 def test_assert_dataclass_equal_checks_b_for_dataclass(self): 2030 a = _ExampleDataclass('a', 'b') 2031 2032 message = 'Second argument is not a dataclass instance.' 2033 with self.assertRaisesWithLiteralMatch(AssertionError, message): 2034 self.assertDataclassEqual(a, 'b') 2035 2036 def test_assert_dataclass_equal_different_dataclasses(self): 2037 a = _ExampleDataclass('a', 'b') 2038 b = _ExampleCustomEqualDataclass('c') 2039 2040 message = """Found different dataclass types: <class '__main__._ExampleDataclass'> != <class '__main__._ExampleCustomEqualDataclass'>""" 2041 with self.assertRaisesWithLiteralMatch(AssertionError, message): 2042 self.assertDataclassEqual(a, b) 2043 2044 def test_assert_dataclass_equal(self): 2045 a = _ExampleDataclass(comparable='a', not_comparable='b') 2046 b = _ExampleDataclass(comparable='a', not_comparable='c') 2047 2048 self.assertDataclassEqual(a, a) 2049 self.assertDataclassEqual(a, b) 2050 self.assertDataclassEqual(b, a) 2051 2052 def test_assert_dataclass_fails_non_equal_classes_assert_dict_passes(self): 2053 a = _ExampleCustomEqualDataclass(value='a') 2054 b = _ExampleCustomEqualDataclass(value='a') 2055 2056 message = textwrap.dedent("""\ 2057 _ExampleCustomEqualDataclass(value='a') != _ExampleCustomEqualDataclass(value='a') 2058 Cannot detect difference by examining the fields of the dataclass.""") 2059 with self.assertRaisesWithLiteralMatch(AssertionError, message): 2060 self.assertDataclassEqual(a, b) 2061 2062 def test_assert_dataclass_fails_assert_dict_fails_one_field(self): 2063 a = _ExampleDataclass(comparable='a', not_comparable='b') 2064 b = _ExampleDataclass(comparable='c', not_comparable='d') 2065 2066 message = textwrap.dedent("""\ 2067 _ExampleDataclass(comparable='a', not_comparable='b', comparable2='comparable2') != _ExampleDataclass(comparable='c', not_comparable='d', comparable2='comparable2') 2068 Fields that differ: 2069 comparable: 'a' != 'c'""") 2070 with self.assertRaisesWithLiteralMatch(AssertionError, message): 2071 self.assertDataclassEqual(a, b) 2072 2073 def test_assert_dataclass_fails_assert_dict_fails_multiple_fields(self): 2074 a = _ExampleDataclass(comparable='a', not_comparable='b', comparable2='c') 2075 b = _ExampleDataclass(comparable='c', not_comparable='d', comparable2='e') 2076 2077 message = textwrap.dedent("""\ 2078 _ExampleDataclass(comparable='a', not_comparable='b', comparable2='c') != _ExampleDataclass(comparable='c', not_comparable='d', comparable2='e') 2079 Fields that differ: 2080 comparable: 'a' != 'c' 2081 comparable2: 'c' != 'e'""") 2082 with self.assertRaisesWithLiteralMatch(AssertionError, message): 2083 self.assertDataclassEqual(a, b) 2084 2085 2086class GetCommandStringTest(parameterized.TestCase): 2087 2088 @parameterized.parameters( 2089 ([], '', ''), 2090 ([''], "''", ''), 2091 (['command', 'arg-0'], "'command' 'arg-0'", 'command arg-0'), 2092 ([u'command', u'arg-0'], "'command' 'arg-0'", u'command arg-0'), 2093 (["foo'bar"], "'foo'\"'\"'bar'", "foo'bar"), 2094 (['foo"bar'], "'foo\"bar'", 'foo"bar'), 2095 ('command arg-0', 'command arg-0', 'command arg-0'), 2096 (u'command arg-0', 'command arg-0', 'command arg-0')) 2097 def test_get_command_string( 2098 self, command, expected_non_windows, expected_windows): 2099 expected = expected_windows if os.name == 'nt' else expected_non_windows 2100 self.assertEqual(expected, absltest.get_command_string(command)) 2101 2102 2103class TempFileTest(BaseTestCase): 2104 2105 def assert_dir_exists(self, temp_dir): 2106 path = temp_dir.full_path 2107 self.assertTrue(os.path.exists(path), 'Dir {} does not exist'.format(path)) 2108 self.assertTrue(os.path.isdir(path), 2109 'Path {} exists, but is not a directory'.format(path)) 2110 2111 def assert_file_exists(self, temp_file, expected_content=b''): 2112 path = temp_file.full_path 2113 self.assertTrue(os.path.exists(path), 'File {} does not exist'.format(path)) 2114 self.assertTrue(os.path.isfile(path), 2115 'Path {} exists, but is not a file'.format(path)) 2116 2117 mode = 'rb' if isinstance(expected_content, bytes) else 'rt' 2118 with io.open(path, mode) as fp: 2119 actual = fp.read() 2120 self.assertEqual(expected_content, actual) 2121 2122 def run_tempfile_helper(self, cleanup, expected_paths): 2123 tmpdir = self.create_tempdir('helper-test-temp-dir') 2124 env = { 2125 'ABSLTEST_TEST_HELPER_TEMPFILE_CLEANUP': cleanup, 2126 'TEST_TMPDIR': tmpdir.full_path, 2127 } 2128 stdout, stderr, _ = self.run_helper( 2129 0, ['TempFileHelperTest'], env, expect_success=False 2130 ) 2131 output = ('\n=== Helper output ===\n' 2132 '----- stdout -----\n{}\n' 2133 '----- end stdout -----\n' 2134 '----- stderr -----\n{}\n' 2135 '----- end stderr -----\n' 2136 '===== end helper output =====').format(stdout, stderr) 2137 self.assertIn('test_failure', stderr, output) 2138 2139 # Adjust paths to match on Windows 2140 expected_paths = {path.replace('/', os.sep) for path in expected_paths} 2141 2142 actual = { 2143 os.path.relpath(f, tmpdir.full_path) 2144 for f in _listdir_recursive(tmpdir.full_path) 2145 if f != tmpdir.full_path 2146 } 2147 self.assertEqual(expected_paths, actual, output) 2148 2149 def test_create_file_pre_existing_readonly(self): 2150 first = self.create_tempfile('foo', content='first') 2151 os.chmod(first.full_path, 0o444) 2152 second = self.create_tempfile('foo', content='second') 2153 self.assertEqual('second', first.read_text()) 2154 self.assertEqual('second', second.read_text()) 2155 2156 def test_create_file_fails_cleanup(self): 2157 path = self.create_tempfile().full_path 2158 # Removing the write bit from the file makes it undeletable on Windows. 2159 os.chmod(path, 0) 2160 # Removing the write bit from the whole directory makes all contained files 2161 # undeletable on unix. We also need it to be exec so that os.path.isfile 2162 # returns true, and we reach the buggy branch. 2163 os.chmod(os.path.dirname(path), stat.S_IEXEC) 2164 # The test should pass, even though that file cannot be deleted in teardown. 2165 2166 def test_temp_file_path_like(self): 2167 tempdir = self.create_tempdir('foo') 2168 tempfile_ = tempdir.create_file('bar') 2169 2170 self.assertEqual(tempfile_.read_text(), pathlib.Path(tempfile_).read_text()) 2171 # assertIsInstance causes the types to be narrowed, so calling create_file 2172 # and read_text() must be done before these assertions to avoid type errors. 2173 self.assertIsInstance(tempdir, os.PathLike) 2174 self.assertIsInstance(tempfile_, os.PathLike) 2175 2176 def test_unnamed(self): 2177 td = self.create_tempdir() 2178 self.assert_dir_exists(td) 2179 2180 tdf = td.create_file() 2181 self.assert_file_exists(tdf) 2182 2183 tdd = td.mkdir() 2184 self.assert_dir_exists(tdd) 2185 2186 tf = self.create_tempfile() 2187 self.assert_file_exists(tf) 2188 2189 def test_named(self): 2190 td = self.create_tempdir('d') 2191 self.assert_dir_exists(td) 2192 2193 tdf = td.create_file('df') 2194 self.assert_file_exists(tdf) 2195 2196 tdd = td.mkdir('dd') 2197 self.assert_dir_exists(tdd) 2198 2199 tf = self.create_tempfile('f') 2200 self.assert_file_exists(tf) 2201 2202 def test_nested_paths(self): 2203 td = self.create_tempdir('d1/d2') 2204 self.assert_dir_exists(td) 2205 2206 tdf = td.create_file('df1/df2') 2207 self.assert_file_exists(tdf) 2208 2209 tdd = td.mkdir('dd1/dd2') 2210 self.assert_dir_exists(tdd) 2211 2212 tf = self.create_tempfile('f1/f2') 2213 self.assert_file_exists(tf) 2214 2215 def test_tempdir_create_file(self): 2216 td = self.create_tempdir() 2217 td.create_file(content='text') 2218 2219 def test_tempfile_text(self): 2220 tf = self.create_tempfile(content='text') 2221 self.assert_file_exists(tf, 'text') 2222 self.assertEqual('text', tf.read_text()) 2223 2224 with tf.open_text() as fp: 2225 self.assertEqual('text', fp.read()) 2226 2227 with tf.open_text('w') as fp: 2228 fp.write(u'text-from-open-write') 2229 self.assertEqual('text-from-open-write', tf.read_text()) 2230 2231 tf.write_text('text-from-write-text') 2232 self.assertEqual('text-from-write-text', tf.read_text()) 2233 2234 def test_tempfile_bytes(self): 2235 tf = self.create_tempfile(content=b'\x00\x01\x02') 2236 self.assert_file_exists(tf, b'\x00\x01\x02') 2237 self.assertEqual(b'\x00\x01\x02', tf.read_bytes()) 2238 2239 with tf.open_bytes() as fp: 2240 self.assertEqual(b'\x00\x01\x02', fp.read()) 2241 2242 with tf.open_bytes('wb') as fp: 2243 fp.write(b'\x03') 2244 self.assertEqual(b'\x03', tf.read_bytes()) 2245 2246 tf.write_bytes(b'\x04') 2247 self.assertEqual(b'\x04', tf.read_bytes()) 2248 2249 def test_tempdir_same_name(self): 2250 """Make sure the same directory name can be used.""" 2251 td1 = self.create_tempdir('foo') 2252 td2 = self.create_tempdir('foo') 2253 self.assert_dir_exists(td1) 2254 self.assert_dir_exists(td2) 2255 2256 def test_tempfile_cleanup_success(self): 2257 expected = { 2258 'TempFileHelperTest', 2259 'TempFileHelperTest/test_failure', 2260 'TempFileHelperTest/test_failure/failure', 2261 'TempFileHelperTest/test_success', 2262 'TempFileHelperTest/test_subtest_failure', 2263 'TempFileHelperTest/test_subtest_failure/parent', 2264 'TempFileHelperTest/test_subtest_failure/successful_child', 2265 'TempFileHelperTest/test_subtest_failure/failed_child', 2266 'TempFileHelperTest/test_subtest_success', 2267 } 2268 self.run_tempfile_helper('SUCCESS', expected) 2269 2270 def test_tempfile_cleanup_always(self): 2271 expected = { 2272 'TempFileHelperTest', 2273 'TempFileHelperTest/test_failure', 2274 'TempFileHelperTest/test_success', 2275 'TempFileHelperTest/test_subtest_failure', 2276 'TempFileHelperTest/test_subtest_success', 2277 } 2278 self.run_tempfile_helper('ALWAYS', expected) 2279 2280 def test_tempfile_cleanup_off(self): 2281 expected = { 2282 'TempFileHelperTest', 2283 'TempFileHelperTest/test_failure', 2284 'TempFileHelperTest/test_failure/failure', 2285 'TempFileHelperTest/test_success', 2286 'TempFileHelperTest/test_success/success', 2287 'TempFileHelperTest/test_subtest_failure', 2288 'TempFileHelperTest/test_subtest_failure/parent', 2289 'TempFileHelperTest/test_subtest_failure/successful_child', 2290 'TempFileHelperTest/test_subtest_failure/failed_child', 2291 'TempFileHelperTest/test_subtest_success', 2292 'TempFileHelperTest/test_subtest_success/parent', 2293 'TempFileHelperTest/test_subtest_success/child0', 2294 'TempFileHelperTest/test_subtest_success/child1', 2295 } 2296 self.run_tempfile_helper('OFF', expected) 2297 2298 2299class SkipClassTest(absltest.TestCase): 2300 2301 def test_incorrect_decorator_call(self): 2302 with self.assertRaises(TypeError): 2303 2304 # Disabling type checking because pytype correctly picks up that 2305 # @absltest.skipThisClass is being used incorrectly. 2306 # pytype: disable=wrong-arg-types 2307 @absltest.skipThisClass 2308 class Test(absltest.TestCase): # pylint: disable=unused-variable 2309 pass 2310 # pytype: enable=wrong-arg-types 2311 2312 def test_incorrect_decorator_subclass(self): 2313 with self.assertRaises(TypeError): 2314 2315 @absltest.skipThisClass('reason') 2316 def test_method(): # pylint: disable=unused-variable 2317 pass 2318 2319 def test_correct_decorator_class(self): 2320 2321 @absltest.skipThisClass('reason') 2322 class Test(absltest.TestCase): 2323 pass 2324 2325 with self.assertRaises(absltest.SkipTest): 2326 Test.setUpClass() 2327 2328 def test_correct_decorator_subclass(self): 2329 2330 @absltest.skipThisClass('reason') 2331 class Test(absltest.TestCase): 2332 pass 2333 2334 class Subclass(Test): 2335 pass 2336 2337 with self.subTest('Base class should be skipped'): 2338 with self.assertRaises(absltest.SkipTest): 2339 Test.setUpClass() 2340 2341 with self.subTest('Subclass should not be skipped'): 2342 Subclass.setUpClass() # should not raise. 2343 2344 def test_setup(self): 2345 2346 @absltest.skipThisClass('reason') 2347 class Test(absltest.TestCase): 2348 2349 @classmethod 2350 def setUpClass(cls): 2351 super(Test, cls).setUpClass() 2352 cls.foo = 1 2353 2354 class Subclass(Test): 2355 pass 2356 2357 Subclass.setUpClass() 2358 self.assertEqual(Subclass.foo, 1) 2359 2360 def test_setup_chain(self): 2361 2362 @absltest.skipThisClass('reason') 2363 class BaseTest(absltest.TestCase): 2364 2365 foo: int 2366 2367 @classmethod 2368 def setUpClass(cls): 2369 super(BaseTest, cls).setUpClass() 2370 cls.foo = 1 2371 2372 @absltest.skipThisClass('reason') 2373 class SecondBaseTest(BaseTest): 2374 2375 @classmethod 2376 def setUpClass(cls): 2377 super(SecondBaseTest, cls).setUpClass() 2378 cls.bar = 2 2379 2380 class Subclass(SecondBaseTest): 2381 pass 2382 2383 Subclass.setUpClass() 2384 self.assertEqual(Subclass.foo, 1) 2385 self.assertEqual(Subclass.bar, 2) 2386 2387 def test_setup_args(self): 2388 2389 @absltest.skipThisClass('reason') 2390 class Test(absltest.TestCase): 2391 foo: str 2392 bar: Optional[str] 2393 2394 @classmethod 2395 def setUpClass(cls, foo, bar=None): 2396 super(Test, cls).setUpClass() 2397 cls.foo = foo 2398 cls.bar = bar 2399 2400 class Subclass(Test): 2401 2402 @classmethod 2403 def setUpClass(cls): 2404 super(Subclass, cls).setUpClass('foo', bar='baz') 2405 2406 Subclass.setUpClass() 2407 self.assertEqual(Subclass.foo, 'foo') 2408 self.assertEqual(Subclass.bar, 'baz') 2409 2410 def test_setup_multiple_inheritance(self): 2411 2412 # Test that skipping this class doesn't break the MRO chain and stop 2413 # RequiredBase.setUpClass from running. 2414 @absltest.skipThisClass('reason') 2415 class Left(absltest.TestCase): 2416 pass 2417 2418 class RequiredBase(absltest.TestCase): 2419 foo: str 2420 2421 @classmethod 2422 def setUpClass(cls): 2423 super(RequiredBase, cls).setUpClass() 2424 cls.foo = 'foo' 2425 2426 class Right(RequiredBase): 2427 2428 @classmethod 2429 def setUpClass(cls): 2430 super(Right, cls).setUpClass() 2431 2432 # Test will fail unless Left.setUpClass() follows mro properly 2433 # Right.setUpClass() 2434 class Subclass(Left, Right): 2435 2436 @classmethod 2437 def setUpClass(cls): 2438 super(Subclass, cls).setUpClass() 2439 2440 class Test(Subclass): 2441 pass 2442 2443 Test.setUpClass() 2444 self.assertEqual(Test.foo, 'foo') 2445 2446 def test_skip_class(self): 2447 2448 @absltest.skipThisClass('reason') 2449 class BaseTest(absltest.TestCase): 2450 2451 def test_foo(self): 2452 _ = 1 / 0 2453 2454 class Test(BaseTest): 2455 2456 def test_foo(self): 2457 self.assertEqual(1, 1) 2458 2459 with self.subTest('base class'): 2460 ts = unittest.makeSuite(BaseTest) 2461 self.assertEqual(1, ts.countTestCases()) 2462 2463 res = unittest.TestResult() 2464 ts.run(res) 2465 self.assertTrue(res.wasSuccessful()) 2466 self.assertLen(res.skipped, 1) 2467 self.assertEqual(0, res.testsRun) 2468 self.assertEmpty(res.failures) 2469 self.assertEmpty(res.errors) 2470 2471 with self.subTest('real test'): 2472 ts = unittest.makeSuite(Test) 2473 self.assertEqual(1, ts.countTestCases()) 2474 2475 res = unittest.TestResult() 2476 ts.run(res) 2477 self.assertTrue(res.wasSuccessful()) 2478 self.assertEqual(1, res.testsRun) 2479 self.assertEmpty(res.skipped) 2480 self.assertEmpty(res.failures) 2481 self.assertEmpty(res.errors) 2482 2483 def test_skip_class_unittest(self): 2484 2485 @absltest.skipThisClass('reason') 2486 class Test(unittest.TestCase): # note: unittest not absltest 2487 2488 def test_foo(self): 2489 _ = 1 / 0 2490 2491 ts = unittest.makeSuite(Test) 2492 self.assertEqual(1, ts.countTestCases()) 2493 2494 res = unittest.TestResult() 2495 ts.run(res) 2496 self.assertTrue(res.wasSuccessful()) 2497 self.assertLen(res.skipped, 1) 2498 self.assertEqual(0, res.testsRun) 2499 self.assertEmpty(res.failures) 2500 self.assertEmpty(res.errors) 2501 2502 2503class ExitCodeTest(BaseTestCase): 2504 2505 def test_exits_5_when_no_tests(self): 2506 expect_success = sys.version_info < (3, 12) 2507 _, _, exit_code = self.run_helper( 2508 None, 2509 [], 2510 {}, 2511 expect_success=expect_success, 2512 helper_name='absltest_test_helper_skipped', 2513 ) 2514 if not expect_success: 2515 self.assertEqual(exit_code, 5) 2516 2517 def test_exits_5_when_all_skipped(self): 2518 self.run_helper( 2519 None, 2520 [], 2521 {'ABSLTEST_TEST_HELPER_DEFINE_CLASS': '1'}, 2522 expect_success=True, 2523 helper_name='absltest_test_helper_skipped', 2524 ) 2525 2526 2527def _listdir_recursive(path): 2528 for dirname, _, filenames in os.walk(path): 2529 yield dirname 2530 for filename in filenames: 2531 yield os.path.join(dirname, filename) 2532 2533 2534def _env_for_command_tests(): 2535 if os.name == 'nt' and 'PATH' in os.environ: 2536 # get_command_stderr and assertCommandXXX don't inherit environment 2537 # variables by default. This makes sure msys commands can be found on 2538 # Windows. 2539 return {'PATH': os.environ['PATH']} 2540 else: 2541 return None 2542 2543 2544if __name__ == '__main__': 2545 absltest.main() 2546