2422 lines
83 KiB
Python
2422 lines
83 KiB
Python
# 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."""
|
|
|
|
import collections
|
|
import contextlib
|
|
import io
|
|
import os
|
|
import pathlib
|
|
import re
|
|
import stat
|
|
import string
|
|
import subprocess
|
|
import tempfile
|
|
import unittest
|
|
|
|
from absl.testing import _bazelize_command
|
|
from absl.testing import absltest
|
|
from absl.testing import parameterized
|
|
from absl.testing.tests import absltest_env
|
|
|
|
|
|
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 = absltest_env.inherited_env()
|
|
for key, value in env_overrides.items():
|
|
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_app_run(self):
|
|
stdout, _ = self.run_helper(
|
|
7,
|
|
['--name=cat', '--name=dog'],
|
|
{'ABSLTEST_TEST_HELPER_USE_APP_RUN': '1'},
|
|
expect_success=True)
|
|
self.assertIn('Names in main() are: cat dog', stdout)
|
|
self.assertIn('Names in test_name_flag() are: cat dog', stdout)
|
|
|
|
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]])
|
|
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.
|
|
"""
|
|
self.assertRaisesWithLiteralMatch(AssertionError, sample_text_error,
|
|
self.assertMultiLineEqual,
|
|
sample_text,
|
|
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_raises_with_predicate_match_exception_captured(self):
|
|
def _raise_value_error():
|
|
raise ValueError
|
|
|
|
predicate = lambda e: e is not None
|
|
with self.assertRaisesWithPredicateMatch(ValueError, predicate) as ctx_mgr:
|
|
_raise_value_error()
|
|
|
|
expected = getattr(ctx_mgr, 'exception', None)
|
|
self.assertIsInstance(expected, ValueError)
|
|
|
|
def test_assert_raises_with_literal_match_exception_captured(self):
|
|
message = 'some value error'
|
|
def _raise_value_error():
|
|
raise ValueError(message)
|
|
|
|
# predicate = lambda e: e is not None
|
|
with self.assertRaisesWithLiteralMatch(ValueError, message) as ctx_mgr:
|
|
_raise_value_error()
|
|
|
|
expected = getattr(ctx_mgr, 'exception', None)
|
|
self.assertIsInstance(expected, 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)])
|
|
|
|
# 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
|
|
|
|
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'
|
|
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}))
|
|
|
|
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])
|
|
stderr = stderr.decode('utf-8')
|
|
self.assertRegex(stderr, 'No such file or directory')
|
|
|
|
|
|
@contextlib.contextmanager
|
|
def cm_for_test(obj):
|
|
try:
|
|
obj.cm_state = 'yielded'
|
|
yield 'value'
|
|
finally:
|
|
obj.cm_state = 'exited'
|
|
|
|
|
|
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(cm_for_test(self))
|
|
|
|
def test_enter_context(self):
|
|
self.assertEqual(self.cm_value, 'value')
|
|
self.assertEqual(self.cm_state, 'yielded')
|
|
|
|
|
|
@absltest.skipIf(not hasattr(absltest.TestCase, 'addClassCleanup'),
|
|
'Python 3.8 required for class-level enter_context')
|
|
class EnterContextClassmethodTest(absltest.TestCase):
|
|
|
|
cm_state = 'unset'
|
|
cm_value = 'unset'
|
|
|
|
@classmethod
|
|
def setUpClass(cls):
|
|
|
|
def assert_cm_exited():
|
|
assert cls.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.
|
|
cls.addClassCleanup(assert_cm_exited)
|
|
|
|
super(EnterContextClassmethodTest, cls).setUpClass()
|
|
cls.cm_value = cls.enter_context(cm_for_test(cls))
|
|
|
|
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)
|
|
|
|
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)
|
|
|
|
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)
|
|
|
|
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):
|
|
same_a = self.EqualityTestsWithLtEq(42)
|
|
same_b = self.EqualityTestsWithLtEq(42)
|
|
different = self.EqualityTestsWithLtEq(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.
|
|
|
|
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',
|
|
'TempFileHelperTest/test_subtest_failure',
|
|
'TempFileHelperTest/test_subtest_failure/parent',
|
|
'TempFileHelperTest/test_subtest_failure/successful_child',
|
|
'TempFileHelperTest/test_subtest_failure/failed_child',
|
|
'TempFileHelperTest/test_subtest_success',
|
|
}
|
|
self.run_tempfile_helper('SUCCESS', expected)
|
|
|
|
def test_tempfile_cleanup_always(self):
|
|
expected = {
|
|
'TempFileHelperTest',
|
|
'TempFileHelperTest/test_failure',
|
|
'TempFileHelperTest/test_success',
|
|
'TempFileHelperTest/test_subtest_failure',
|
|
'TempFileHelperTest/test_subtest_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',
|
|
'TempFileHelperTest/test_subtest_failure',
|
|
'TempFileHelperTest/test_subtest_failure/parent',
|
|
'TempFileHelperTest/test_subtest_failure/successful_child',
|
|
'TempFileHelperTest/test_subtest_failure/failed_child',
|
|
'TempFileHelperTest/test_subtest_success',
|
|
'TempFileHelperTest/test_subtest_success/parent',
|
|
'TempFileHelperTest/test_subtest_success/child0',
|
|
'TempFileHelperTest/test_subtest_success/child1',
|
|
}
|
|
self.run_tempfile_helper('OFF', expected)
|
|
|
|
|
|
class SkipClassTest(absltest.TestCase):
|
|
|
|
def test_incorrect_decorator_call(self):
|
|
with self.assertRaises(TypeError):
|
|
|
|
@absltest.skipThisClass
|
|
class Test(absltest.TestCase): # pylint: disable=unused-variable
|
|
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()
|