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