Skip to content

Update unittest partially #6051

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Jul 31, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 0 additions & 16 deletions Lib/test/test_unittest.py

This file was deleted.

6 changes: 6 additions & 0 deletions Lib/test/test_unittest/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import os.path
from test.support import load_package_tests


def load_tests(*args):
return load_package_tests(os.path.dirname(__file__), *args)
4 changes: 4 additions & 0 deletions Lib/test/test_unittest/__main__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
from . import load_tests
import unittest

unittest.main()
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,6 @@ def warnfun():
warnings.warn('rw', RuntimeWarning)

class TestWarnings(unittest.TestCase):
# unittest warnings will be printed at most once per type (max one message
# for the fail* methods, and one for the assert* methods)
def test_assert(self):
self.assertEquals(2+2, 4)
self.assertEquals(2*2, 4)
self.assertEquals(2**2, 4)

def test_fail(self):
self.failUnless(1)
self.failUnless(True)

def test_other_unittest(self):
self.assertAlmostEqual(2+2, 4)
self.assertNotAlmostEqual(4+4, 2)
Expand Down
File renamed without changes.
16 changes: 16 additions & 0 deletions Lib/unittest/test/support.py → Lib/test/test_unittest/support.py
Original file line number Diff line number Diff line change
Expand Up @@ -136,3 +136,19 @@ def addSuccess(self, test):

def wasSuccessful(self):
return True


class BufferedWriter:
def __init__(self):
self.result = ''
self.buffer = ''

def write(self, arg):
self.buffer += arg

def flush(self):
self.result += self.buffer
self.buffer = ''

def getvalue(self):
return self.result
Original file line number Diff line number Diff line change
Expand Up @@ -271,20 +271,11 @@ def testAssertDictEqual(self):
r"\+ \{'key': 'value'\}$",
r"\+ \{'key': 'value'\} : oops$"])

def testAssertDictContainsSubset(self):
with warnings.catch_warnings():
warnings.simplefilter("ignore", DeprecationWarning)

self.assertMessages('assertDictContainsSubset', ({'key': 'value'}, {}),
["^Missing: 'key'$", "^oops$",
"^Missing: 'key'$",
"^Missing: 'key' : oops$"])

def testAssertMultiLineEqual(self):
self.assertMessages('assertMultiLineEqual', ("", "foo"),
[r"\+ foo$", "^oops$",
r"\+ foo$",
r"\+ foo : oops$"])
[r"\+ foo\n$", "^oops$",
r"\+ foo\n$",
r"\+ foo\n : oops$"])

def testAssertLess(self):
self.assertMessages('assertLess', (2, 1),
Expand Down Expand Up @@ -395,6 +386,16 @@ def testAssertWarns(self):
'^UserWarning not triggered$',
'^UserWarning not triggered : oops$'])

def test_assertNotWarns(self):
def warn_future():
warnings.warn('xyz', FutureWarning, stacklevel=2)
self.assertMessagesCM('_assertNotWarns', (FutureWarning,),
warn_future,
['^FutureWarning triggered$',
'^oops$',
'^FutureWarning triggered$',
'^FutureWarning triggered : oops$'])

def testAssertWarnsRegex(self):
# test error not raised
self.assertMessagesCM('assertWarnsRegex', (UserWarning, 'unused regex'),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,9 @@ async def __aenter__(self):
pass


# TODO: RUSTPYTHON; used by following test suite
# VAR = contextvars.ContextVar('VAR', default=())
VAR = contextvars.ContextVar('VAR', default=())


@unittest.skip("TODO: RUSTPYTHON; requires sys.get_coroutine_origin_tracking_depth()")
class TestAsyncCase(unittest.TestCase):
maxDiff = None

Expand All @@ -50,6 +48,8 @@ def setUp(self):
# starting a new event loop
self.addCleanup(support.gc_collect)

# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_full_cycle(self):
expected = ['setUp',
'asyncSetUp',
Expand Down Expand Up @@ -296,6 +296,8 @@ async def on_cleanup2(self):
test.doCleanups()
self.assertEqual(events, ['asyncSetUp', 'test', 'asyncTearDown', 'cleanup2', 'cleanup1'])

# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_deprecation_of_return_val_from_test(self):
# Issue 41322 - deprecate return of value that is not None from a test
class Nothing:
Expand Down Expand Up @@ -486,5 +488,21 @@ async def test_demo1(self):
result = test.run()
self.assertTrue(result.wasSuccessful())

# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_loop_factory(self):
asyncio.set_event_loop_policy(None)

class TestCase1(unittest.IsolatedAsyncioTestCase):
loop_factory = asyncio.EventLoop

async def test_demo1(self):
pass

test = TestCase1('test_demo1')
result = test.run()
self.assertTrue(result.wasSuccessful())
self.assertIsNone(support.maybe_get_event_loop_policy())

if __name__ == "__main__":
unittest.main()
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,7 @@ def __init__(self, catchbreak):
self.testRunner = FakeRunner
self.test = test
self.result = None
self.durations = None

p = Program(False)
p.runTests()
Expand All @@ -244,7 +245,8 @@ def __init__(self, catchbreak):
'verbosity': verbosity,
'failfast': failfast,
'tb_locals': False,
'warnings': None})])
'warnings': None,
'durations': None})])
self.assertEqual(FakeRunner.runArgs, [test])
self.assertEqual(p.result, result)

