| # Copyright 2017 The Abseil Authors. |
| # |
| # Licensed under the Apache License, Version 2.0 (the "License"); |
| # you may not use this file except in compliance with the License. |
| # You may obtain a copy of the License at |
| # |
| # http://www.apache.org/licenses/LICENSE-2.0 |
| # |
| # Unless required by applicable law or agreed to in writing, software |
| # distributed under the License is distributed on an "AS IS" BASIS, |
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| # See the License for the specific language governing permissions and |
| # limitations under the License. |
| |
| """Tests for absltest.""" |
| |
| from __future__ import absolute_import |
| from __future__ import division |
| from __future__ import print_function |
| |
| import collections |
| import contextlib |
| import io |
| import os |
| import re |
| import stat |
| import string |
| import subprocess |
| import sys |
| import tempfile |
| import unittest |
| |
| from absl.testing import _bazelize_command |
| from absl.testing import absltest |
| from absl.testing import parameterized |
| import six |
| |
| try: |
| import pathlib |
| except ImportError: # PY2 |
| pathlib = None |
| |
| PY_VERSION_2 = sys.version_info[0] == 2 |
| |
| |
| class HelperMixin(object): |
| |
| def _get_helper_exec_path(self): |
| helper = 'absl/testing/tests/absltest_test_helper' |
| return _bazelize_command.get_executable_path(helper) |
| |
| def run_helper(self, test_id, args, env_overrides, expect_success): |
| env = os.environ.copy() |
| for key, value in six.iteritems(env_overrides): |
| if value is None: |
| if key in env: |
| del env[key] |
| else: |
| env[key] = value |
| |
| command = [self._get_helper_exec_path(), |
| '--test_id={}'.format(test_id)] + args |
| process = subprocess.Popen( |
| command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=env, |
| universal_newlines=True) |
| stdout, stderr = process.communicate() |
| if expect_success: |
| self.assertEqual( |
| 0, process.returncode, |
| 'Expected success, but failed with ' |
| 'stdout:\n{}\nstderr:\n{}\n'.format(stdout, stderr)) |
| else: |
| self.assertEqual( |
| 1, process.returncode, |
| 'Expected failure, but succeeded with ' |
| 'stdout:\n{}\nstderr:\n{}\n'.format(stdout, stderr)) |
| return stdout, stderr |
| |
| |
| class TestCaseTest(absltest.TestCase, HelperMixin): |
| longMessage = True |
| |
| def run_helper(self, test_id, args, env_overrides, expect_success): |
| return super(TestCaseTest, self).run_helper(test_id, args + ['HelperTest'], |
| env_overrides, expect_success) |
| |
| def test_flags_no_env_var_no_flags(self): |
| self.run_helper( |
| 1, |
| [], |
| {'TEST_RANDOM_SEED': None, |
| 'TEST_SRCDIR': None, |
| 'TEST_TMPDIR': None, |
| }, |
| expect_success=True) |
| |
| def test_flags_env_var_no_flags(self): |
| tmpdir = tempfile.mkdtemp(dir=absltest.TEST_TMPDIR.value) |
| srcdir = tempfile.mkdtemp(dir=absltest.TEST_TMPDIR.value) |
| self.run_helper( |
| 2, |
| [], |
| {'TEST_RANDOM_SEED': '321', |
| 'TEST_SRCDIR': srcdir, |
| 'TEST_TMPDIR': tmpdir, |
| 'ABSLTEST_TEST_HELPER_EXPECTED_TEST_SRCDIR': srcdir, |
| 'ABSLTEST_TEST_HELPER_EXPECTED_TEST_TMPDIR': tmpdir, |
| }, |
| expect_success=True) |
| |
| def test_flags_no_env_var_flags(self): |
| tmpdir = tempfile.mkdtemp(dir=absltest.TEST_TMPDIR.value) |
| srcdir = tempfile.mkdtemp(dir=absltest.TEST_TMPDIR.value) |
| self.run_helper( |
| 3, |
| ['--test_random_seed=123', '--test_srcdir={}'.format(srcdir), |
| '--test_tmpdir={}'.format(tmpdir)], |
| {'TEST_RANDOM_SEED': None, |
| 'TEST_SRCDIR': None, |
| 'TEST_TMPDIR': None, |
| 'ABSLTEST_TEST_HELPER_EXPECTED_TEST_SRCDIR': srcdir, |
| 'ABSLTEST_TEST_HELPER_EXPECTED_TEST_TMPDIR': tmpdir, |
| }, |
| expect_success=True) |
| |
| def test_flags_env_var_flags(self): |
| tmpdir_from_flag = tempfile.mkdtemp(dir=absltest.TEST_TMPDIR.value) |
| srcdir_from_flag = tempfile.mkdtemp(dir=absltest.TEST_TMPDIR.value) |
| tmpdir_from_env_var = tempfile.mkdtemp(dir=absltest.TEST_TMPDIR.value) |
| srcdir_from_env_var = tempfile.mkdtemp(dir=absltest.TEST_TMPDIR.value) |
| self.run_helper( |
| 4, |
| ['--test_random_seed=221', '--test_srcdir={}'.format(srcdir_from_flag), |
| '--test_tmpdir={}'.format(tmpdir_from_flag)], |
| {'TEST_RANDOM_SEED': '123', |
| 'TEST_SRCDIR': srcdir_from_env_var, |
| 'TEST_TMPDIR': tmpdir_from_env_var, |
| 'ABSLTEST_TEST_HELPER_EXPECTED_TEST_SRCDIR': srcdir_from_flag, |
| 'ABSLTEST_TEST_HELPER_EXPECTED_TEST_TMPDIR': tmpdir_from_flag, |
| }, |
| expect_success=True) |
| |
| def test_xml_output_file_from_xml_output_file_env(self): |
| xml_dir = tempfile.mkdtemp(dir=absltest.TEST_TMPDIR.value) |
| xml_output_file_env = os.path.join(xml_dir, 'xml_output_file.xml') |
| random_dir = tempfile.mkdtemp(dir=absltest.TEST_TMPDIR.value) |
| self.run_helper( |
| 6, |
| [], |
| {'XML_OUTPUT_FILE': xml_output_file_env, |
| 'RUNNING_UNDER_TEST_DAEMON': '1', |
| 'TEST_XMLOUTPUTDIR': random_dir, |
| 'ABSLTEST_TEST_HELPER_EXPECTED_XML_OUTPUT_FILE': xml_output_file_env, |
| }, |
| expect_success=True) |
| |
| def test_xml_output_file_from_daemon(self): |
| tmpdir = os.path.join(tempfile.mkdtemp( |
| dir=absltest.TEST_TMPDIR.value), 'sub_dir') |
| random_dir = tempfile.mkdtemp(dir=absltest.TEST_TMPDIR.value) |
| self.run_helper( |
| 6, |
| ['--test_tmpdir', tmpdir], |
| {'XML_OUTPUT_FILE': None, |
| 'RUNNING_UNDER_TEST_DAEMON': '1', |
| 'TEST_XMLOUTPUTDIR': random_dir, |
| 'ABSLTEST_TEST_HELPER_EXPECTED_XML_OUTPUT_FILE': os.path.join( |
| os.path.dirname(tmpdir), 'test_detail.xml'), |
| }, |
| expect_success=True) |
| |
| def test_xml_output_file_from_test_xmloutputdir_env(self): |
| xml_output_dir = tempfile.mkdtemp(dir=absltest.TEST_TMPDIR.value) |
| expected_xml_file = 'absltest_test_helper.xml' |
| self.run_helper( |
| 6, |
| [], |
| {'XML_OUTPUT_FILE': None, |
| 'RUNNING_UNDER_TEST_DAEMON': None, |
| 'TEST_XMLOUTPUTDIR': xml_output_dir, |
| 'ABSLTEST_TEST_HELPER_EXPECTED_XML_OUTPUT_FILE': os.path.join( |
| xml_output_dir, expected_xml_file), |
| }, |
| expect_success=True) |
| |
| def test_xml_output_file_from_flag(self): |
| random_dir = tempfile.mkdtemp(dir=absltest.TEST_TMPDIR.value) |
| flag_file = os.path.join( |
| tempfile.mkdtemp(dir=absltest.TEST_TMPDIR.value), 'output.xml') |
| self.run_helper( |
| 6, |
| ['--xml_output_file', flag_file], |
| {'XML_OUTPUT_FILE': os.path.join(random_dir, 'output.xml'), |
| 'RUNNING_UNDER_TEST_DAEMON': '1', |
| 'TEST_XMLOUTPUTDIR': random_dir, |
| 'ABSLTEST_TEST_HELPER_EXPECTED_XML_OUTPUT_FILE': flag_file, |
| }, |
| expect_success=True) |
| |
| def test_assert_in(self): |
| animals = {'monkey': 'banana', 'cow': 'grass', 'seal': 'fish'} |
| |
| self.assertIn('a', 'abc') |
| self.assertIn(2, [1, 2, 3]) |
| self.assertIn('monkey', animals) |
| |
| self.assertNotIn('d', 'abc') |
| self.assertNotIn(0, [1, 2, 3]) |
| self.assertNotIn('otter', animals) |
| |
| self.assertRaises(AssertionError, self.assertIn, 'x', 'abc') |
| self.assertRaises(AssertionError, self.assertIn, 4, [1, 2, 3]) |
| self.assertRaises(AssertionError, self.assertIn, 'elephant', animals) |
| |
| self.assertRaises(AssertionError, self.assertNotIn, 'c', 'abc') |
| self.assertRaises(AssertionError, self.assertNotIn, 1, [1, 2, 3]) |
| self.assertRaises(AssertionError, self.assertNotIn, 'cow', animals) |
| |
| @absltest.expectedFailure |
| def test_expected_failure(self): |
| self.assertEqual(1, 2) # the expected failure |
| |
| @absltest.expectedFailureIf(True, 'always true') |
| def test_expected_failure_if(self): |
| self.assertEqual(1, 2) # the expected failure |
| |
| def test_expected_failure_success(self): |
| _, stderr = self.run_helper(5, ['--', '-v'], {}, expect_success=False) |
| self.assertRegex(stderr, r'FAILED \(.*unexpected successes=1\)') |
| |
| def test_assert_equal(self): |
| self.assertListEqual([], []) |
| self.assertTupleEqual((), ()) |
| self.assertSequenceEqual([], ()) |
| |
| a = [0, 'a', []] |
| b = [] |
| self.assertRaises(absltest.TestCase.failureException, |
| self.assertListEqual, a, b) |
| self.assertRaises(absltest.TestCase.failureException, |
| self.assertListEqual, tuple(a), tuple(b)) |
| self.assertRaises(absltest.TestCase.failureException, |
| self.assertSequenceEqual, a, tuple(b)) |
| |
| b.extend(a) |
| self.assertListEqual(a, b) |
| self.assertTupleEqual(tuple(a), tuple(b)) |
| self.assertSequenceEqual(a, tuple(b)) |
| self.assertSequenceEqual(tuple(a), b) |
| |
| self.assertRaises(AssertionError, self.assertListEqual, a, tuple(b)) |
| self.assertRaises(AssertionError, self.assertTupleEqual, tuple(a), b) |
| self.assertRaises(AssertionError, self.assertListEqual, None, b) |
| self.assertRaises(AssertionError, self.assertTupleEqual, None, tuple(b)) |
| self.assertRaises(AssertionError, self.assertSequenceEqual, None, tuple(b)) |
| self.assertRaises(AssertionError, self.assertListEqual, 1, 1) |
| self.assertRaises(AssertionError, self.assertTupleEqual, 1, 1) |
| self.assertRaises(AssertionError, self.assertSequenceEqual, 1, 1) |
| |
| self.assertSameElements([1, 2, 3], [3, 2, 1]) |
| self.assertSameElements([1, 2] + [3] * 100, [1] * 100 + [2, 3]) |
| self.assertSameElements(['foo', 'bar', 'baz'], ['bar', 'baz', 'foo']) |
| self.assertRaises(AssertionError, self.assertSameElements, [10], [10, 11]) |
| self.assertRaises(AssertionError, self.assertSameElements, [10, 11], [10]) |
| |
| # Test that sequences of unhashable objects can be tested for sameness: |
| self.assertSameElements([[1, 2], [3, 4]], [[3, 4], [1, 2]]) |
| if PY_VERSION_2: |
| # dict's are no longer valid for < comparison in Python 3 making them |
| # unsortable (yay, sanity!). But we need to preserve this old behavior |
| # when running under Python 2. |
| self.assertSameElements([{'a': 1}, {'b': 2}], [{'b': 2}, {'a': 1}]) |
| self.assertRaises(AssertionError, self.assertSameElements, [[1]], [[2]]) |
| |
| def test_assert_items_equal_hotfix(self): |
| """Confirm that http://bugs.python.org/issue14832 - b/10038517 is gone.""" |
| for assert_items_method in (self.assertItemsEqual, self.assertCountEqual): |
| with self.assertRaises(self.failureException) as error_context: |
| assert_items_method([4], [2]) |
| error_message = str(error_context.exception) |
| # Confirm that the bug is either no longer present in Python or that our |
| # assertItemsEqual patching version of the method in absltest.TestCase |
| # doesn't get used. |
| self.assertIn('First has 1, Second has 0: 4', error_message) |
| self.assertIn('First has 0, Second has 1: 2', error_message) |
| |
| def test_assert_dict_equal(self): |
| self.assertDictEqual({}, {}) |
| |
| c = {'x': 1} |
| d = {} |
| self.assertRaises(absltest.TestCase.failureException, |
| self.assertDictEqual, c, d) |
| |
| d.update(c) |
| self.assertDictEqual(c, d) |
| |
| d['x'] = 0 |
| self.assertRaises(absltest.TestCase.failureException, |
| self.assertDictEqual, c, d, 'These are unequal') |
| |
| self.assertRaises(AssertionError, self.assertDictEqual, None, d) |
| self.assertRaises(AssertionError, self.assertDictEqual, [], d) |
| self.assertRaises(AssertionError, self.assertDictEqual, 1, 1) |
| |
| try: |
| # Ensure we use equality as the sole measure of elements, not type, since |
| # that is consistent with dict equality. |
| self.assertDictEqual({1: 1.0, 2: 2}, {1: 1, 2: 3}) |
| except AssertionError as e: |
| self.assertMultiLineEqual('{1: 1.0, 2: 2} != {1: 1, 2: 3}\n' |
| 'repr() of differing entries:\n2: 2 != 3\n', |
| str(e)) |
| |
| try: |
| self.assertDictEqual({}, {'x': 1}) |
| except AssertionError as e: |
| self.assertMultiLineEqual("{} != {'x': 1}\n" |
| "Unexpected, but present entries:\n'x': 1\n", |
| str(e)) |
| else: |
| self.fail('Expecting AssertionError') |
| |
| try: |
| self.assertDictEqual({}, {'x': 1}, 'a message') |
| except AssertionError as e: |
| self.assertIn('a message', str(e)) |
| else: |
| self.fail('Expecting AssertionError') |
| |
| expected = {'a': 1, 'b': 2, 'c': 3} |
| seen = {'a': 2, 'c': 3, 'd': 4} |
| try: |
| self.assertDictEqual(expected, seen) |
| except AssertionError as e: |
| self.assertMultiLineEqual("""\ |
| {'a': 1, 'b': 2, 'c': 3} != {'a': 2, 'c': 3, 'd': 4} |
| Unexpected, but present entries: |
| 'd': 4 |
| |
| repr() of differing entries: |
| 'a': 1 != 2 |
| |
| Missing entries: |
| 'b': 2 |
| """, str(e)) |
| else: |
| self.fail('Expecting AssertionError') |
| |
| self.assertRaises(AssertionError, self.assertDictEqual, (1, 2), {}) |
| self.assertRaises(AssertionError, self.assertDictEqual, {}, (1, 2)) |
| |
| # Ensure deterministic output of keys in dictionaries whose sort order |
| # doesn't match the lexical ordering of repr -- this is most Python objects, |
| # which are keyed by memory address. |
| class Obj(object): |
| |
| def __init__(self, name): |
| self.name = name |
| |
| def __repr__(self): |
| return self.name |
| |
| try: |
| self.assertDictEqual( |
| {'a': Obj('A'), Obj('b'): Obj('B'), Obj('c'): Obj('C')}, |
| {'a': Obj('A'), Obj('d'): Obj('D'), Obj('e'): Obj('E')}) |
| except AssertionError as e: |
| # Do as best we can not to be misleading when objects have the same repr |
| # but aren't equal. |
| err_str = str(e) |
| self.assertStartsWith(err_str, |
| "{'a': A, b: B, c: C} != {'a': A, d: D, e: E}\n") |
| self.assertRegex( |
| err_str, r'(?ms).*^Unexpected, but present entries:\s+' |
| r'^(d: D$\s+^e: E|e: E$\s+^d: D)$') |
| self.assertRegex( |
| err_str, r'(?ms).*^repr\(\) of differing entries:\s+' |
| r'^.a.: A != A$', err_str) |
| self.assertRegex( |
| err_str, r'(?ms).*^Missing entries:\s+' |
| r'^(b: B$\s+^c: C|c: C$\s+^b: B)$') |
| else: |
| self.fail('Expecting AssertionError') |
| |
| # Confirm that safe_repr, not repr, is being used. |
| class RaisesOnRepr(object): |
| |
| def __repr__(self): |
| return 1/0 # Intentionally broken __repr__ implementation. |
| |
| try: |
| self.assertDictEqual( |
| {RaisesOnRepr(): RaisesOnRepr()}, |
| {RaisesOnRepr(): RaisesOnRepr()} |
| ) |
| self.fail('Expected dicts not to match') |
| except AssertionError as e: |
| # Depending on the testing environment, the object may get a __main__ |
| # prefix or a absltest_test prefix, so strip that for comparison. |
| error_msg = re.sub( |
| r'( at 0x[^>]+)|__main__\.|absltest_test\.', '', str(e)) |
| self.assertRegex(error_msg, """(?m)\ |
| {<.*RaisesOnRepr object.*>: <.*RaisesOnRepr object.*>} != \ |
| {<.*RaisesOnRepr object.*>: <.*RaisesOnRepr object.*>} |
| Unexpected, but present entries: |
| <.*RaisesOnRepr object.*>: <.*RaisesOnRepr object.*> |
| |
| Missing entries: |
| <.*RaisesOnRepr object.*>: <.*RaisesOnRepr object.*> |
| """) |
| |
| # Confirm that safe_repr, not repr, is being used. |
| class RaisesOnLt(object): |
| |
| def __lt__(self, unused_other): |
| raise TypeError('Object is unordered.') |
| |
| def __repr__(self): |
| return '<RaisesOnLt object>' |
| |
| try: |
| self.assertDictEqual( |
| {RaisesOnLt(): RaisesOnLt()}, |
| {RaisesOnLt(): RaisesOnLt()}) |
| except AssertionError as e: |
| self.assertIn('Unexpected, but present entries:\n<RaisesOnLt', str(e)) |
| self.assertIn('Missing entries:\n<RaisesOnLt', str(e)) |
| |
| def test_assert_set_equal(self): |
| set1 = set() |
| set2 = set() |
| self.assertSetEqual(set1, set2) |
| |
| self.assertRaises(AssertionError, self.assertSetEqual, None, set2) |
| self.assertRaises(AssertionError, self.assertSetEqual, [], set2) |
| self.assertRaises(AssertionError, self.assertSetEqual, set1, None) |
| self.assertRaises(AssertionError, self.assertSetEqual, set1, []) |
| |
| set1 = set(['a']) |
| set2 = set() |
| self.assertRaises(AssertionError, self.assertSetEqual, set1, set2) |
| |
| set1 = set(['a']) |
| set2 = set(['a']) |
| self.assertSetEqual(set1, set2) |
| |
| set1 = set(['a']) |
| set2 = set(['a', 'b']) |
| self.assertRaises(AssertionError, self.assertSetEqual, set1, set2) |
| |
| set1 = set(['a']) |
| set2 = frozenset(['a', 'b']) |
| self.assertRaises(AssertionError, self.assertSetEqual, set1, set2) |
| |
| set1 = set(['a', 'b']) |
| set2 = frozenset(['a', 'b']) |
| self.assertSetEqual(set1, set2) |
| |
| set1 = set() |
| set2 = 'foo' |
| self.assertRaises(AssertionError, self.assertSetEqual, set1, set2) |
| self.assertRaises(AssertionError, self.assertSetEqual, set2, set1) |
| |
| # make sure any string formatting is tuple-safe |
| set1 = set([(0, 1), (2, 3)]) |
| set2 = set([(4, 5)]) |
| self.assertRaises(AssertionError, self.assertSetEqual, set1, set2) |
| |
| def test_assert_dict_contains_subset(self): |
| self.assertDictContainsSubset({}, {}) |
| |
| self.assertDictContainsSubset({}, {'a': 1}) |
| |
| self.assertDictContainsSubset({'a': 1}, {'a': 1}) |
| |
| self.assertDictContainsSubset({'a': 1}, {'a': 1, 'b': 2}) |
| |
| self.assertDictContainsSubset({'a': 1, 'b': 2}, {'a': 1, 'b': 2}) |
| |
| self.assertRaises(absltest.TestCase.failureException, |
| self.assertDictContainsSubset, {'a': 2}, {'a': 1}, |
| '.*Mismatched values:.*') |
| |
| self.assertRaises(absltest.TestCase.failureException, |
| self.assertDictContainsSubset, {'c': 1}, {'a': 1}, |
| '.*Missing:.*') |
| |
| self.assertRaises(absltest.TestCase.failureException, |
| self.assertDictContainsSubset, {'a': 1, 'c': 1}, {'a': 1}, |
| '.*Missing:.*') |
| |
| self.assertRaises(absltest.TestCase.failureException, |
| self.assertDictContainsSubset, {'a': 1, 'c': 1}, {'a': 1}, |
| '.*Missing:.*Mismatched values:.*') |
| |
| def test_assert_sequence_almost_equal(self): |
| actual = (1.1, 1.2, 1.4) |
| |
| # Test across sequence types. |
| self.assertSequenceAlmostEqual((1.1, 1.2, 1.4), actual) |
| self.assertSequenceAlmostEqual([1.1, 1.2, 1.4], actual) |
| |
| # Test sequence size mismatch. |
| with self.assertRaises(AssertionError): |
| self.assertSequenceAlmostEqual([1.1, 1.2], actual) |
| with self.assertRaises(AssertionError): |
| self.assertSequenceAlmostEqual([1.1, 1.2, 1.4, 1.5], actual) |
| |
| # Test delta. |
| with self.assertRaises(AssertionError): |
| self.assertSequenceAlmostEqual((1.15, 1.15, 1.4), actual) |
| self.assertSequenceAlmostEqual((1.15, 1.15, 1.4), actual, delta=0.1) |
| |
| # Test places. |
| with self.assertRaises(AssertionError): |
| self.assertSequenceAlmostEqual((1.1001, 1.2001, 1.3999), actual) |
| self.assertSequenceAlmostEqual((1.1001, 1.2001, 1.3999), actual, places=3) |
| |
| def test_assert_contains_subset(self): |
| # sets, lists, tuples, dicts all ok. Types of set and subset do not have to |
| # match. |
| actual = ('a', 'b', 'c') |
| self.assertContainsSubset({'a', 'b'}, actual) |
| self.assertContainsSubset(('b', 'c'), actual) |
| self.assertContainsSubset({'b': 1, 'c': 2}, list(actual)) |
| self.assertContainsSubset(['c', 'a'], set(actual)) |
| self.assertContainsSubset([], set()) |
| self.assertContainsSubset([], {'a': 1}) |
| |
| self.assertRaises(AssertionError, self.assertContainsSubset, ('d',), actual) |
| self.assertRaises(AssertionError, self.assertContainsSubset, ['d'], |
| set(actual)) |
| self.assertRaises(AssertionError, self.assertContainsSubset, {'a': 1}, []) |
| |
| with self.assertRaisesRegex(AssertionError, 'Missing elements'): |
| self.assertContainsSubset({1, 2, 3}, {1, 2}) |
| |
| with self.assertRaisesRegex( |
| AssertionError, |
| re.compile('Missing elements .* Custom message', re.DOTALL)): |
| self.assertContainsSubset({1, 2}, {1}, 'Custom message') |
| |
| def test_assert_no_common_elements(self): |
| actual = ('a', 'b', 'c') |
| self.assertNoCommonElements((), actual) |
| self.assertNoCommonElements(('d', 'e'), actual) |
| self.assertNoCommonElements({'d', 'e'}, actual) |
| |
| with self.assertRaisesRegex( |
| AssertionError, |
| re.compile('Common elements .* Custom message', re.DOTALL)): |
| self.assertNoCommonElements({1, 2}, {1}, 'Custom message') |
| |
| with self.assertRaises(AssertionError): |
| self.assertNoCommonElements(['a'], actual) |
| |
| with self.assertRaises(AssertionError): |
| self.assertNoCommonElements({'a', 'b', 'c'}, actual) |
| |
| with self.assertRaises(AssertionError): |
| self.assertNoCommonElements({'b', 'c'}, set(actual)) |
| |
| def test_assert_almost_equal(self): |
| self.assertAlmostEqual(1.00000001, 1.0) |
| self.assertNotAlmostEqual(1.0000001, 1.0) |
| |
| def test_assert_almost_equals_with_delta(self): |
| self.assertAlmostEqual(3.14, 3, delta=0.2) |
| self.assertAlmostEqual(2.81, 3.14, delta=1) |
| self.assertAlmostEqual(-1, 1, delta=3) |
| self.assertRaises(AssertionError, self.assertAlmostEqual, |
| 3.14, 2.81, delta=0.1) |
| self.assertRaises(AssertionError, self.assertAlmostEqual, |
| 1, 2, delta=0.5) |
| self.assertNotAlmostEqual(3.14, 2.81, delta=0.1) |
| |
| def test_assert_starts_with(self): |
| self.assertStartsWith('foobar', 'foo') |
| self.assertStartsWith('foobar', 'foobar') |
| msg = 'This is a useful message' |
| whole_msg = "'foobar' does not start with 'bar' : This is a useful message" |
| self.assertRaisesWithLiteralMatch(AssertionError, whole_msg, |
| self.assertStartsWith, |
| 'foobar', 'bar', msg) |
| self.assertRaises(AssertionError, self.assertStartsWith, 'foobar', 'blah') |
| |
| def test_assert_not_starts_with(self): |
| self.assertNotStartsWith('foobar', 'bar') |
| self.assertNotStartsWith('foobar', 'blah') |
| msg = 'This is a useful message' |
| whole_msg = "'foobar' does start with 'foo' : This is a useful message" |
| self.assertRaisesWithLiteralMatch(AssertionError, whole_msg, |
| self.assertNotStartsWith, |
| 'foobar', 'foo', msg) |
| self.assertRaises(AssertionError, self.assertNotStartsWith, 'foobar', |
| 'foobar') |
| |
| def test_assert_ends_with(self): |
| self.assertEndsWith('foobar', 'bar') |
| self.assertEndsWith('foobar', 'foobar') |
| msg = 'This is a useful message' |
| whole_msg = "'foobar' does not end with 'foo' : This is a useful message" |
| self.assertRaisesWithLiteralMatch(AssertionError, whole_msg, |
| self.assertEndsWith, |
| 'foobar', 'foo', msg) |
| self.assertRaises(AssertionError, self.assertEndsWith, 'foobar', 'blah') |
| |
| def test_assert_not_ends_with(self): |
| self.assertNotEndsWith('foobar', 'foo') |
| self.assertNotEndsWith('foobar', 'blah') |
| msg = 'This is a useful message' |
| whole_msg = "'foobar' does end with 'bar' : This is a useful message" |
| self.assertRaisesWithLiteralMatch(AssertionError, whole_msg, |
| self.assertNotEndsWith, |
| 'foobar', 'bar', msg) |
| self.assertRaises(AssertionError, self.assertNotEndsWith, 'foobar', |
| 'foobar') |
| |
| def test_assert_regex_backports(self): |
| self.assertRegex('regex', 'regex') |
| self.assertNotRegex('not-regex', 'no-match') |
| with self.assertRaisesRegex(ValueError, 'pattern'): |
| raise ValueError('pattern') |
| |
| def test_assert_regex_match_matches(self): |
| self.assertRegexMatch('str', ['str']) |
| |
| def test_assert_regex_match_matches_substring(self): |
| self.assertRegexMatch('pre-str-post', ['str']) |
| |
| def test_assert_regex_match_multiple_regex_matches(self): |
| self.assertRegexMatch('str', ['rts', 'str']) |
| |
| def test_assert_regex_match_empty_list_fails(self): |
| expected_re = re.compile(r'No regexes specified\.', re.MULTILINE) |
| |
| with self.assertRaisesRegex(AssertionError, expected_re): |
| self.assertRegexMatch('str', regexes=[]) |
| |
| def test_assert_regex_match_bad_arguments(self): |
| with self.assertRaisesRegex(AssertionError, |
| 'regexes is string or bytes;.*'): |
| self.assertRegexMatch('1.*2', '1 2') |
| |
| def test_assert_regex_match_unicode_vs_bytes(self): |
| """Ensure proper utf-8 encoding or decoding happens automatically.""" |
| self.assertRegexMatch(u'str', [b'str']) |
| self.assertRegexMatch(b'str', [u'str']) |
| |
| def test_assert_regex_match_unicode(self): |
| self.assertRegexMatch(u'foo str', [u'str']) |
| |
| def test_assert_regex_match_bytes(self): |
| self.assertRegexMatch(b'foo str', [b'str']) |
| |
| def test_assert_regex_match_all_the_same_type(self): |
| with self.assertRaisesRegex(AssertionError, 'regexes .* same type'): |
| self.assertRegexMatch('foo str', [b'str', u'foo']) |
| |
| def test_assert_command_fails_stderr(self): |
| tmpdir = tempfile.mkdtemp(dir=absltest.TEST_TMPDIR.value) |
| self.assertCommandFails( |
| ['cat', os.path.join(tmpdir, 'file.txt')], |
| ['No such file or directory'], |
| env=_env_for_command_tests()) |
| |
| def test_assert_command_fails_with_list_of_string(self): |
| self.assertCommandFails( |
| ['false'], [''], env=_env_for_command_tests()) |
| |
| def test_assert_command_fails_with_list_of_unicode_string(self): |
| self.assertCommandFails( |
| [u'false'], [''], env=_env_for_command_tests()) |
| |
| def test_assert_command_fails_with_unicode_string(self): |
| self.assertCommandFails( |
| u'false', [u''], env=_env_for_command_tests()) |
| |
| def test_assert_command_fails_with_unicode_string_bytes_regex(self): |
| self.assertCommandFails( |
| u'false', [b''], env=_env_for_command_tests()) |
| |
| def test_assert_command_fails_with_message(self): |
| msg = 'This is a useful message' |
| expected_re = re.compile('The following command succeeded while expected to' |
| ' fail:.* This is a useful message', re.DOTALL) |
| |
| with self.assertRaisesRegex(AssertionError, expected_re): |
| self.assertCommandFails( |
| [u'true'], [''], msg=msg, env=_env_for_command_tests()) |
| |
| def test_assert_command_succeeds_stderr(self): |
| expected_re = re.compile('No such file or directory') |
| tmpdir = tempfile.mkdtemp(dir=absltest.TEST_TMPDIR.value) |
| |
| with self.assertRaisesRegex(AssertionError, expected_re): |
| self.assertCommandSucceeds( |
| ['cat', os.path.join(tmpdir, 'file.txt')], |
| env=_env_for_command_tests()) |
| |
| def test_assert_command_succeeds_with_matching_unicode_regexes(self): |
| self.assertCommandSucceeds( |
| ['echo', 'SUCCESS'], regexes=[u'SUCCESS'], |
| env=_env_for_command_tests()) |
| |
| def test_assert_command_succeeds_with_matching_bytes_regexes(self): |
| self.assertCommandSucceeds( |
| ['echo', 'SUCCESS'], regexes=[b'SUCCESS'], |
| env=_env_for_command_tests()) |
| |
| def test_assert_command_succeeds_with_non_matching_regexes(self): |
| expected_re = re.compile('Running command.* This is a useful message', |
| re.DOTALL) |
| msg = 'This is a useful message' |
| |
| with self.assertRaisesRegex(AssertionError, expected_re): |
| self.assertCommandSucceeds( |
| ['echo', 'FAIL'], regexes=['SUCCESS'], msg=msg, |
| env=_env_for_command_tests()) |
| |
| def test_assert_command_succeeds_with_list_of_string(self): |
| self.assertCommandSucceeds( |
| ['true'], env=_env_for_command_tests()) |
| |
| def test_assert_command_succeeds_with_list_of_unicode_string(self): |
| self.assertCommandSucceeds( |
| [u'true'], env=_env_for_command_tests()) |
| |
| def test_assert_command_succeeds_with_unicode_string(self): |
| self.assertCommandSucceeds( |
| u'true', env=_env_for_command_tests()) |
| |
| def test_inequality(self): |
| # Try ints |
| self.assertGreater(2, 1) |
| self.assertGreaterEqual(2, 1) |
| self.assertGreaterEqual(1, 1) |
| self.assertLess(1, 2) |
| self.assertLessEqual(1, 2) |
| self.assertLessEqual(1, 1) |
| self.assertRaises(AssertionError, self.assertGreater, 1, 2) |
| self.assertRaises(AssertionError, self.assertGreater, 1, 1) |
| self.assertRaises(AssertionError, self.assertGreaterEqual, 1, 2) |
| self.assertRaises(AssertionError, self.assertLess, 2, 1) |
| self.assertRaises(AssertionError, self.assertLess, 1, 1) |
| self.assertRaises(AssertionError, self.assertLessEqual, 2, 1) |
| |
| # Try Floats |
| self.assertGreater(1.1, 1.0) |
| self.assertGreaterEqual(1.1, 1.0) |
| self.assertGreaterEqual(1.0, 1.0) |
| self.assertLess(1.0, 1.1) |
| self.assertLessEqual(1.0, 1.1) |
| self.assertLessEqual(1.0, 1.0) |
| self.assertRaises(AssertionError, self.assertGreater, 1.0, 1.1) |
| self.assertRaises(AssertionError, self.assertGreater, 1.0, 1.0) |
| self.assertRaises(AssertionError, self.assertGreaterEqual, 1.0, 1.1) |
| self.assertRaises(AssertionError, self.assertLess, 1.1, 1.0) |
| self.assertRaises(AssertionError, self.assertLess, 1.0, 1.0) |
| self.assertRaises(AssertionError, self.assertLessEqual, 1.1, 1.0) |
| |
| # Try Strings |
| self.assertGreater('bug', 'ant') |
| self.assertGreaterEqual('bug', 'ant') |
| self.assertGreaterEqual('ant', 'ant') |
| self.assertLess('ant', 'bug') |
| self.assertLessEqual('ant', 'bug') |
| self.assertLessEqual('ant', 'ant') |
| self.assertRaises(AssertionError, self.assertGreater, 'ant', 'bug') |
| self.assertRaises(AssertionError, self.assertGreater, 'ant', 'ant') |
| self.assertRaises(AssertionError, self.assertGreaterEqual, 'ant', 'bug') |
| self.assertRaises(AssertionError, self.assertLess, 'bug', 'ant') |
| self.assertRaises(AssertionError, self.assertLess, 'ant', 'ant') |
| self.assertRaises(AssertionError, self.assertLessEqual, 'bug', 'ant') |
| |
| # Try Unicode |
| self.assertGreater(u'bug', u'ant') |
| self.assertGreaterEqual(u'bug', u'ant') |
| self.assertGreaterEqual(u'ant', u'ant') |
| self.assertLess(u'ant', u'bug') |
| self.assertLessEqual(u'ant', u'bug') |
| self.assertLessEqual(u'ant', u'ant') |
| self.assertRaises(AssertionError, self.assertGreater, u'ant', u'bug') |
| self.assertRaises(AssertionError, self.assertGreater, u'ant', u'ant') |
| self.assertRaises(AssertionError, self.assertGreaterEqual, u'ant', u'bug') |
| self.assertRaises(AssertionError, self.assertLess, u'bug', u'ant') |
| self.assertRaises(AssertionError, self.assertLess, u'ant', u'ant') |
| self.assertRaises(AssertionError, self.assertLessEqual, u'bug', u'ant') |
| |
| # Try Mixed String/Unicode |
| self.assertGreater('bug', u'ant') |
| self.assertGreater(u'bug', 'ant') |
| self.assertGreaterEqual('bug', u'ant') |
| self.assertGreaterEqual(u'bug', 'ant') |
| self.assertGreaterEqual('ant', u'ant') |
| self.assertGreaterEqual(u'ant', 'ant') |
| self.assertLess('ant', u'bug') |
| self.assertLess(u'ant', 'bug') |
| self.assertLessEqual('ant', u'bug') |
| self.assertLessEqual(u'ant', 'bug') |
| self.assertLessEqual('ant', u'ant') |
| self.assertLessEqual(u'ant', 'ant') |
| self.assertRaises(AssertionError, self.assertGreater, 'ant', u'bug') |
| self.assertRaises(AssertionError, self.assertGreater, u'ant', 'bug') |
| self.assertRaises(AssertionError, self.assertGreater, 'ant', u'ant') |
| self.assertRaises(AssertionError, self.assertGreater, u'ant', 'ant') |
| self.assertRaises(AssertionError, self.assertGreaterEqual, 'ant', u'bug') |
| self.assertRaises(AssertionError, self.assertGreaterEqual, u'ant', 'bug') |
| self.assertRaises(AssertionError, self.assertLess, 'bug', u'ant') |
| self.assertRaises(AssertionError, self.assertLess, u'bug', 'ant') |
| self.assertRaises(AssertionError, self.assertLess, 'ant', u'ant') |
| self.assertRaises(AssertionError, self.assertLess, u'ant', 'ant') |
| self.assertRaises(AssertionError, self.assertLessEqual, 'bug', u'ant') |
| self.assertRaises(AssertionError, self.assertLessEqual, u'bug', 'ant') |
| |
| def test_assert_multi_line_equal(self): |
| sample_text = """\ |
| http://www.python.org/doc/2.3/lib/module-unittest.html |
| test case |
| A test case is the smallest unit of testing. [...] |
| """ |
| revised_sample_text = """\ |
| http://www.python.org/doc/2.4.1/lib/module-unittest.html |
| test case |
| A test case is the smallest unit of testing. [...] You may provide your |
| own implementation that does not subclass from TestCase, of course. |
| """ |
| sample_text_error = """ |
| - http://www.python.org/doc/2.3/lib/module-unittest.html |
| ? ^ |
| + http://www.python.org/doc/2.4.1/lib/module-unittest.html |
| ? ^^^ |
| test case |
| - A test case is the smallest unit of testing. [...] |
| + A test case is the smallest unit of testing. [...] You may provide your |
| ? +++++++++++++++++++++ |
| + own implementation that does not subclass from TestCase, of course. |
| """ |
| types = (str, unicode) if PY_VERSION_2 else (str,) |
| |
| for type1 in types: |
| for type2 in types: |
| self.assertRaisesWithLiteralMatch(AssertionError, sample_text_error, |
| self.assertMultiLineEqual, |
| type1(sample_text), |
| type2(revised_sample_text)) |
| |
| self.assertRaises(AssertionError, self.assertMultiLineEqual, (1, 2), 'str') |
| self.assertRaises(AssertionError, self.assertMultiLineEqual, 'str', (1, 2)) |
| |
| def test_assert_multi_line_equal_adds_newlines_if_needed(self): |
| self.assertRaisesWithLiteralMatch( |
| AssertionError, |
| '\n' |
| ' line1\n' |
| '- line2\n' |
| '? ^\n' |
| '+ line3\n' |
| '? ^\n', |
| self.assertMultiLineEqual, |
| 'line1\n' |
| 'line2', |
| 'line1\n' |
| 'line3') |
| |
| def test_assert_multi_line_equal_shows_missing_newlines(self): |
| self.assertRaisesWithLiteralMatch( |
| AssertionError, |
| '\n' |
| ' line1\n' |
| '- line2\n' |
| '? -\n' |
| '+ line2\n', |
| self.assertMultiLineEqual, |
| 'line1\n' |
| 'line2\n', |
| 'line1\n' |
| 'line2') |
| |
| def test_assert_multi_line_equal_shows_extra_newlines(self): |
| self.assertRaisesWithLiteralMatch( |
| AssertionError, |
| '\n' |
| ' line1\n' |
| '- line2\n' |
| '+ line2\n' |
| '? +\n', |
| self.assertMultiLineEqual, |
| 'line1\n' |
| 'line2', |
| 'line1\n' |
| 'line2\n') |
| |
| def test_assert_multi_line_equal_line_limit_limits(self): |
| self.assertRaisesWithLiteralMatch( |
| AssertionError, |
| '\n' |
| ' line1\n' |
| '(... and 4 more delta lines omitted for brevity.)\n', |
| self.assertMultiLineEqual, |
| 'line1\n' |
| 'line2\n', |
| 'line1\n' |
| 'line3\n', |
| line_limit=1) |
| |
| def test_assert_multi_line_equal_line_limit_limits_with_message(self): |
| self.assertRaisesWithLiteralMatch( |
| AssertionError, |
| 'Prefix:\n' |
| ' line1\n' |
| '(... and 4 more delta lines omitted for brevity.)\n', |
| self.assertMultiLineEqual, |
| 'line1\n' |
| 'line2\n', |
| 'line1\n' |
| 'line3\n', |
| 'Prefix', |
| line_limit=1) |
| |
| def test_assert_is_none(self): |
| self.assertIsNone(None) |
| self.assertRaises(AssertionError, self.assertIsNone, False) |
| self.assertIsNotNone('Google') |
| self.assertRaises(AssertionError, self.assertIsNotNone, None) |
| self.assertRaises(AssertionError, self.assertIsNone, (1, 2)) |
| |
| def test_assert_is(self): |
| self.assertIs(object, object) |
| self.assertRaises(AssertionError, self.assertIsNot, object, object) |
| self.assertIsNot(True, False) |
| self.assertRaises(AssertionError, self.assertIs, True, False) |
| |
| def test_assert_between(self): |
| self.assertBetween(3.14, 3.1, 3.141) |
| self.assertBetween(4, 4, 1e10000) |
| self.assertBetween(9.5, 9.4, 9.5) |
| self.assertBetween(-1e10, -1e10000, 0) |
| self.assertRaises(AssertionError, self.assertBetween, 9.4, 9.3, 9.3999) |
| self.assertRaises(AssertionError, self.assertBetween, -1e10000, -1e10, 0) |
| |
| def test_assert_raises_with_predicate_match_no_raise(self): |
| with self.assertRaisesRegex(AssertionError, '^Exception not raised$'): |
| self.assertRaisesWithPredicateMatch(Exception, |
| lambda e: True, |
| lambda: 1) # don't raise |
| |
| with self.assertRaisesRegex(AssertionError, '^Exception not raised$'): |
| with self.assertRaisesWithPredicateMatch(Exception, lambda e: True): |
| pass # don't raise |
| |
| def test_assert_raises_with_predicate_match_raises_wrong_exception(self): |
| def _raise_value_error(): |
| raise ValueError |
| |
| with self.assertRaises(ValueError): |
| self.assertRaisesWithPredicateMatch(IOError, |
| lambda e: True, |
| _raise_value_error) |
| |
| with self.assertRaises(ValueError): |
| with self.assertRaisesWithPredicateMatch(IOError, lambda e: True): |
| raise ValueError |
| |
| def test_assert_raises_with_predicate_match_predicate_fails(self): |
| def _raise_value_error(): |
| raise ValueError |
| with self.assertRaisesRegex(AssertionError, ' does not match predicate '): |
| self.assertRaisesWithPredicateMatch(ValueError, |
| lambda e: False, |
| _raise_value_error) |
| |
| with self.assertRaisesRegex(AssertionError, ' does not match predicate '): |
| with self.assertRaisesWithPredicateMatch(ValueError, lambda e: False): |
| raise ValueError |
| |
| def test_assert_raises_with_predicate_match_predicate_passes(self): |
| def _raise_value_error(): |
| raise ValueError |
| |
| self.assertRaisesWithPredicateMatch(ValueError, |
| lambda e: True, |
| _raise_value_error) |
| |
| with self.assertRaisesWithPredicateMatch(ValueError, lambda e: True): |
| raise ValueError |
| |
| def test_assert_contains_in_order(self): |
| # Valids |
| self.assertContainsInOrder( |
| ['fox', 'dog'], 'The quick brown fox jumped over the lazy dog.') |
| self.assertContainsInOrder( |
| ['quick', 'fox', 'dog'], |
| 'The quick brown fox jumped over the lazy dog.') |
| self.assertContainsInOrder( |
| ['The', 'fox', 'dog.'], 'The quick brown fox jumped over the lazy dog.') |
| self.assertContainsInOrder( |
| ['fox'], 'The quick brown fox jumped over the lazy dog.') |
| self.assertContainsInOrder( |
| 'fox', 'The quick brown fox jumped over the lazy dog.') |
| self.assertContainsInOrder( |
| ['fox', 'dog'], 'fox dog fox') |
| self.assertContainsInOrder( |
| [], 'The quick brown fox jumped over the lazy dog.') |
| self.assertContainsInOrder( |
| [], '') |
| |
| # Invalids |
| msg = 'This is a useful message' |
| whole_msg = ("Did not find 'fox' after 'dog' in 'The quick brown fox" |
| " jumped over the lazy dog' : This is a useful message") |
| self.assertRaisesWithLiteralMatch( |
| AssertionError, whole_msg, self.assertContainsInOrder, |
| ['dog', 'fox'], 'The quick brown fox jumped over the lazy dog', msg=msg) |
| self.assertRaises( |
| AssertionError, self.assertContainsInOrder, |
| ['The', 'dog', 'fox'], 'The quick brown fox jumped over the lazy dog') |
| self.assertRaises( |
| AssertionError, self.assertContainsInOrder, ['dog'], '') |
| |
| def test_assert_contains_subsequence_for_numbers(self): |
| self.assertContainsSubsequence([1, 2, 3], [1]) |
| self.assertContainsSubsequence([1, 2, 3], [1, 2]) |
| self.assertContainsSubsequence([1, 2, 3], [1, 3]) |
| |
| with self.assertRaises(AssertionError): |
| self.assertContainsSubsequence([1, 2, 3], [4]) |
| msg = 'This is a useful message' |
| whole_msg = ('[3, 1] not a subsequence of [1, 2, 3]. ' |
| 'First non-matching element: 1 : This is a useful message') |
| self.assertRaisesWithLiteralMatch(AssertionError, whole_msg, |
| self.assertContainsSubsequence, |
| [1, 2, 3], [3, 1], msg=msg) |
| |
| def test_assert_contains_subsequence_for_strings(self): |
| self.assertContainsSubsequence(['foo', 'bar', 'blorp'], ['foo', 'blorp']) |
| with self.assertRaises(AssertionError): |
| self.assertContainsSubsequence( |
| ['foo', 'bar', 'blorp'], ['blorp', 'foo']) |
| |
| def test_assert_contains_subsequence_with_empty_subsequence(self): |
| self.assertContainsSubsequence([1, 2, 3], []) |
| self.assertContainsSubsequence(['foo', 'bar', 'blorp'], []) |
| self.assertContainsSubsequence([], []) |
| |
| def test_assert_contains_subsequence_with_empty_container(self): |
| with self.assertRaises(AssertionError): |
| self.assertContainsSubsequence([], [1]) |
| with self.assertRaises(AssertionError): |
| self.assertContainsSubsequence([], ['foo']) |
| |
| def test_assert_contains_exact_subsequence_for_numbers(self): |
| self.assertContainsExactSubsequence([1, 2, 3], [1]) |
| self.assertContainsExactSubsequence([1, 2, 3], [1, 2]) |
| self.assertContainsExactSubsequence([1, 2, 3], [2, 3]) |
| |
| with self.assertRaises(AssertionError): |
| self.assertContainsExactSubsequence([1, 2, 3], [4]) |
| msg = 'This is a useful message' |
| whole_msg = ('[1, 2, 4] not an exact subsequence of [1, 2, 3, 4]. ' |
| 'Longest matching prefix: [1, 2] : This is a useful message') |
| self.assertRaisesWithLiteralMatch(AssertionError, whole_msg, |
| self.assertContainsExactSubsequence, |
| [1, 2, 3, 4], [1, 2, 4], msg=msg) |
| |
| def test_assert_contains_exact_subsequence_for_strings(self): |
| self.assertContainsExactSubsequence( |
| ['foo', 'bar', 'blorp'], ['foo', 'bar']) |
| with self.assertRaises(AssertionError): |
| self.assertContainsExactSubsequence( |
| ['foo', 'bar', 'blorp'], ['blorp', 'foo']) |
| |
| def test_assert_contains_exact_subsequence_with_empty_subsequence(self): |
| self.assertContainsExactSubsequence([1, 2, 3], []) |
| self.assertContainsExactSubsequence(['foo', 'bar', 'blorp'], []) |
| self.assertContainsExactSubsequence([], []) |
| |
| def test_assert_contains_exact_subsequence_with_empty_container(self): |
| with self.assertRaises(AssertionError): |
| self.assertContainsExactSubsequence([], [3]) |
| with self.assertRaises(AssertionError): |
| self.assertContainsExactSubsequence([], ['foo', 'bar']) |
| self.assertContainsExactSubsequence([], []) |
| |
| def test_assert_totally_ordered(self): |
| # Valid. |
| self.assertTotallyOrdered() |
| self.assertTotallyOrdered([1]) |
| self.assertTotallyOrdered([1], [2]) |
| self.assertTotallyOrdered([1, 1, 1]) |
| self.assertTotallyOrdered([(1, 1)], [(1, 2)], [(2, 1)]) |
| if PY_VERSION_2: |
| # In Python 3 comparing different types of elements is not supported. |
| self.assertTotallyOrdered([None], [1], [2]) |
| self.assertTotallyOrdered([1, 1, 1], ['a string']) |
| |
| # From the docstring. |
| class A(object): |
| |
| def __init__(self, x, y): |
| self.x = x |
| self.y = y |
| |
| def __hash__(self): |
| return hash(self.x) |
| |
| def __repr__(self): |
| return 'A(%r, %r)' % (self.x, self.y) |
| |
| def __eq__(self, other): |
| try: |
| return self.x == other.x |
| except AttributeError: |
| return NotImplemented |
| |
| def __ne__(self, other): |
| try: |
| return self.x != other.x |
| except AttributeError: |
| return NotImplemented |
| |
| def __lt__(self, other): |
| try: |
| return self.x < other.x |
| except AttributeError: |
| return NotImplemented |
| |
| def __le__(self, other): |
| try: |
| return self.x <= other.x |
| except AttributeError: |
| return NotImplemented |
| |
| def __gt__(self, other): |
| try: |
| return self.x > other.x |
| except AttributeError: |
| return NotImplemented |
| |
| def __ge__(self, other): |
| try: |
| return self.x >= other.x |
| except AttributeError: |
| return NotImplemented |
| |
| class B(A): |
| """Like A, but not hashable.""" |
| __hash__ = None |
| |
| if PY_VERSION_2: |
| self.assertTotallyOrdered( |
| [None], # None should come before everything else. |
| [1], # Integers sort earlier. |
| [A(1, 'a')], |
| [A(2, 'b')], # 2 is after 1. |
| [ |
| A(3, 'c'), |
| B(3, 'd'), |
| B(3, 'e') # The second argument is irrelevant. |
| ], |
| [A(4, 'z')], |
| ['foo']) # Strings sort last. |
| else: |
| # Python 3 does not define ordering across different types. |
| self.assertTotallyOrdered( |
| [A(1, 'a')], |
| [A(2, 'b')], # 2 is after 1. |
| [ |
| A(3, 'c'), |
| B(3, 'd'), |
| B(3, 'e') # The second argument is irrelevant. |
| ], |
| [A(4, 'z')]) |
| |
| # Invalid. |
| msg = 'This is a useful message' |
| whole_msg = '2 not less than 1 : This is a useful message' |
| self.assertRaisesWithLiteralMatch(AssertionError, whole_msg, |
| self.assertTotallyOrdered, [2], [1], |
| msg=msg) |
| self.assertRaises(AssertionError, self.assertTotallyOrdered, [2], [1]) |
| self.assertRaises(AssertionError, self.assertTotallyOrdered, [2], [1], [3]) |
| self.assertRaises(AssertionError, self.assertTotallyOrdered, [1, 2]) |
| |
| def test_short_description_without_docstring(self): |
| self.assertEquals( |
| self.shortDescription(), |
| 'TestCaseTest.test_short_description_without_docstring') |
| |
| def test_short_description_with_one_line_docstring(self): |
| """Tests shortDescription() for a method with a docstring.""" |
| self.assertEquals( |
| self.shortDescription(), |
| 'TestCaseTest.test_short_description_with_one_line_docstring\n' |
| 'Tests shortDescription() for a method with a docstring.') |
| |
| def test_short_description_with_multi_line_docstring(self): |
| """Tests shortDescription() for a method with a longer docstring. |
| |
| This method ensures that only the first line of a docstring is |
| returned used in the short description, no matter how long the |
| whole thing is. |
| """ |
| self.assertEquals( |
| self.shortDescription(), |
| 'TestCaseTest.test_short_description_with_multi_line_docstring\n' |
| 'Tests shortDescription() for a method with a longer docstring.') |
| |
| def test_assert_url_equal_same(self): |
| self.assertUrlEqual('http://a', 'http://a') |
| self.assertUrlEqual('http://a/path/test', 'http://a/path/test') |
| self.assertUrlEqual('#fragment', '#fragment') |
| self.assertUrlEqual('http://a/?q=1', 'http://a/?q=1') |
| self.assertUrlEqual('http://a/?q=1&v=5', 'http://a/?v=5&q=1') |
| self.assertUrlEqual('/logs?v=1&a=2&t=labels&f=path%3A%22foo%22', |
| '/logs?a=2&f=path%3A%22foo%22&v=1&t=labels') |
| self.assertUrlEqual('http://a/path;p1', 'http://a/path;p1') |
| self.assertUrlEqual('http://a/path;p2;p3;p1', 'http://a/path;p1;p2;p3') |
| self.assertUrlEqual('sip:alice@atlanta.com;maddr=239.255.255.1;ttl=15', |
| 'sip:alice@atlanta.com;ttl=15;maddr=239.255.255.1') |
| self.assertUrlEqual('http://nyan/cat?p=1&b=', 'http://nyan/cat?b=&p=1') |
| |
| def test_assert_url_equal_different(self): |
| msg = 'This is a useful message' |
| if PY_VERSION_2: |
| whole_msg = "'a' != 'b' : This is a useful message" |
| else: |
| whole_msg = 'This is a useful message:\n- a\n+ b\n' |
| self.assertRaisesWithLiteralMatch(AssertionError, whole_msg, |
| self.assertUrlEqual, |
| 'http://a', 'http://b', msg=msg) |
| self.assertRaises(AssertionError, self.assertUrlEqual, |
| 'http://a/x', 'http://a:8080/x') |
| self.assertRaises(AssertionError, self.assertUrlEqual, |
| 'http://a/x', 'http://a/y') |
| self.assertRaises(AssertionError, self.assertUrlEqual, |
| 'http://a/?q=2', 'http://a/?q=1') |
| self.assertRaises(AssertionError, self.assertUrlEqual, |
| 'http://a/?q=1&v=5', 'http://a/?v=2&q=1') |
| self.assertRaises(AssertionError, self.assertUrlEqual, |
| 'http://a', 'sip://b') |
| self.assertRaises(AssertionError, self.assertUrlEqual, |
| 'http://a#g', 'sip://a#f') |
| self.assertRaises(AssertionError, self.assertUrlEqual, |
| 'http://a/path;p1;p3;p1', 'http://a/path;p1;p2;p3') |
| self.assertRaises(AssertionError, self.assertUrlEqual, |
| 'http://nyan/cat?p=1&b=', 'http://nyan/cat?p=1') |
| |
| def test_same_structure_same(self): |
| self.assertSameStructure(0, 0) |
| self.assertSameStructure(1, 1) |
| self.assertSameStructure('', '') |
| self.assertSameStructure('hello', 'hello', msg='This Should not fail') |
| self.assertSameStructure(set(), set()) |
| self.assertSameStructure(set([1, 2]), set([1, 2])) |
| self.assertSameStructure(set(), frozenset()) |
| self.assertSameStructure(set([1, 2]), frozenset([1, 2])) |
| self.assertSameStructure([], []) |
| self.assertSameStructure(['a'], ['a']) |
| self.assertSameStructure([], ()) |
| self.assertSameStructure(['a'], ('a',)) |
| self.assertSameStructure({}, {}) |
| self.assertSameStructure({'one': 1}, {'one': 1}) |
| self.assertSameStructure(collections.defaultdict(None, {'one': 1}), |
| {'one': 1}) |
| self.assertSameStructure(collections.OrderedDict({'one': 1}), |
| collections.defaultdict(None, {'one': 1})) |
| # int and long should always be treated as the same type. |
| if PY_VERSION_2: |
| self.assertSameStructure({long(3): 3}, {3: long(3)}) |
| |
| def test_same_structure_different(self): |
| # Different type |
| with self.assertRaisesRegex( |
| AssertionError, |
| r"a is a <(type|class) 'int'> but b is a <(type|class) 'str'>"): |
| self.assertSameStructure(0, 'hello') |
| with self.assertRaisesRegex( |
| AssertionError, |
| r"a is a <(type|class) 'int'> but b is a <(type|class) 'list'>"): |
| self.assertSameStructure(0, []) |
| with self.assertRaisesRegex( |
| AssertionError, |
| r"a is a <(type|class) 'int'> but b is a <(type|class) 'float'>"): |
| self.assertSameStructure(2, 2.0) |
| |
| with self.assertRaisesRegex( |
| AssertionError, |
| r"a is a <(type|class) 'list'> but b is a <(type|class) 'dict'>"): |
| self.assertSameStructure([], {}) |
| |
| with self.assertRaisesRegex( |
| AssertionError, |
| r"a is a <(type|class) 'list'> but b is a <(type|class) 'set'>"): |
| self.assertSameStructure([], set()) |
| |
| with self.assertRaisesRegex( |
| AssertionError, |
| r"a is a <(type|class) 'dict'> but b is a <(type|class) 'set'>"): |
| self.assertSameStructure({}, set()) |
| |
| # Different scalar values |
| self.assertRaisesWithLiteralMatch( |
| AssertionError, 'a is 0 but b is 1', |
| self.assertSameStructure, 0, 1) |
| self.assertRaisesWithLiteralMatch( |
| AssertionError, "a is 'hello' but b is 'goodbye' : This was expected", |
| self.assertSameStructure, 'hello', 'goodbye', msg='This was expected') |
| |
| # Different sets |
| self.assertRaisesWithLiteralMatch( |
| AssertionError, |
| r'AA has 2 but BB does not', |
| self.assertSameStructure, |
| set([1, 2]), |
| set([1]), |
| aname='AA', |
| bname='BB') |
| self.assertRaisesWithLiteralMatch( |
| AssertionError, |
| r'AA lacks 2 but BB has it', |
| self.assertSameStructure, |
| set([1]), |
| set([1, 2]), |
| aname='AA', |
| bname='BB') |
| |
| # Different lists |
| self.assertRaisesWithLiteralMatch( |
| AssertionError, "a has [2] with value 'z' but b does not", |
| self.assertSameStructure, ['x', 'y', 'z'], ['x', 'y']) |
| self.assertRaisesWithLiteralMatch( |
| AssertionError, "a lacks [2] but b has it with value 'z'", |
| self.assertSameStructure, ['x', 'y'], ['x', 'y', 'z']) |
| self.assertRaisesWithLiteralMatch( |
| AssertionError, "a[2] is 'z' but b[2] is 'Z'", |
| self.assertSameStructure, ['x', 'y', 'z'], ['x', 'y', 'Z']) |
| |
| # Different dicts |
| self.assertRaisesWithLiteralMatch( |
| AssertionError, "a has ['two'] with value 2 but it's missing in b", |
| self.assertSameStructure, {'one': 1, 'two': 2}, {'one': 1}) |
| self.assertRaisesWithLiteralMatch( |
| AssertionError, "a lacks ['two'] but b has it with value 2", |
| self.assertSameStructure, {'one': 1}, {'one': 1, 'two': 2}) |
| self.assertRaisesWithLiteralMatch( |
| AssertionError, "a['two'] is 2 but b['two'] is 3", |
| self.assertSameStructure, {'one': 1, 'two': 2}, {'one': 1, 'two': 3}) |
| |
| # String and byte types should not be considered equivalent to other |
| # sequences |
| self.assertRaisesRegex( |
| AssertionError, |
| r"a is a <(type|class) 'list'> but b is a <(type|class) 'str'>", |
| self.assertSameStructure, [], '') |
| self.assertRaisesRegex( |
| AssertionError, |
| r"a is a <(type|class) 'str'> but b is a <(type|class) 'tuple'>", |
| self.assertSameStructure, '', ()) |
| self.assertRaisesRegex( |
| AssertionError, |
| r"a is a <(type|class) 'list'> but b is a <(type|class) 'str'>", |
| self.assertSameStructure, ['a', 'b', 'c'], 'abc') |
| self.assertRaisesRegex( |
| AssertionError, |
| r"a is a <(type|class) 'str'> but b is a <(type|class) 'tuple'>", |
| self.assertSameStructure, 'abc', ('a', 'b', 'c')) |
| |
| # Deep key generation |
| self.assertRaisesWithLiteralMatch( |
| AssertionError, |
| "a[0][0]['x']['y']['z'][0] is 1 but b[0][0]['x']['y']['z'][0] is 2", |
| self.assertSameStructure, |
| [[{'x': {'y': {'z': [1]}}}]], [[{'x': {'y': {'z': [2]}}}]]) |
| |
| # Multiple problems |
| self.assertRaisesWithLiteralMatch( |
| AssertionError, |
| 'a[0] is 1 but b[0] is 3; a[1] is 2 but b[1] is 4', |
| self.assertSameStructure, [1, 2], [3, 4]) |
| with self.assertRaisesRegex( |
| AssertionError, |
| re.compile(r"^a\[0] is 'a' but b\[0] is 'A'; .*" |
| r"a\[18] is 's' but b\[18] is 'S'; \.\.\.$")): |
| self.assertSameStructure( |
| list(string.ascii_lowercase), list(string.ascii_uppercase)) |
| |
| # Verify same behavior with self.maxDiff = None |
| self.maxDiff = None |
| self.assertRaisesWithLiteralMatch( |
| AssertionError, |
| 'a[0] is 1 but b[0] is 3; a[1] is 2 but b[1] is 4', |
| self.assertSameStructure, [1, 2], [3, 4]) |
| |
| def test_same_structure_mapping_unchanged(self): |
| default_a = collections.defaultdict(lambda: 'BAD MODIFICATION', {}) |
| dict_b = {'one': 'z'} |
| self.assertRaisesWithLiteralMatch( |
| AssertionError, |
| r"a lacks ['one'] but b has it with value 'z'", |
| self.assertSameStructure, default_a, dict_b) |
| self.assertEmpty(default_a) |
| |
| dict_a = {'one': 'z'} |
| default_b = collections.defaultdict(lambda: 'BAD MODIFICATION', {}) |
| self.assertRaisesWithLiteralMatch( |
| AssertionError, |
| r"a has ['one'] with value 'z' but it's missing in b", |
| self.assertSameStructure, dict_a, default_b) |
| self.assertEmpty(default_b) |
| |
| def test_assert_json_equal_same(self): |
| self.assertJsonEqual('{"success": true}', '{"success": true}') |
| self.assertJsonEqual('{"success": true}', '{"success":true}') |
| self.assertJsonEqual('true', 'true') |
| self.assertJsonEqual('null', 'null') |
| self.assertJsonEqual('false', 'false') |
| self.assertJsonEqual('34', '34') |
| self.assertJsonEqual('[1, 2, 3]', '[1,2,3]', msg='please PASS') |
| self.assertJsonEqual('{"sequence": [1, 2, 3], "float": 23.42}', |
| '{"float": 23.42, "sequence": [1,2,3]}') |
| self.assertJsonEqual('{"nest": {"spam": "eggs"}, "float": 23.42}', |
| '{"float": 23.42, "nest": {"spam":"eggs"}}') |
| |
| def test_assert_json_equal_different(self): |
| with self.assertRaises(AssertionError): |
| self.assertJsonEqual('{"success": true}', '{"success": false}') |
| with self.assertRaises(AssertionError): |
| self.assertJsonEqual('{"success": false}', '{"Success": false}') |
| with self.assertRaises(AssertionError): |
| self.assertJsonEqual('false', 'true') |
| with self.assertRaises(AssertionError) as error_context: |
| self.assertJsonEqual('null', '0', msg='I demand FAILURE') |
| self.assertIn('I demand FAILURE', error_context.exception.args[0]) |
| self.assertIn('None', error_context.exception.args[0]) |
| with self.assertRaises(AssertionError): |
| self.assertJsonEqual('[1, 0, 3]', '[1,2,3]') |
| with self.assertRaises(AssertionError): |
| self.assertJsonEqual('{"sequence": [1, 2, 3], "float": 23.42}', |
| '{"float": 23.42, "sequence": [1,0,3]}') |
| with self.assertRaises(AssertionError): |
| self.assertJsonEqual('{"nest": {"spam": "eggs"}, "float": 23.42}', |
| '{"float": 23.42, "nest": {"Spam":"beans"}}') |
| |
| def test_assert_json_equal_bad_json(self): |
| with self.assertRaises(ValueError) as error_context: |
| self.assertJsonEqual("alhg'2;#", '{"a": true}') |
| self.assertIn('first', error_context.exception.args[0]) |
| self.assertIn('alhg', error_context.exception.args[0]) |
| |
| with self.assertRaises(ValueError) as error_context: |
| self.assertJsonEqual('{"a": true}', "alhg'2;#") |
| self.assertIn('second', error_context.exception.args[0]) |
| self.assertIn('alhg', error_context.exception.args[0]) |
| |
| with self.assertRaises(ValueError) as error_context: |
| self.assertJsonEqual('', '') |
| |
| |
| class GetCommandStderrTestCase(absltest.TestCase): |
| |
| def setUp(self): |
| super(GetCommandStderrTestCase, self).setUp() |
| self.original_environ = os.environ.copy() |
| |
| def tearDown(self): |
| super(GetCommandStderrTestCase, self).tearDown() |
| os.environ = self.original_environ |
| |
| def test_return_status(self): |
| tmpdir = tempfile.mkdtemp(dir=absltest.TEST_TMPDIR.value) |
| returncode = ( |
| absltest.get_command_stderr( |
| ['cat', os.path.join(tmpdir, 'file.txt')], |
| env=_env_for_command_tests())[0]) |
| self.assertEqual(1, returncode) |
| |
| def test_stderr(self): |
| tmpdir = tempfile.mkdtemp(dir=absltest.TEST_TMPDIR.value) |
| stderr = ( |
| absltest.get_command_stderr( |
| ['cat', os.path.join(tmpdir, 'file.txt')], |
| env=_env_for_command_tests())[1]) |
| if not PY_VERSION_2: |
| stderr = stderr.decode('utf-8') |
| self.assertRegex(stderr, 'No such file or directory') |
| |
| |
| @absltest.skipIf(six.PY2, 'Python 2 does not have ExitStack') |
| class EnterContextTest(absltest.TestCase): |
| |
| def setUp(self): |
| self.cm_state = 'unset' |
| self.cm_value = 'unset' |
| |
| def assert_cm_exited(): |
| self.assertEqual(self.cm_state, 'exited') |
| |
| # Because cleanup functions are run in reverse order, we have to add |
| # our assert-cleanup before the exit stack registers its own cleanup. |
| # This ensures we see state after the stack cleanup runs. |
| self.addCleanup(assert_cm_exited) |
| |
| super(EnterContextTest, self).setUp() |
| self.cm_value = self.enter_context(self.cm_for_test()) |
| |
| @contextlib.contextmanager |
| def cm_for_test(self): |
| try: |
| self.cm_state = 'yielded' |
| yield 'value' |
| finally: |
| self.cm_state = 'exited' |
| |
| def test_enter_context(self): |
| self.assertEqual(self.cm_value, 'value') |
| self.assertEqual(self.cm_state, 'yielded') |
| |
| |
| class EqualityAssertionTest(absltest.TestCase): |
| """This test verifies that absltest.failIfEqual actually tests __ne__. |
| |
| If a user class implements __eq__, unittest.failUnlessEqual will call it |
| via first == second. However, failIfEqual also calls |
| first == second. This means that while the caller may believe |
| their __ne__ method is being tested, it is not. |
| """ |
| |
| class NeverEqual(object): |
| """Objects of this class behave like NaNs.""" |
| |
| def __eq__(self, unused_other): |
| return False |
| |
| def __ne__(self, unused_other): |
| return False |
| |
| class AllSame(object): |
| """All objects of this class compare as equal.""" |
| |
| def __eq__(self, unused_other): |
| return True |
| |
| def __ne__(self, unused_other): |
| return False |
| |
| class EqualityTestsWithEq(object): |
| """Performs all equality and inequality tests with __eq__.""" |
| |
| def __init__(self, value): |
| self._value = value |
| |
| def __eq__(self, other): |
| return self._value == other._value |
| |
| def __ne__(self, other): |
| return not self.__eq__(other) |
| |
| class EqualityTestsWithNe(object): |
| """Performs all equality and inequality tests with __ne__.""" |
| |
| def __init__(self, value): |
| self._value = value |
| |
| def __eq__(self, other): |
| return not self.__ne__(other) |
| |
| def __ne__(self, other): |
| return self._value != other._value |
| |
| class EqualityTestsWithCmp(object): |
| |
| def __init__(self, value): |
| self._value = value |
| |
| def __cmp__(self, other): |
| return cmp(self._value, other._value) |
| |
| class EqualityTestsWithLtEq(object): |
| |
| def __init__(self, value): |
| self._value = value |
| |
| def __eq__(self, other): |
| return self._value == other._value |
| |
| def __lt__(self, other): |
| return self._value < other._value |
| |
| def test_all_comparisons_fail(self): |
| i1 = self.NeverEqual() |
| i2 = self.NeverEqual() |
| self.assertFalse(i1 == i2) |
| self.assertFalse(i1 != i2) |
| |
| # Compare two distinct objects |
| self.assertFalse(i1 is i2) |
| self.assertRaises(AssertionError, self.assertEqual, i1, i2) |
| self.assertRaises(AssertionError, self.assertEquals, i1, i2) |
| self.assertRaises(AssertionError, self.failUnlessEqual, i1, i2) |
| self.assertRaises(AssertionError, self.assertNotEqual, i1, i2) |
| self.assertRaises(AssertionError, self.assertNotEquals, i1, i2) |
| self.assertRaises(AssertionError, self.failIfEqual, i1, i2) |
| # A NeverEqual object should not compare equal to itself either. |
| i2 = i1 |
| self.assertTrue(i1 is i2) |
| self.assertFalse(i1 == i2) |
| self.assertFalse(i1 != i2) |
| self.assertRaises(AssertionError, self.assertEqual, i1, i2) |
| self.assertRaises(AssertionError, self.assertEquals, i1, i2) |
| self.assertRaises(AssertionError, self.failUnlessEqual, i1, i2) |
| self.assertRaises(AssertionError, self.assertNotEqual, i1, i2) |
| self.assertRaises(AssertionError, self.assertNotEquals, i1, i2) |
| self.assertRaises(AssertionError, self.failIfEqual, i1, i2) |
| |
| def test_all_comparisons_succeed(self): |
| a = self.AllSame() |
| b = self.AllSame() |
| self.assertFalse(a is b) |
| self.assertTrue(a == b) |
| self.assertFalse(a != b) |
| self.assertEqual(a, b) |
| self.assertEquals(a, b) |
| self.failUnlessEqual(a, b) |
| self.assertRaises(AssertionError, self.assertNotEqual, a, b) |
| self.assertRaises(AssertionError, self.assertNotEquals, a, b) |
| self.assertRaises(AssertionError, self.failIfEqual, a, b) |
| |
| def _perform_apple_apple_orange_checks(self, same_a, same_b, different): |
| """Perform consistency checks with two apples and an orange. |
| |
| The two apples should always compare as being the same (and inequality |
| checks should fail). The orange should always compare as being different |
| to each of the apples. |
| |
| Args: |
| same_a: the first apple |
| same_b: the second apple |
| different: the orange |
| """ |
| self.assertTrue(same_a == same_b) |
| self.assertFalse(same_a != same_b) |
| self.assertEqual(same_a, same_b) |
| self.assertEquals(same_a, same_b) |
| self.failUnlessEqual(same_a, same_b) |
| if PY_VERSION_2: |
| # Python 3 removes the global cmp function |
| self.assertEqual(0, cmp(same_a, same_b)) |
| |
| self.assertFalse(same_a == different) |
| self.assertTrue(same_a != different) |
| self.assertNotEqual(same_a, different) |
| self.assertNotEquals(same_a, different) |
| self.failIfEqual(same_a, different) |
| if PY_VERSION_2: |
| self.assertNotEqual(0, cmp(same_a, different)) |
| |
| self.assertFalse(same_b == different) |
| self.assertTrue(same_b != different) |
| self.assertNotEqual(same_b, different) |
| self.assertNotEquals(same_b, different) |
| self.failIfEqual(same_b, different) |
| if PY_VERSION_2: |
| self.assertNotEqual(0, cmp(same_b, different)) |
| |
| def test_comparison_with_eq(self): |
| same_a = self.EqualityTestsWithEq(42) |
| same_b = self.EqualityTestsWithEq(42) |
| different = self.EqualityTestsWithEq(1769) |
| self._perform_apple_apple_orange_checks(same_a, same_b, different) |
| |
| def test_comparison_with_ne(self): |
| same_a = self.EqualityTestsWithNe(42) |
| same_b = self.EqualityTestsWithNe(42) |
| different = self.EqualityTestsWithNe(1769) |
| self._perform_apple_apple_orange_checks(same_a, same_b, different) |
| |
| def test_comparison_with_cmp_or_lt_eq(self): |
| if PY_VERSION_2: |
| # In Python 3; the __cmp__ method is no longer special. |
| cmp_or_lteq_class = self.EqualityTestsWithCmp |
| else: |
| cmp_or_lteq_class = self.EqualityTestsWithLtEq |
| |
| same_a = cmp_or_lteq_class(42) |
| same_b = cmp_or_lteq_class(42) |
| different = cmp_or_lteq_class(1769) |
| self._perform_apple_apple_orange_checks(same_a, same_b, different) |
| |
| |
| class AssertSequenceStartsWithTest(absltest.TestCase): |
| |
| def setUp(self): |
| self.a = [5, 'foo', {'c': 'd'}, None] |
| |
| def test_empty_sequence_starts_with_empty_prefix(self): |
| self.assertSequenceStartsWith([], ()) |
| |
| def test_sequence_prefix_is_an_empty_list(self): |
| self.assertSequenceStartsWith([[]], ([], 'foo')) |
| |
| def test_raise_if_empty_prefix_with_non_empty_whole(self): |
| with self.assertRaisesRegex( |
| AssertionError, 'Prefix length is 0 but whole length is %d: %s' % (len( |
| self.a), r"\[5, 'foo', \{'c': 'd'\}, None\]")): |
| self.assertSequenceStartsWith([], self.a) |
| |
| def test_single_element_prefix(self): |
| self.assertSequenceStartsWith([5], self.a) |
| |
| def test_two_element_prefix(self): |
| self.assertSequenceStartsWith((5, 'foo'), self.a) |
| |
| def test_prefix_is_full_sequence(self): |
| self.assertSequenceStartsWith([5, 'foo', {'c': 'd'}, None], self.a) |
| |
| def test_string_prefix(self): |
| self.assertSequenceStartsWith('abc', 'abc123') |
| |
| def test_convert_non_sequence_prefix_to_sequence_and_try_again(self): |
| self.assertSequenceStartsWith(5, self.a) |
| |
| def test_whole_not_asequence(self): |
| msg = (r'For whole: len\(5\) is not supported, it appears to be type: ' |
| '<(type|class) \'int\'>') |
| with self.assertRaisesRegex(AssertionError, msg): |
| self.assertSequenceStartsWith(self.a, 5) |
| |
| def test_raise_if_sequence_does_not_start_with_prefix(self): |
| msg = (r"prefix: \['foo', \{'c': 'd'\}\] not found at start of whole: " |
| r"\[5, 'foo', \{'c': 'd'\}, None\].") |
| with self.assertRaisesRegex(AssertionError, msg): |
| self.assertSequenceStartsWith(['foo', {'c': 'd'}], self.a) |
| |
| def test_raise_if_types_ar_not_supported(self): |
| with self.assertRaisesRegex(TypeError, 'unhashable type'): |
| self.assertSequenceStartsWith({'a': 1, 2: 'b'}, |
| {'a': 1, 2: 'b', 'c': '3'}) |
| |
| |
| class TestAssertEmpty(absltest.TestCase): |
| longMessage = True |
| |
| def test_raises_if_not_asized_object(self): |
| msg = "Expected a Sized object, got: 'int'" |
| with self.assertRaisesRegex(AssertionError, msg): |
| self.assertEmpty(1) |
| |
| def test_calls_len_not_bool(self): |
| |
| class BadList(list): |
| |
| def __bool__(self): |
| return False |
| |
| __nonzero__ = __bool__ |
| |
| bad_list = BadList() |
| self.assertEmpty(bad_list) |
| self.assertFalse(bad_list) |
| |
| def test_passes_when_empty(self): |
| empty_containers = [ |
| list(), |
| tuple(), |
| dict(), |
| set(), |
| frozenset(), |
| b'', |
| u'', |
| bytearray(), |
| ] |
| for container in empty_containers: |
| self.assertEmpty(container) |
| |
| def test_raises_with_not_empty_containers(self): |
| not_empty_containers = [ |
| [1], |
| (1,), |
| {'foo': 'bar'}, |
| {1}, |
| frozenset([1]), |
| b'a', |
| u'a', |
| bytearray(b'a'), |
| ] |
| regexp = r'.* has length of 1\.$' |
| for container in not_empty_containers: |
| with self.assertRaisesRegex(AssertionError, regexp): |
| self.assertEmpty(container) |
| |
| def test_user_message_added_to_default(self): |
| msg = 'This is a useful message' |
| whole_msg = re.escape('[1] has length of 1. : This is a useful message') |
| with self.assertRaisesRegex(AssertionError, whole_msg): |
| self.assertEmpty([1], msg=msg) |
| |
| |
| class TestAssertNotEmpty(absltest.TestCase): |
| longMessage = True |
| |
| def test_raises_if_not_asized_object(self): |
| msg = "Expected a Sized object, got: 'int'" |
| with self.assertRaisesRegex(AssertionError, msg): |
| self.assertNotEmpty(1) |
| |
| def test_calls_len_not_bool(self): |
| |
| class BadList(list): |
| |
| def __bool__(self): |
| return False |
| |
| __nonzero__ = __bool__ |
| |
| bad_list = BadList([1]) |
| self.assertNotEmpty(bad_list) |
| self.assertFalse(bad_list) |
| |
| def test_passes_when_not_empty(self): |
| not_empty_containers = [ |
| [1], |
| (1,), |
| {'foo': 'bar'}, |
| {1}, |
| frozenset([1]), |
| b'a', |
| u'a', |
| bytearray(b'a'), |
| ] |
| for container in not_empty_containers: |
| self.assertNotEmpty(container) |
| |
| def test_raises_with_empty_containers(self): |
| empty_containers = [ |
| list(), |
| tuple(), |
| dict(), |
| set(), |
| frozenset(), |
| b'', |
| u'', |
| bytearray(), |
| ] |
| regexp = r'.* has length of 0\.$' |
| for container in empty_containers: |
| with self.assertRaisesRegex(AssertionError, regexp): |
| self.assertNotEmpty(container) |
| |
| def test_user_message_added_to_default(self): |
| msg = 'This is a useful message' |
| whole_msg = re.escape('[] has length of 0. : This is a useful message') |
| with self.assertRaisesRegex(AssertionError, whole_msg): |
| self.assertNotEmpty([], msg=msg) |
| |
| |
| class TestAssertLen(absltest.TestCase): |
| longMessage = True |
| |
| def test_raises_if_not_asized_object(self): |
| msg = "Expected a Sized object, got: 'int'" |
| with self.assertRaisesRegex(AssertionError, msg): |
| self.assertLen(1, 1) |
| |
| def test_passes_when_expected_len(self): |
| containers = [ |
| [[1], 1], |
| [(1, 2), 2], |
| [{'a': 1, 'b': 2, 'c': 3}, 3], |
| [{1, 2, 3, 4}, 4], |
| [frozenset([1]), 1], |
| [b'abc', 3], |
| [u'def', 3], |
| [bytearray(b'ghij'), 4], |
| ] |
| for container, expected_len in containers: |
| self.assertLen(container, expected_len) |
| |
| def test_raises_when_unexpected_len(self): |
| containers = [ |
| [1], |
| (1, 2), |
| {'a': 1, 'b': 2, 'c': 3}, |
| {1, 2, 3, 4}, |
| frozenset([1]), |
| b'abc', |
| u'def', |
| bytearray(b'ghij'), |
| ] |
| for container in containers: |
| regexp = r'.* has length of %d, expected 100\.$' % len(container) |
| with self.assertRaisesRegex(AssertionError, regexp): |
| self.assertLen(container, 100) |
| |
| def test_user_message_added_to_default(self): |
| msg = 'This is a useful message' |
| whole_msg = ( |
| r'\[1\] has length of 1, expected 100. : This is a useful message') |
| with self.assertRaisesRegex(AssertionError, whole_msg): |
| self.assertLen([1], 100, msg) |
| |
| |
| class TestLoaderTest(absltest.TestCase): |
| """Tests that the TestLoader bans methods named TestFoo.""" |
| |
| # pylint: disable=invalid-name |
| class Valid(absltest.TestCase): |
| """Test case containing a variety of valid names.""" |
| |
| test_property = 1 |
| TestProperty = 2 |
| |
| @staticmethod |
| def TestStaticMethod(): |
| pass |
| |
| @staticmethod |
| def TestStaticMethodWithArg(foo): |
| pass |
| |
| @classmethod |
| def TestClassMethod(cls): |
| pass |
| |
| def Test(self): |
| pass |
| |
| def TestingHelper(self): |
| pass |
| |
| def testMethod(self): |
| pass |
| |
| def TestHelperWithParams(self, a, b): |
| pass |
| |
| def TestHelperWithVarargs(self, *args, **kwargs): |
| pass |
| |
| def TestHelperWithDefaults(self, a=5): |
| pass |
| |
| class Invalid(absltest.TestCase): |
| """Test case containing a suspicious method.""" |
| |
| def testMethod(self): |
| pass |
| |
| def TestSuspiciousMethod(self): |
| pass |
| # pylint: enable=invalid-name |
| |
| def setUp(self): |
| self.loader = absltest.TestLoader() |
| |
| def test_valid(self): |
| suite = self.loader.loadTestsFromTestCase(TestLoaderTest.Valid) |
| self.assertEquals(1, suite.countTestCases()) |
| |
| def testInvalid(self): |
| with self.assertRaisesRegex(TypeError, 'TestSuspiciousMethod'): |
| self.loader.loadTestsFromTestCase(TestLoaderTest.Invalid) |
| |
| |
| class InitNotNecessaryForAssertsTest(absltest.TestCase): |
| """TestCase assertions should work even if __init__ wasn't correctly called. |
| |
| This is a workaround, see comment in |
| absltest.TestCase._getAssertEqualityFunc. We know that not calling |
| __init__ of a superclass is a bad thing, but people keep doing them, |
| and this (even if a little bit dirty) saves them from shooting |
| themselves in the foot. |
| """ |
| |
| def test_subclass(self): |
| |
| class Subclass(absltest.TestCase): |
| |
| def __init__(self): # pylint: disable=super-init-not-called |
| pass |
| |
| Subclass().assertEquals({}, {}) |
| |
| def test_multiple_inheritance(self): |
| |
| class Foo(object): |
| |
| def __init__(self, *args, **kwargs): |
| pass |
| |
| class Subclass(Foo, absltest.TestCase): |
| pass |
| |
| Subclass().assertEquals({}, {}) |
| |
| |
| class GetCommandStringTest(parameterized.TestCase): |
| |
| @parameterized.parameters( |
| ([], '', ''), |
| ([''], "''", ''), |
| (['command', 'arg-0'], "'command' 'arg-0'", 'command arg-0'), |
| ([u'command', u'arg-0'], "'command' 'arg-0'", u'command arg-0'), |
| (["foo'bar"], "'foo'\"'\"'bar'", "foo'bar"), |
| (['foo"bar'], "'foo\"bar'", 'foo"bar'), |
| ('command arg-0', 'command arg-0', 'command arg-0'), |
| (u'command arg-0', 'command arg-0', 'command arg-0')) |
| def test_get_command_string( |
| self, command, expected_non_windows, expected_windows): |
| expected = expected_windows if os.name == 'nt' else expected_non_windows |
| self.assertEqual(expected, absltest.get_command_string(command)) |
| |
| |
| class TempFileTest(absltest.TestCase, HelperMixin): |
| |
| def assert_dir_exists(self, temp_dir): |
| path = temp_dir.full_path |
| self.assertTrue(os.path.exists(path), 'Dir {} does not exist'.format(path)) |
| self.assertTrue(os.path.isdir(path), |
| 'Path {} exists, but is not a directory'.format(path)) |
| |
| def assert_file_exists(self, temp_file, expected_content=b''): |
| path = temp_file.full_path |
| self.assertTrue(os.path.exists(path), 'File {} does not exist'.format(path)) |
| self.assertTrue(os.path.isfile(path), |
| 'Path {} exists, but is not a file'.format(path)) |
| |
| mode = 'rb' if isinstance(expected_content, bytes) else 'rt' |
| with io.open(path, mode) as fp: |
| actual = fp.read() |
| self.assertEqual(expected_content, actual) |
| |
| def run_tempfile_helper(self, cleanup, expected_paths): |
| tmpdir = self.create_tempdir('helper-test-temp-dir') |
| env = { |
| 'ABSLTEST_TEST_HELPER_TEMPFILE_CLEANUP': cleanup, |
| 'TEST_TMPDIR': tmpdir.full_path, |
| } |
| stdout, stderr = self.run_helper(0, ['TempFileHelperTest'], env, |
| expect_success=False) |
| output = ('\n=== Helper output ===\n' |
| '----- stdout -----\n{}\n' |
| '----- end stdout -----\n' |
| '----- stderr -----\n{}\n' |
| '----- end stderr -----\n' |
| '===== end helper output =====').format(stdout, stderr) |
| self.assertIn('test_failure', stderr, output) |
| |
| # Adjust paths to match on Windows |
| expected_paths = {path.replace('/', os.sep) for path in expected_paths} |
| |
| actual = { |
| os.path.relpath(f, tmpdir.full_path) |
| for f in _listdir_recursive(tmpdir.full_path) |
| if f != tmpdir.full_path |
| } |
| self.assertEqual(expected_paths, actual, output) |
| |
| def test_create_file_pre_existing_readonly(self): |
| first = self.create_tempfile('foo', content='first') |
| os.chmod(first.full_path, 0o444) |
| second = self.create_tempfile('foo', content='second') |
| self.assertEqual('second', first.read_text()) |
| self.assertEqual('second', second.read_text()) |
| |
| def test_create_file_fails_cleanup(self): |
| path = self.create_tempfile().full_path |
| # Removing the write bit from the file makes it undeletable on Windows. |
| os.chmod(path, 0) |
| # Removing the write bit from the whole directory makes all contained files |
| # undeletable on unix. We also need it to be exec so that os.path.isfile |
| # returns true, and we reach the buggy branch. |
| os.chmod(os.path.dirname(path), stat.S_IEXEC) |
| # The test should pass, even though that file cannot be deleted in teardown. |
| |
| @absltest.skipUnless(getattr(os, 'PathLike', None), 'Testing os.PathLike') |
| def test_temp_file_path_like(self): |
| tempdir = self.create_tempdir('foo') |
| self.assertIsInstance(tempdir, os.PathLike) |
| |
| tempfile_ = tempdir.create_file('bar') |
| self.assertIsInstance(tempfile_, os.PathLike) |
| |
| self.assertEqual(tempfile_.read_text(), pathlib.Path(tempfile_).read_text()) |
| |
| def test_unnamed(self): |
| td = self.create_tempdir() |
| self.assert_dir_exists(td) |
| |
| tdf = td.create_file() |
| self.assert_file_exists(tdf) |
| |
| tdd = td.mkdir() |
| self.assert_dir_exists(tdd) |
| |
| tf = self.create_tempfile() |
| self.assert_file_exists(tf) |
| |
| def test_named(self): |
| td = self.create_tempdir('d') |
| self.assert_dir_exists(td) |
| |
| tdf = td.create_file('df') |
| self.assert_file_exists(tdf) |
| |
| tdd = td.mkdir('dd') |
| self.assert_dir_exists(tdd) |
| |
| tf = self.create_tempfile('f') |
| self.assert_file_exists(tf) |
| |
| def test_nested_paths(self): |
| td = self.create_tempdir('d1/d2') |
| self.assert_dir_exists(td) |
| |
| tdf = td.create_file('df1/df2') |
| self.assert_file_exists(tdf) |
| |
| tdd = td.mkdir('dd1/dd2') |
| self.assert_dir_exists(tdd) |
| |
| tf = self.create_tempfile('f1/f2') |
| self.assert_file_exists(tf) |
| |
| def test_tempdir_create_file(self): |
| td = self.create_tempdir() |
| td.create_file(content='text') |
| |
| def test_tempfile_text(self): |
| tf = self.create_tempfile(content='text') |
| self.assert_file_exists(tf, 'text') |
| self.assertEqual('text', tf.read_text()) |
| |
| with tf.open_text() as fp: |
| self.assertEqual('text', fp.read()) |
| |
| with tf.open_text('w') as fp: |
| fp.write(u'text-from-open-write') |
| self.assertEqual('text-from-open-write', tf.read_text()) |
| |
| tf.write_text('text-from-write-text') |
| self.assertEqual('text-from-write-text', tf.read_text()) |
| |
| def test_tempfile_bytes(self): |
| tf = self.create_tempfile(content=b'\x00\x01\x02') |
| self.assert_file_exists(tf, b'\x00\x01\x02') |
| self.assertEqual(b'\x00\x01\x02', tf.read_bytes()) |
| |
| with tf.open_bytes() as fp: |
| self.assertEqual(b'\x00\x01\x02', fp.read()) |
| |
| with tf.open_bytes('wb') as fp: |
| fp.write(b'\x03') |
| self.assertEqual(b'\x03', tf.read_bytes()) |
| |
| tf.write_bytes(b'\x04') |
| self.assertEqual(b'\x04', tf.read_bytes()) |
| |
| def test_tempdir_same_name(self): |
| """Make sure the same directory name can be used.""" |
| td1 = self.create_tempdir('foo') |
| td2 = self.create_tempdir('foo') |
| self.assert_dir_exists(td1) |
| self.assert_dir_exists(td2) |
| |
| def test_tempfile_cleanup_success(self): |
| expected = { |
| 'TempFileHelperTest', |
| 'TempFileHelperTest/test_failure', |
| 'TempFileHelperTest/test_failure/failure', |
| 'TempFileHelperTest/test_success', |
| } |
| self.run_tempfile_helper('SUCCESS', expected) |
| |
| def test_tempfile_cleanup_always(self): |
| expected = { |
| 'TempFileHelperTest', |
| 'TempFileHelperTest/test_failure', |
| 'TempFileHelperTest/test_success', |
| } |
| self.run_tempfile_helper('ALWAYS', expected) |
| |
| def test_tempfile_cleanup_off(self): |
| expected = { |
| 'TempFileHelperTest', |
| 'TempFileHelperTest/test_failure', |
| 'TempFileHelperTest/test_failure/failure', |
| 'TempFileHelperTest/test_success', |
| 'TempFileHelperTest/test_success/success', |
| } |
| self.run_tempfile_helper('OFF', expected) |
| |
| |
| class SkipClassTest(absltest.TestCase): |
| |
| def test_incorrect_decorator_call(self): |
| with self.assertRaises(TypeError): |
| |
| @absltest.skipThisClass # pylint: disable=unused-variable |
| class Test(absltest.TestCase): |
| pass |
| |
| def test_incorrect_decorator_subclass(self): |
| with self.assertRaises(TypeError): |
| |
| @absltest.skipThisClass('reason') |
| def test_method(): # pylint: disable=unused-variable |
| pass |
| |
| def test_correct_decorator_class(self): |
| |
| @absltest.skipThisClass('reason') |
| class Test(absltest.TestCase): |
| pass |
| |
| with self.assertRaises(absltest.SkipTest): |
| Test.setUpClass() |
| |
| def test_correct_decorator_subclass(self): |
| |
| @absltest.skipThisClass('reason') |
| class Test(absltest.TestCase): |
| pass |
| |
| class Subclass(Test): |
| pass |
| |
| with self.subTest('Base class should be skipped'): |
| with self.assertRaises(absltest.SkipTest): |
| Test.setUpClass() |
| |
| with self.subTest('Subclass should not be skipped'): |
| Subclass.setUpClass() # should not raise. |
| |
| def test_setup(self): |
| |
| @absltest.skipThisClass('reason') |
| class Test(absltest.TestCase): |
| |
| @classmethod |
| def setUpClass(cls): |
| super(Test, cls).setUpClass() |
| cls.foo = 1 |
| |
| class Subclass(Test): |
| pass |
| |
| Subclass.setUpClass() |
| self.assertEqual(Subclass.foo, 1) |
| |
| def test_setup_chain(self): |
| |
| @absltest.skipThisClass('reason') |
| class BaseTest(absltest.TestCase): |
| |
| @classmethod |
| def setUpClass(cls): |
| super(BaseTest, cls).setUpClass() |
| cls.foo = 1 |
| |
| @absltest.skipThisClass('reason') |
| class SecondBaseTest(BaseTest): |
| |
| @classmethod |
| def setUpClass(cls): |
| super(SecondBaseTest, cls).setUpClass() |
| cls.bar = 2 |
| |
| class Subclass(SecondBaseTest): |
| pass |
| |
| Subclass.setUpClass() |
| self.assertEqual(Subclass.foo, 1) |
| self.assertEqual(Subclass.bar, 2) |
| |
| def test_setup_args(self): |
| |
| @absltest.skipThisClass('reason') |
| class Test(absltest.TestCase): |
| |
| @classmethod |
| def setUpClass(cls, foo, bar=None): |
| super(Test, cls).setUpClass() |
| cls.foo = foo |
| cls.bar = bar |
| |
| class Subclass(Test): |
| |
| @classmethod |
| def setUpClass(cls): |
| super(Subclass, cls).setUpClass('foo', bar='baz') |
| |
| Subclass.setUpClass() |
| self.assertEqual(Subclass.foo, 'foo') |
| self.assertEqual(Subclass.bar, 'baz') |
| |
| def test_setup_multiple_inheritance(self): |
| |
| # Test that skipping this class doesn't break the MRO chain and stop |
| # RequiredBase.setUpClass from running. |
| @absltest.skipThisClass('reason') |
| class Left(absltest.TestCase): |
| pass |
| |
| class RequiredBase(absltest.TestCase): |
| |
| @classmethod |
| def setUpClass(cls): |
| super(RequiredBase, cls).setUpClass() |
| cls.foo = 'foo' |
| |
| class Right(RequiredBase): |
| |
| @classmethod |
| def setUpClass(cls): |
| super(Right, cls).setUpClass() |
| |
| # Test will fail unless Left.setUpClass() follows mro properly |
| # Right.setUpClass() |
| class Subclass(Left, Right): |
| |
| @classmethod |
| def setUpClass(cls): |
| super(Subclass, cls).setUpClass() |
| |
| class Test(Subclass): |
| pass |
| |
| Test.setUpClass() |
| self.assertEqual(Test.foo, 'foo') |
| |
| def test_skip_class(self): |
| |
| @absltest.skipThisClass('reason') |
| class BaseTest(absltest.TestCase): |
| |
| def test_foo(self): |
| _ = 1 / 0 |
| |
| class Test(BaseTest): |
| |
| def test_foo(self): |
| self.assertEqual(1, 1) |
| |
| with self.subTest('base class'): |
| ts = unittest.makeSuite(BaseTest) |
| self.assertEqual(1, ts.countTestCases()) |
| |
| res = unittest.TestResult() |
| ts.run(res) |
| self.assertTrue(res.wasSuccessful()) |
| self.assertLen(res.skipped, 1) |
| self.assertEqual(0, res.testsRun) |
| self.assertEmpty(res.failures) |
| self.assertEmpty(res.errors) |
| |
| with self.subTest('real test'): |
| ts = unittest.makeSuite(Test) |
| self.assertEqual(1, ts.countTestCases()) |
| |
| res = unittest.TestResult() |
| ts.run(res) |
| self.assertTrue(res.wasSuccessful()) |
| self.assertEqual(1, res.testsRun) |
| self.assertEmpty(res.skipped) |
| self.assertEmpty(res.failures) |
| self.assertEmpty(res.errors) |
| |
| def test_skip_class_unittest(self): |
| |
| @absltest.skipThisClass('reason') |
| class Test(unittest.TestCase): # note: unittest not absltest |
| |
| def test_foo(self): |
| _ = 1 / 0 |
| |
| ts = unittest.makeSuite(Test) |
| self.assertEqual(1, ts.countTestCases()) |
| |
| res = unittest.TestResult() |
| ts.run(res) |
| self.assertTrue(res.wasSuccessful()) |
| self.assertLen(res.skipped, 1) |
| self.assertEqual(0, res.testsRun) |
| self.assertEmpty(res.failures) |
| self.assertEmpty(res.errors) |
| |
| |
| def _listdir_recursive(path): |
| for dirname, _, filenames in os.walk(path): |
| yield dirname |
| for filename in filenames: |
| yield os.path.join(dirname, filename) |
| |
| |
| def _env_for_command_tests(): |
| if os.name == 'nt' and 'PATH' in os.environ: |
| # get_command_stderr and assertCommandXXX don't inherit environment |
| # variables by default. This makes sure msys commands can be found on |
| # Windows. |
| return {'PATH': os.environ['PATH']} |
| else: |
| return None |
| |
| |
| if __name__ == '__main__': |
| absltest.main() |