Expand All @@ -259,7 +261,8 @@ def __init__(self, catchbreak):
'verbosity': verbosity,
'failfast': failfast,
'tb_locals': False,
'warnings': None})])
'warnings': None,
'durations': None})])
self.assertEqual(FakeRunner.runArgs, [test])
self.assertEqual(p.result, result)

Expand Down
146 changes: 80 additions & 66 deletions Lib/unittest/test/test_case.py → Lib/test/test_unittest/test_case.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@

import unittest

from unittest.test.support import (
from test.test_unittest.support import (
TestEquality, TestHashing, LoggingResult, LegacyLoggingResult,
ResultWithNoStartTestRunStopTestRun
)
Expand Down Expand Up @@ -304,7 +304,8 @@ def defaultTestResult(self):
def test(self):
pass

Foo('test').run()
with self.assertWarns(RuntimeWarning):
Foo('test').run()

def test_deprecation_of_return_val_from_test(self):
# Issue 41322 - deprecate return of value that is not None from a test
Expand Down Expand Up @@ -709,36 +710,6 @@ def testAssertIn(self):
self.assertRaises(self.failureException, self.assertNotIn, 'cow',
animals)

def testAssertDictContainsSubset(self):
with warnings.catch_warnings():
warnings.simplefilter("ignore", DeprecationWarning)

self.assertDictContainsSubset({}, {})
self.assertDictContainsSubset({}, {'a': 1})
self.assertDictContainsSubset({'a': 1}, {'a': 1})
self.assertDictContainsSubset({'a': 1}, {'a': 1, 'b': 2})
self.assertDictContainsSubset({'a': 1, 'b': 2}, {'a': 1, 'b': 2})

with self.assertRaises(self.failureException):
self.assertDictContainsSubset({1: "one"}, {})

with self.assertRaises(self.failureException):
self.assertDictContainsSubset({'a': 2}, {'a': 1})

with self.assertRaises(self.failureException):
self.assertDictContainsSubset({'c': 1}, {'a': 1})

with self.assertRaises(self.failureException):
self.assertDictContainsSubset({'a': 1, 'c': 1}, {'a': 1})

with self.assertRaises(self.failureException):
self.assertDictContainsSubset({'a': 1, 'c': 1}, {'a': 1})

one = ''.join(chr(i) for i in range(255))
# this used to cause a UnicodeDecodeError constructing the failure msg
with self.assertRaises(self.failureException):
self.assertDictContainsSubset({'foo': one}, {'foo': '\uFFFD'})

def testAssertEqual(self):
equal_pairs = [
((), ()),
Expand Down Expand Up @@ -1161,6 +1132,8 @@ def testAssertMultiLineEqual(self):
# need to remove the first line of the error message
error = str(e).split('\n', 1)[1]
self.assertEqual(sample_text_error, error)
else:
self.fail(f'{self.failureException} not raised')

def testAssertEqualSingleLine(self):
sample_text = "laden swallows fly slowly"
Expand All @@ -1177,6 +1150,74 @@ def testAssertEqualSingleLine(self):
# need to remove the first line of the error message
error = str(e).split('\n', 1)[1]
self.assertEqual(sample_text_error, error)
else:
self.fail(f'{self.failureException} not raised')

def testAssertEqualwithEmptyString(self):
'''Verify when there is an empty string involved, the diff output
does not treat the empty string as a single empty line. It should
instead be handled as a non-line.
'''
sample_text = ''
revised_sample_text = 'unladen swallows fly quickly'
sample_text_error = '''\
+ unladen swallows fly quickly
'''
try:
self.assertEqual(sample_text, revised_sample_text)
except self.failureException as e:
# need to remove the first line of the error message
error = str(e).split('\n', 1)[1]
self.assertEqual(sample_text_error, error)
else:
self.fail(f'{self.failureException} not raised')

def testAssertEqualMultipleLinesMissingNewlineTerminator(self):
'''Verifying format of diff output from assertEqual involving strings
with multiple lines, but missing the terminating newline on both.
'''
sample_text = 'laden swallows\nfly sloely'
revised_sample_text = 'laden swallows\nfly slowly'
sample_text_error = '''\
laden swallows
- fly sloely
? ^
+ fly slowly
? ^
'''
try:
self.assertEqual(sample_text, revised_sample_text)
except self.failureException as e:
# need to remove the first line of the error message
error = str(e).split('\n', 1)[1]
self.assertEqual(sample_text_error, error)
else:
self.fail(f'{self.failureException} not raised')

def testAssertEqualMultipleLinesMismatchedNewlinesTerminators(self):
'''Verifying format of diff output from assertEqual involving strings
with multiple lines and mismatched newlines. The output should
include a - on it's own line to indicate the newline difference
between the two strings
'''
sample_text = 'laden swallows\nfly sloely\n'
revised_sample_text = 'laden swallows\nfly slowly'
sample_text_error = '''\
laden swallows
- fly sloely
? ^
+ fly slowly
? ^
-\x20
'''
try:
self.assertEqual(sample_text, revised_sample_text)
except self.failureException as e:
# need to remove the first line of the error message
error = str(e).split('\n', 1)[1]
self.assertEqual(sample_text_error, error)
else:
self.fail(f'{self.failureException} not raised')

def testEqualityBytesWarning(self):
if sys.flags.bytes_warning:
Expand Down Expand Up @@ -1801,45 +1842,18 @@ def testAssertNoLogsYieldsNone(self):
pass
self.assertIsNone(value)

def testDeprecatedMethodNames(self):
"""
Test that the deprecated methods raise a DeprecationWarning. See #9424.
"""
old = (
(self.failIfEqual, (3, 5)),
(self.assertNotEquals, (3, 5)),
(self.failUnlessEqual, (3, 3)),
(self.assertEquals, (3, 3)),
(self.failUnlessAlmostEqual, (2.0, 2.0)),
(self.assertAlmostEquals, (2.0, 2.0)),
(self.failIfAlmostEqual, (3.0, 5.0)),
(self.assertNotAlmostEquals, (3.0, 5.0)),
(self.failUnless, (True,)),
(self.assert_, (True,)),
(self.failUnlessRaises, (TypeError, lambda _: 3.14 + 'spam')),
(self.failIf, (False,)),
(self.assertDictContainsSubset, (dict(a=1, b=2), dict(a=1, b=2, c=3))),
(self.assertRaisesRegexp, (KeyError, 'foo', lambda: {}['foo'])),
(self.assertRegexpMatches, ('bar', 'bar')),
)
for meth, args in old:
with self.assertWarns(DeprecationWarning):
meth(*args)

# disable this test for now. When the version where the fail* methods will
# be removed is decided, re-enable it and update the version
def _testDeprecatedFailMethods(self):
"""Test that the deprecated fail* methods get removed in 3.x"""
if sys.version_info[:2] < (3, 3):
return
def testDeprecatedFailMethods(self):
"""Test that the deprecated fail* methods get removed in 3.12"""
deprecated_names = [
'failIfEqual', 'failUnlessEqual', 'failUnlessAlmostEqual',
'failIfAlmostEqual', 'failUnless', 'failUnlessRaises', 'failIf',
'assertDictContainsSubset',
'assertNotEquals', 'assertEquals', 'assertAlmostEquals',
'assertNotAlmostEquals', 'assert_', 'assertDictContainsSubset',
'assertRaisesRegexp', 'assertRegexpMatches'
]
for deprecated_name in deprecated_names:
with self.assertRaises(AttributeError):
getattr(self, deprecated_name) # remove these in 3.x
getattr(self, deprecated_name)

def testDeepcopy(self):
# Issue: 5660
Expand Down Expand Up @@ -1956,7 +1970,7 @@ def testNoCycles(self):
del case
self.assertFalse(wr())

# TODO: RUSTPYTHON; destructors
# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_no_exception_leak(self):
# Issue #19880: TestCase.run() should not keep a reference
Expand Down
Loading
Loading