mirror of
https://github.com/RustPython/RustPython.git
synced 2026-10-28 10:44:36 +08:00
Upgrade unittest from 3.14.2
This commit is contained in:
1 parent
5242ff5243
commit
dfed341ec8
29 files changed
+828
-181
No files matched your search
Vendored
+1
@@ -1,4 +1,5 @@
|
||||
import os.path
|
||||
|
||||
from test.support import load_package_tests
|
||||
|
||||
|
||||
|
||||
Vendored
+2
-1
@@ -1,4 +1,5 @@
|
||||
from . import load_tests
|
||||
import unittest
|
||||
|
||||
from . import load_tests
|
||||
|
||||
unittest.main()
|
||||
+1
@@ -14,6 +14,7 @@ import sys
|
||||
import unittest
|
||||
import warnings
|
||||
|
||||
|
||||
def warnfun():
|
||||
warnings.warn('rw', RuntimeWarning)
|
||||
|
||||
|
||||
+3
-2
@@ -1,10 +1,11 @@
|
||||
import datetime
|
||||
import unittest
|
||||
import warnings
|
||||
import weakref
|
||||
import unittest
|
||||
from test.support import gc_collect
|
||||
from itertools import product
|
||||
|
||||
from test.support import gc_collect
|
||||
|
||||
|
||||
class Test_Assertions(unittest.TestCase):
|
||||
def test_AlmostEqual(self):
|
||||
|
||||
+9
-3
@@ -1,7 +1,9 @@
|
||||
import asyncio
|
||||
import contextvars
|
||||
import unittest
|
||||
|
||||
from test import support
|
||||
from test.support import force_not_colorized
|
||||
|
||||
support.requires_working_socket(module=True)
|
||||
|
||||
@@ -11,7 +13,7 @@ class MyException(Exception):
|
||||
|
||||
|
||||
def tearDownModule():
|
||||
asyncio.set_event_loop_policy(None)
|
||||
asyncio.events._set_event_loop_policy(None)
|
||||
|
||||
|
||||
class TestCM:
|
||||
@@ -253,6 +255,7 @@ class TestAsyncCase(unittest.TestCase):
|
||||
test.doCleanups()
|
||||
self.assertEqual(events, ['asyncSetUp', 'test', 'asyncTearDown', 'cleanup'])
|
||||
|
||||
@force_not_colorized
|
||||
def test_exception_in_tear_clean_up(self):
|
||||
class Test(unittest.IsolatedAsyncioTestCase):
|
||||
async def asyncSetUp(self):
|
||||
@@ -314,18 +317,21 @@ class TestAsyncCase(unittest.TestCase):
|
||||
self.assertIn('It is deprecated to return a value that is not None', str(w.warning))
|
||||
self.assertIn('test1', str(w.warning))
|
||||
self.assertEqual(w.filename, __file__)
|
||||
self.assertIn("returned 'int'", str(w.warning))
|
||||
|
||||
with self.assertWarns(DeprecationWarning) as w:
|
||||
Test('test2').run()
|
||||
self.assertIn('It is deprecated to return a value that is not None', str(w.warning))
|
||||
self.assertIn('test2', str(w.warning))
|
||||
self.assertEqual(w.filename, __file__)
|
||||
self.assertIn("returned 'async_generator'", str(w.warning))
|
||||
|
||||
with self.assertWarns(DeprecationWarning) as w:
|
||||
Test('test3').run()
|
||||
self.assertIn('It is deprecated to return a value that is not None', str(w.warning))
|
||||
self.assertIn('test3', str(w.warning))
|
||||
self.assertEqual(w.filename, __file__)
|
||||
self.assertIn(f'returned {Nothing.__name__!r}', str(w.warning))
|
||||
|
||||
def test_cleanups_interleave_order(self):
|
||||
events = []
|
||||
@@ -477,7 +483,7 @@ class TestAsyncCase(unittest.TestCase):
|
||||
|
||||
class TestCase1(unittest.IsolatedAsyncioTestCase):
|
||||
def setUp(self):
|
||||
asyncio.get_event_loop_policy().get_event_loop()
|
||||
asyncio.events._get_event_loop_policy().get_event_loop()
|
||||
|
||||
async def test_demo1(self):
|
||||
pass
|
||||
@@ -487,7 +493,7 @@ class TestAsyncCase(unittest.TestCase):
|
||||
self.assertTrue(result.wasSuccessful())
|
||||
|
||||
def test_loop_factory(self):
|
||||
asyncio.set_event_loop_policy(None)
|
||||
asyncio.events._set_event_loop_policy(None)
|
||||
|
||||
class TestCase1(unittest.IsolatedAsyncioTestCase):
|
||||
loop_factory = asyncio.EventLoop
|
||||
|
||||
Vendored
+2
-2
@@ -1,10 +1,10 @@
|
||||
import gc
|
||||
import io
|
||||
import os
|
||||
import sys
|
||||
import signal
|
||||
import weakref
|
||||
import sys
|
||||
import unittest
|
||||
import weakref
|
||||
|
||||
from test import support
|
||||
|
||||
|
||||
Vendored
+349
-22
@@ -1,26 +1,27 @@
|
||||
import contextlib
|
||||
import difflib
|
||||
import pprint
|
||||
import inspect
|
||||
import logging
|
||||
import pickle
|
||||
import pprint
|
||||
import re
|
||||
import sys
|
||||
import logging
|
||||
import types
|
||||
import unittest
|
||||
import warnings
|
||||
import weakref
|
||||
import inspect
|
||||
import types
|
||||
|
||||
from collections import UserString
|
||||
from copy import deepcopy
|
||||
|
||||
from test import support
|
||||
|
||||
import unittest
|
||||
|
||||
from test.test_unittest.support import (
|
||||
TestEquality, TestHashing, LoggingResult, LegacyLoggingResult,
|
||||
ResultWithNoStartTestRunStopTestRun
|
||||
)
|
||||
from test.support import captured_stderr, gc_collect
|
||||
|
||||
from test.test_unittest.support import (
|
||||
LegacyLoggingResult,
|
||||
LoggingResult,
|
||||
ResultWithNoStartTestRunStopTestRun,
|
||||
TestEquality,
|
||||
TestHashing,
|
||||
)
|
||||
|
||||
log_foo = logging.getLogger('foo')
|
||||
log_foobar = logging.getLogger('foo.bar')
|
||||
@@ -54,6 +55,10 @@ class Test(object):
|
||||
self.events.append('tearDown')
|
||||
|
||||
|
||||
class List(list):
|
||||
pass
|
||||
|
||||
|
||||
class Test_TestCase(unittest.TestCase, TestEquality, TestHashing):
|
||||
|
||||
### Set up attributes used by inherited tests
|
||||
@@ -85,7 +90,7 @@ class Test_TestCase(unittest.TestCase, TestEquality, TestHashing):
|
||||
def runTest(self): raise MyException()
|
||||
def test(self): pass
|
||||
|
||||
self.assertEqual(Test().id()[-13:], '.Test.runTest')
|
||||
self.assertEndsWith(Test().id(), '.Test.runTest')
|
||||
|
||||
# test that TestCase can be instantiated with no args
|
||||
# primarily for use at the interactive interpreter
|
||||
@@ -106,7 +111,7 @@ class Test_TestCase(unittest.TestCase, TestEquality, TestHashing):
|
||||
def runTest(self): raise MyException()
|
||||
def test(self): pass
|
||||
|
||||
self.assertEqual(Test('test').id()[-10:], '.Test.test')
|
||||
self.assertEndsWith(Test('test').id(), '.Test.test')
|
||||
|
||||
# "class TestCase([methodName])"
|
||||
# ...
|
||||
@@ -325,18 +330,40 @@ class Test_TestCase(unittest.TestCase, TestEquality, TestHashing):
|
||||
self.assertIn('It is deprecated to return a value that is not None', str(w.warning))
|
||||
self.assertIn('test1', str(w.warning))
|
||||
self.assertEqual(w.filename, __file__)
|
||||
self.assertIn("returned 'int'", str(w.warning))
|
||||
|
||||
with self.assertWarns(DeprecationWarning) as w:
|
||||
Foo('test2').run()
|
||||
self.assertIn('It is deprecated to return a value that is not None', str(w.warning))
|
||||
self.assertIn('test2', str(w.warning))
|
||||
self.assertEqual(w.filename, __file__)
|
||||
self.assertIn("returned 'generator'", str(w.warning))
|
||||
|
||||
with self.assertWarns(DeprecationWarning) as w:
|
||||
Foo('test3').run()
|
||||
self.assertIn('It is deprecated to return a value that is not None', str(w.warning))
|
||||
self.assertIn('test3', str(w.warning))
|
||||
self.assertEqual(w.filename, __file__)
|
||||
self.assertIn(f'returned {Nothing.__name__!r}', str(w.warning))
|
||||
|
||||
def test_deprecation_of_return_val_from_test_async_method(self):
|
||||
class Foo(unittest.TestCase):
|
||||
async def test1(self):
|
||||
return 1
|
||||
|
||||
with self.assertWarns(DeprecationWarning) as w:
|
||||
warnings.filterwarnings('ignore',
|
||||
'coroutine .* was never awaited', RuntimeWarning)
|
||||
Foo('test1').run()
|
||||
support.gc_collect()
|
||||
self.assertIn('It is deprecated to return a value that is not None', str(w.warning))
|
||||
self.assertIn('test1', str(w.warning))
|
||||
self.assertEqual(w.filename, __file__)
|
||||
self.assertIn("returned 'coroutine'", str(w.warning))
|
||||
self.assertIn(
|
||||
'Maybe you forgot to use IsolatedAsyncioTestCase as the base class?',
|
||||
str(w.warning),
|
||||
)
|
||||
|
||||
def _check_call_order__subtests(self, result, events, expected_events):
|
||||
class Foo(Test.LoggingTestCase):
|
||||
@@ -678,16 +705,136 @@ class Test_TestCase(unittest.TestCase, TestEquality, TestHashing):
|
||||
self.assertRaises(self.failureException, self.assertIsNot, thing, thing)
|
||||
|
||||
def testAssertIsInstance(self):
|
||||
thing = []
|
||||
thing = List()
|
||||
self.assertIsInstance(thing, list)
|
||||
self.assertRaises(self.failureException, self.assertIsInstance,
|
||||
thing, dict)
|
||||
self.assertIsInstance(thing, (int, list))
|
||||
with self.assertRaises(self.failureException) as cm:
|
||||
self.assertIsInstance(thing, int)
|
||||
self.assertEqual(str(cm.exception),
|
||||
"[] is not an instance of <class 'int'>")
|
||||
with self.assertRaises(self.failureException) as cm:
|
||||
self.assertIsInstance(thing, (int, float))
|
||||
self.assertEqual(str(cm.exception),
|
||||
"[] is not an instance of any of (<class 'int'>, <class 'float'>)")
|
||||
|
||||
with self.assertRaises(self.failureException) as cm:
|
||||
self.assertIsInstance(thing, int, 'ababahalamaha')
|
||||
self.assertIn('ababahalamaha', str(cm.exception))
|
||||
with self.assertRaises(self.failureException) as cm:
|
||||
self.assertIsInstance(thing, int, msg='ababahalamaha')
|
||||
self.assertIn('ababahalamaha', str(cm.exception))
|
||||
|
||||
def testAssertNotIsInstance(self):
|
||||
thing = []
|
||||
self.assertNotIsInstance(thing, dict)
|
||||
self.assertRaises(self.failureException, self.assertNotIsInstance,
|
||||
thing, list)
|
||||
thing = List()
|
||||
self.assertNotIsInstance(thing, int)
|
||||
self.assertNotIsInstance(thing, (int, float))
|
||||
with self.assertRaises(self.failureException) as cm:
|
||||
self.assertNotIsInstance(thing, list)
|
||||
self.assertEqual(str(cm.exception),
|
||||
"[] is an instance of <class 'list'>")
|
||||
with self.assertRaises(self.failureException) as cm:
|
||||
self.assertNotIsInstance(thing, (int, list))
|
||||
self.assertEqual(str(cm.exception),
|
||||
"[] is an instance of <class 'list'>")
|
||||
|
||||
with self.assertRaises(self.failureException) as cm:
|
||||
self.assertNotIsInstance(thing, list, 'ababahalamaha')
|
||||
self.assertIn('ababahalamaha', str(cm.exception))
|
||||
with self.assertRaises(self.failureException) as cm:
|
||||
self.assertNotIsInstance(thing, list, msg='ababahalamaha')
|
||||
self.assertIn('ababahalamaha', str(cm.exception))
|
||||
|
||||
def testAssertIsSubclass(self):
|
||||
self.assertIsSubclass(List, list)
|
||||
self.assertIsSubclass(List, (int, list))
|
||||
with self.assertRaises(self.failureException) as cm:
|
||||
self.assertIsSubclass(List, int)
|
||||
self.assertEqual(str(cm.exception),
|
||||
f"{List!r} is not a subclass of <class 'int'>")
|
||||
with self.assertRaises(self.failureException) as cm:
|
||||
self.assertIsSubclass(List, (int, float))
|
||||
self.assertEqual(str(cm.exception),
|
||||
f"{List!r} is not a subclass of any of (<class 'int'>, <class 'float'>)")
|
||||
with self.assertRaises(self.failureException) as cm:
|
||||
self.assertIsSubclass(1, int)
|
||||
self.assertEqual(str(cm.exception), "1 is not a class")
|
||||
|
||||
with self.assertRaises(self.failureException) as cm:
|
||||
self.assertIsSubclass(List, int, 'ababahalamaha')
|
||||
self.assertIn('ababahalamaha', str(cm.exception))
|
||||
with self.assertRaises(self.failureException) as cm:
|
||||
self.assertIsSubclass(List, int, msg='ababahalamaha')
|
||||
self.assertIn('ababahalamaha', str(cm.exception))
|
||||
|
||||
def testAssertNotIsSubclass(self):
|
||||
self.assertNotIsSubclass(List, int)
|
||||
self.assertNotIsSubclass(List, (int, float))
|
||||
with self.assertRaises(self.failureException) as cm:
|
||||
self.assertNotIsSubclass(List, list)
|
||||
self.assertEqual(str(cm.exception),
|
||||
f"{List!r} is a subclass of <class 'list'>")
|
||||
with self.assertRaises(self.failureException) as cm:
|
||||
self.assertNotIsSubclass(List, (int, list))
|
||||
self.assertEqual(str(cm.exception),
|
||||
f"{List!r} is a subclass of <class 'list'>")
|
||||
with self.assertRaises(self.failureException) as cm:
|
||||
self.assertNotIsSubclass(1, int)
|
||||
self.assertEqual(str(cm.exception), "1 is not a class")
|
||||
|
||||
with self.assertRaises(self.failureException) as cm:
|
||||
self.assertNotIsSubclass(List, list, 'ababahalamaha')
|
||||
self.assertIn('ababahalamaha', str(cm.exception))
|
||||
with self.assertRaises(self.failureException) as cm:
|
||||
self.assertNotIsSubclass(List, list, msg='ababahalamaha')
|
||||
self.assertIn('ababahalamaha', str(cm.exception))
|
||||
|
||||
def testAssertHasAttr(self):
|
||||
a = List()
|
||||
a.x = 1
|
||||
self.assertHasAttr(a, 'x')
|
||||
with self.assertRaises(self.failureException) as cm:
|
||||
self.assertHasAttr(a, 'y')
|
||||
self.assertEqual(str(cm.exception),
|
||||
"'List' object has no attribute 'y'")
|
||||
with self.assertRaises(self.failureException) as cm:
|
||||
self.assertHasAttr(List, 'spam')
|
||||
self.assertEqual(str(cm.exception),
|
||||
"type object 'List' has no attribute 'spam'")
|
||||
with self.assertRaises(self.failureException) as cm:
|
||||
self.assertHasAttr(sys, 'nonexistent')
|
||||
self.assertEqual(str(cm.exception),
|
||||
"module 'sys' has no attribute 'nonexistent'")
|
||||
|
||||
with self.assertRaises(self.failureException) as cm:
|
||||
self.assertHasAttr(a, 'y', 'ababahalamaha')
|
||||
self.assertIn('ababahalamaha', str(cm.exception))
|
||||
with self.assertRaises(self.failureException) as cm:
|
||||
self.assertHasAttr(a, 'y', msg='ababahalamaha')
|
||||
self.assertIn('ababahalamaha', str(cm.exception))
|
||||
|
||||
def testAssertNotHasAttr(self):
|
||||
a = List()
|
||||
a.x = 1
|
||||
self.assertNotHasAttr(a, 'y')
|
||||
with self.assertRaises(self.failureException) as cm:
|
||||
self.assertNotHasAttr(a, 'x')
|
||||
self.assertEqual(str(cm.exception),
|
||||
"'List' object has unexpected attribute 'x'")
|
||||
with self.assertRaises(self.failureException) as cm:
|
||||
self.assertNotHasAttr(List, 'append')
|
||||
self.assertEqual(str(cm.exception),
|
||||
"type object 'List' has unexpected attribute 'append'")
|
||||
with self.assertRaises(self.failureException) as cm:
|
||||
self.assertNotHasAttr(sys, 'modules')
|
||||
self.assertEqual(str(cm.exception),
|
||||
"module 'sys' has unexpected attribute 'modules'")
|
||||
|
||||
with self.assertRaises(self.failureException) as cm:
|
||||
self.assertNotHasAttr(a, 'x', 'ababahalamaha')
|
||||
self.assertIn('ababahalamaha', str(cm.exception))
|
||||
with self.assertRaises(self.failureException) as cm:
|
||||
self.assertNotHasAttr(a, 'x', msg='ababahalamaha')
|
||||
self.assertIn('ababahalamaha', str(cm.exception))
|
||||
|
||||
def testAssertIn(self):
|
||||
animals = {'monkey': 'banana', 'cow': 'grass', 'seal': 'fish'}
|
||||
@@ -1842,6 +1989,186 @@ test case
|
||||
pass
|
||||
self.assertIsNone(value)
|
||||
|
||||
def testAssertStartsWith(self):
|
||||
self.assertStartsWith('ababahalamaha', 'ababa')
|
||||
self.assertStartsWith('ababahalamaha', ('x', 'ababa', 'y'))
|
||||
self.assertStartsWith(UserString('ababahalamaha'), 'ababa')
|
||||
self.assertStartsWith(UserString('ababahalamaha'), ('x', 'ababa', 'y'))
|
||||
self.assertStartsWith(bytearray(b'ababahalamaha'), b'ababa')
|
||||
self.assertStartsWith(bytearray(b'ababahalamaha'), (b'x', b'ababa', b'y'))
|
||||
self.assertStartsWith(b'ababahalamaha', bytearray(b'ababa'))
|
||||
self.assertStartsWith(b'ababahalamaha',
|
||||
(bytearray(b'x'), bytearray(b'ababa'), bytearray(b'y')))
|
||||
|
||||
with self.assertRaises(self.failureException) as cm:
|
||||
self.assertStartsWith('ababahalamaha', 'amaha')
|
||||
self.assertEqual(str(cm.exception),
|
||||
"'ababahalamaha' doesn't start with 'amaha'")
|
||||
with self.assertRaises(self.failureException) as cm:
|
||||
self.assertStartsWith('ababahalamaha', ('x', 'y'))
|
||||
self.assertEqual(str(cm.exception),
|
||||
"'ababahalamaha' doesn't start with any of ('x', 'y')")
|
||||
|
||||
with self.assertRaises(self.failureException) as cm:
|
||||
self.assertStartsWith(b'ababahalamaha', 'ababa')
|
||||
self.assertEqual(str(cm.exception), 'Expected str, not bytes')
|
||||
with self.assertRaises(self.failureException) as cm:
|
||||
self.assertStartsWith(b'ababahalamaha', ('amaha', 'ababa'))
|
||||
self.assertEqual(str(cm.exception), 'Expected str, not bytes')
|
||||
with self.assertRaises(self.failureException) as cm:
|
||||
self.assertStartsWith([], 'ababa')
|
||||
self.assertEqual(str(cm.exception), 'Expected str, not list')
|
||||
with self.assertRaises(self.failureException) as cm:
|
||||
self.assertStartsWith('ababahalamaha', b'ababa')
|
||||
self.assertEqual(str(cm.exception), 'Expected bytes, not str')
|
||||
with self.assertRaises(self.failureException) as cm:
|
||||
self.assertStartsWith('ababahalamaha', (b'amaha', b'ababa'))
|
||||
self.assertEqual(str(cm.exception), 'Expected bytes, not str')
|
||||
with self.assertRaises(TypeError):
|
||||
self.assertStartsWith('ababahalamaha', ord('a'))
|
||||
|
||||
with self.assertRaises(self.failureException) as cm:
|
||||
self.assertStartsWith('ababahalamaha', 'amaha', 'abracadabra')
|
||||
self.assertIn('ababahalamaha', str(cm.exception))
|
||||
with self.assertRaises(self.failureException) as cm:
|
||||
self.assertStartsWith('ababahalamaha', 'amaha', msg='abracadabra')
|
||||
self.assertIn('ababahalamaha', str(cm.exception))
|
||||
|
||||
def testAssertNotStartsWith(self):
|
||||
self.assertNotStartsWith('ababahalamaha', 'amaha')
|
||||
self.assertNotStartsWith('ababahalamaha', ('x', 'amaha', 'y'))
|
||||
self.assertNotStartsWith(UserString('ababahalamaha'), 'amaha')
|
||||
self.assertNotStartsWith(UserString('ababahalamaha'), ('x', 'amaha', 'y'))
|
||||
self.assertNotStartsWith(bytearray(b'ababahalamaha'), b'amaha')
|
||||
self.assertNotStartsWith(bytearray(b'ababahalamaha'), (b'x', b'amaha', b'y'))
|
||||
self.assertNotStartsWith(b'ababahalamaha', bytearray(b'amaha'))
|
||||
self.assertNotStartsWith(b'ababahalamaha',
|
||||
(bytearray(b'x'), bytearray(b'amaha'), bytearray(b'y')))
|
||||
|
||||
with self.assertRaises(self.failureException) as cm:
|
||||
self.assertNotStartsWith('ababahalamaha', 'ababa')
|
||||
self.assertEqual(str(cm.exception),
|
||||
"'ababahalamaha' starts with 'ababa'")
|
||||
with self.assertRaises(self.failureException) as cm:
|
||||
self.assertNotStartsWith('ababahalamaha', ('x', 'ababa', 'y'))
|
||||
self.assertEqual(str(cm.exception),
|
||||
"'ababahalamaha' starts with 'ababa'")
|
||||
|
||||
with self.assertRaises(self.failureException) as cm:
|
||||
self.assertNotStartsWith(b'ababahalamaha', 'ababa')
|
||||
self.assertEqual(str(cm.exception), 'Expected str, not bytes')
|
||||
with self.assertRaises(self.failureException) as cm:
|
||||
self.assertNotStartsWith(b'ababahalamaha', ('amaha', 'ababa'))
|
||||
self.assertEqual(str(cm.exception), 'Expected str, not bytes')
|
||||
with self.assertRaises(self.failureException) as cm:
|
||||
self.assertNotStartsWith([], 'ababa')
|
||||
self.assertEqual(str(cm.exception), 'Expected str, not list')
|
||||
with self.assertRaises(self.failureException) as cm:
|
||||
self.assertNotStartsWith('ababahalamaha', b'ababa')
|
||||
self.assertEqual(str(cm.exception), 'Expected bytes, not str')
|
||||
with self.assertRaises(self.failureException) as cm:
|
||||
self.assertNotStartsWith('ababahalamaha', (b'amaha', b'ababa'))
|
||||
self.assertEqual(str(cm.exception), 'Expected bytes, not str')
|
||||
with self.assertRaises(TypeError):
|
||||
self.assertNotStartsWith('ababahalamaha', ord('a'))
|
||||
|
||||
with self.assertRaises(self.failureException) as cm:
|
||||
self.assertNotStartsWith('ababahalamaha', 'ababa', 'abracadabra')
|
||||
self.assertIn('ababahalamaha', str(cm.exception))
|
||||
with self.assertRaises(self.failureException) as cm:
|
||||
self.assertNotStartsWith('ababahalamaha', 'ababa', msg='abracadabra')
|
||||
self.assertIn('ababahalamaha', str(cm.exception))
|
||||
|
||||
def testAssertEndsWith(self):
|
||||
self.assertEndsWith('ababahalamaha', 'amaha')
|
||||
self.assertEndsWith('ababahalamaha', ('x', 'amaha', 'y'))
|
||||
self.assertEndsWith(UserString('ababahalamaha'), 'amaha')
|
||||
self.assertEndsWith(UserString('ababahalamaha'), ('x', 'amaha', 'y'))
|
||||
self.assertEndsWith(bytearray(b'ababahalamaha'), b'amaha')
|
||||
self.assertEndsWith(bytearray(b'ababahalamaha'), (b'x', b'amaha', b'y'))
|
||||
self.assertEndsWith(b'ababahalamaha', bytearray(b'amaha'))
|
||||
self.assertEndsWith(b'ababahalamaha',
|
||||
(bytearray(b'x'), bytearray(b'amaha'), bytearray(b'y')))
|
||||
|
||||
with self.assertRaises(self.failureException) as cm:
|
||||
self.assertEndsWith('ababahalamaha', 'ababa')
|
||||
self.assertEqual(str(cm.exception),
|
||||
"'ababahalamaha' doesn't end with 'ababa'")
|
||||
with self.assertRaises(self.failureException) as cm:
|
||||
self.assertEndsWith('ababahalamaha', ('x', 'y'))
|
||||
self.assertEqual(str(cm.exception),
|
||||
"'ababahalamaha' doesn't end with any of ('x', 'y')")
|
||||
|
||||
with self.assertRaises(self.failureException) as cm:
|
||||
self.assertEndsWith(b'ababahalamaha', 'amaha')
|
||||
self.assertEqual(str(cm.exception), 'Expected str, not bytes')
|
||||
with self.assertRaises(self.failureException) as cm:
|
||||
self.assertEndsWith(b'ababahalamaha', ('ababa', 'amaha'))
|
||||
self.assertEqual(str(cm.exception), 'Expected str, not bytes')
|
||||
with self.assertRaises(self.failureException) as cm:
|
||||
self.assertEndsWith([], 'amaha')
|
||||
self.assertEqual(str(cm.exception), 'Expected str, not list')
|
||||
with self.assertRaises(self.failureException) as cm:
|
||||
self.assertEndsWith('ababahalamaha', b'amaha')
|
||||
self.assertEqual(str(cm.exception), 'Expected bytes, not str')
|
||||
with self.assertRaises(self.failureException) as cm:
|
||||
self.assertEndsWith('ababahalamaha', (b'ababa', b'amaha'))
|
||||
self.assertEqual(str(cm.exception), 'Expected bytes, not str')
|
||||
with self.assertRaises(TypeError):
|
||||
self.assertEndsWith('ababahalamaha', ord('a'))
|
||||
|
||||
with self.assertRaises(self.failureException) as cm:
|
||||
self.assertEndsWith('ababahalamaha', 'ababa', 'abracadabra')
|
||||
self.assertIn('ababahalamaha', str(cm.exception))
|
||||
with self.assertRaises(self.failureException) as cm:
|
||||
self.assertEndsWith('ababahalamaha', 'ababa', msg='abracadabra')
|
||||
self.assertIn('ababahalamaha', str(cm.exception))
|
||||
|
||||
def testAssertNotEndsWith(self):
|
||||
self.assertNotEndsWith('ababahalamaha', 'ababa')
|
||||
self.assertNotEndsWith('ababahalamaha', ('x', 'ababa', 'y'))
|
||||
self.assertNotEndsWith(UserString('ababahalamaha'), 'ababa')
|
||||
self.assertNotEndsWith(UserString('ababahalamaha'), ('x', 'ababa', 'y'))
|
||||
self.assertNotEndsWith(bytearray(b'ababahalamaha'), b'ababa')
|
||||
self.assertNotEndsWith(bytearray(b'ababahalamaha'), (b'x', b'ababa', b'y'))
|
||||
self.assertNotEndsWith(b'ababahalamaha', bytearray(b'ababa'))
|
||||
self.assertNotEndsWith(b'ababahalamaha',
|
||||
(bytearray(b'x'), bytearray(b'ababa'), bytearray(b'y')))
|
||||
|
||||
with self.assertRaises(self.failureException) as cm:
|
||||
self.assertNotEndsWith('ababahalamaha', 'amaha')
|
||||
self.assertEqual(str(cm.exception),
|
||||
"'ababahalamaha' ends with 'amaha'")
|
||||
with self.assertRaises(self.failureException) as cm:
|
||||
self.assertNotEndsWith('ababahalamaha', ('x', 'amaha', 'y'))
|
||||
self.assertEqual(str(cm.exception),
|
||||
"'ababahalamaha' ends with 'amaha'")
|
||||
|
||||
with self.assertRaises(self.failureException) as cm:
|
||||
self.assertNotEndsWith(b'ababahalamaha', 'amaha')
|
||||
self.assertEqual(str(cm.exception), 'Expected str, not bytes')
|
||||
with self.assertRaises(self.failureException) as cm:
|
||||
self.assertNotEndsWith(b'ababahalamaha', ('ababa', 'amaha'))
|
||||
self.assertEqual(str(cm.exception), 'Expected str, not bytes')
|
||||
with self.assertRaises(self.failureException) as cm:
|
||||
self.assertNotEndsWith([], 'amaha')
|
||||
self.assertEqual(str(cm.exception), 'Expected str, not list')
|
||||
with self.assertRaises(self.failureException) as cm:
|
||||
self.assertNotEndsWith('ababahalamaha', b'amaha')
|
||||
self.assertEqual(str(cm.exception), 'Expected bytes, not str')
|
||||
with self.assertRaises(self.failureException) as cm:
|
||||
self.assertNotEndsWith('ababahalamaha', (b'ababa', b'amaha'))
|
||||
self.assertEqual(str(cm.exception), 'Expected bytes, not str')
|
||||
with self.assertRaises(TypeError):
|
||||
self.assertNotEndsWith('ababahalamaha', ord('a'))
|
||||
|
||||
with self.assertRaises(self.failureException) as cm:
|
||||
self.assertNotEndsWith('ababahalamaha', 'amaha', 'abracadabra')
|
||||
self.assertIn('ababahalamaha', str(cm.exception))
|
||||
with self.assertRaises(self.failureException) as cm:
|
||||
self.assertNotEndsWith('ababahalamaha', 'amaha', msg='abracadabra')
|
||||
self.assertIn('ababahalamaha', str(cm.exception))
|
||||
|
||||
def testDeprecatedFailMethods(self):
|
||||
"""Test that the deprecated fail* methods get removed in 3.12"""
|
||||
deprecated_names = [
|
||||
|
||||
+57
-7
@@ -1,15 +1,17 @@
|
||||
import os.path
|
||||
from os.path import abspath
|
||||
import pickle
|
||||
import re
|
||||
import sys
|
||||
import types
|
||||
import pickle
|
||||
from test import support
|
||||
from test.support import import_helper
|
||||
|
||||
import unittest
|
||||
import unittest.mock
|
||||
from importlib._bootstrap_external import NamespaceLoader
|
||||
from os.path import abspath
|
||||
|
||||
import test.test_unittest
|
||||
from test import support
|
||||
from test.support import import_helper
|
||||
from test.test_importlib import util as test_util
|
||||
|
||||
|
||||
class TestableTestProgram(unittest.TestProgram):
|
||||
@@ -395,7 +397,7 @@ class TestDiscovery(unittest.TestCase):
|
||||
self.addCleanup(restore_isdir)
|
||||
|
||||
_find_tests_args = []
|
||||
def _find_tests(start_dir, pattern):
|
||||
def _find_tests(start_dir, pattern, namespace=None):
|
||||
_find_tests_args.append((start_dir, pattern))
|
||||
return ['tests']
|
||||
loader._find_tests = _find_tests
|
||||
@@ -815,7 +817,7 @@ class TestDiscovery(unittest.TestCase):
|
||||
expectedPath = os.path.abspath(os.path.dirname(test.test_unittest.__file__))
|
||||
|
||||
self.wasRun = False
|
||||
def _find_tests(start_dir, pattern):
|
||||
def _find_tests(start_dir, pattern, namespace=None):
|
||||
self.wasRun = True
|
||||
self.assertEqual(start_dir, expectedPath)
|
||||
return tests
|
||||
@@ -848,6 +850,54 @@ class TestDiscovery(unittest.TestCase):
|
||||
'Can not use builtin modules '
|
||||
'as dotted module names')
|
||||
|
||||
def test_discovery_from_dotted_namespace_packages(self):
|
||||
loader = unittest.TestLoader()
|
||||
|
||||
package = types.ModuleType('package')
|
||||
package.__name__ = "tests"
|
||||
package.__path__ = ['/a', '/b']
|
||||
package.__file__ = None
|
||||
package.__spec__ = types.SimpleNamespace(
|
||||
name=package.__name__,
|
||||
loader=NamespaceLoader(package.__name__, package.__path__, None),
|
||||
submodule_search_locations=['/a', '/b']
|
||||
)
|
||||
|
||||
def _import(packagename, *args, **kwargs):
|
||||
sys.modules[packagename] = package
|
||||
return package
|
||||
|
||||
_find_tests_args = []
|
||||
def _find_tests(start_dir, pattern, namespace=None):
|
||||
_find_tests_args.append((start_dir, pattern))
|
||||
return ['%s/tests' % start_dir]
|
||||
|
||||
loader._find_tests = _find_tests
|
||||
loader.suiteClass = list
|
||||
|
||||
with unittest.mock.patch('builtins.__import__', _import):
|
||||
# Since loader.discover() can modify sys.path, restore it when done.
|
||||
with import_helper.DirsOnSysPath():
|
||||
# Make sure to remove 'package' from sys.modules when done.
|
||||
with test_util.uncache('package'):
|
||||
suite = loader.discover('package')
|
||||
|
||||
self.assertEqual(suite, ['/a/tests', '/b/tests'])
|
||||
|
||||
def test_discovery_start_dir_is_namespace(self):
|
||||
"""Subdirectory discovery not affected if start_dir is a namespace pkg."""
|
||||
loader = unittest.TestLoader()
|
||||
with (
|
||||
import_helper.DirsOnSysPath(os.path.join(os.path.dirname(__file__))),
|
||||
test_util.uncache('namespace_test_pkg')
|
||||
):
|
||||
suite = loader.discover('namespace_test_pkg')
|
||||
self.assertEqual(
|
||||
{list(suite)[0]._tests[0].__module__ for suite in suite._tests if list(suite)},
|
||||
# files under namespace_test_pkg.noop not discovered.
|
||||
{'namespace_test_pkg.test_foo', 'namespace_test_pkg.bar.test_bar'},
|
||||
)
|
||||
|
||||
def test_discovery_failed_discovery(self):
|
||||
from test.test_importlib import util
|
||||
|
||||
|
||||
+2
-2
@@ -1,9 +1,9 @@
|
||||
import functools
|
||||
import sys
|
||||
import types
|
||||
|
||||
import unittest
|
||||
|
||||
|
||||
class Test_TestLoader(unittest.TestCase):
|
||||
|
||||
### Basic object tests
|
||||
@@ -76,7 +76,7 @@ class Test_TestLoader(unittest.TestCase):
|
||||
|
||||
loader = unittest.TestLoader()
|
||||
# This has to be false for the test to succeed
|
||||
self.assertFalse('runTest'.startswith(loader.testMethodPrefix))
|
||||
self.assertNotStartsWith('runTest', loader.testMethodPrefix)
|
||||
|
||||
suite = loader.loadTestsFromTestCase(Foo)
|
||||
self.assertIsInstance(suite, loader.suiteClass)
|
||||
|
||||
+8
-8
@@ -1,9 +1,10 @@
|
||||
import os
|
||||
import sys
|
||||
import subprocess
|
||||
from test import support
|
||||
import sys
|
||||
import unittest
|
||||
|
||||
import test.test_unittest
|
||||
from test import support
|
||||
from test.test_unittest.test_result import BufferedWriter
|
||||
|
||||
|
||||
@@ -135,14 +136,14 @@ class Test_TestProgram(unittest.TestCase):
|
||||
argv=["foobar"],
|
||||
testRunner=unittest.TextTestRunner(stream=stream),
|
||||
testLoader=self.TestLoader(self.FooBar))
|
||||
self.assertTrue(hasattr(program, 'result'))
|
||||
self.assertHasAttr(program, 'result')
|
||||
out = stream.getvalue()
|
||||
self.assertIn('\nFAIL: testFail ', out)
|
||||
self.assertIn('\nERROR: testError ', out)
|
||||
self.assertIn('\nUNEXPECTED SUCCESS: testUnexpectedSuccess ', out)
|
||||
expected = ('\n\nFAILED (failures=1, errors=1, skipped=1, '
|
||||
'expected failures=1, unexpected successes=1)\n')
|
||||
self.assertTrue(out.endswith(expected))
|
||||
self.assertEndsWith(out, expected)
|
||||
|
||||
def test_Exit(self):
|
||||
stream = BufferedWriter()
|
||||
@@ -159,7 +160,7 @@ class Test_TestProgram(unittest.TestCase):
|
||||
self.assertIn('\nUNEXPECTED SUCCESS: testUnexpectedSuccess ', out)
|
||||
expected = ('\n\nFAILED (failures=1, errors=1, skipped=1, '
|
||||
'expected failures=1, unexpected successes=1)\n')
|
||||
self.assertTrue(out.endswith(expected))
|
||||
self.assertEndsWith(out, expected)
|
||||
|
||||
def test_ExitAsDefault(self):
|
||||
stream = BufferedWriter()
|
||||
@@ -174,7 +175,7 @@ class Test_TestProgram(unittest.TestCase):
|
||||
self.assertIn('\nUNEXPECTED SUCCESS: testUnexpectedSuccess ', out)
|
||||
expected = ('\n\nFAILED (failures=1, errors=1, skipped=1, '
|
||||
'expected failures=1, unexpected successes=1)\n')
|
||||
self.assertTrue(out.endswith(expected))
|
||||
self.assertEndsWith(out, expected)
|
||||
|
||||
def test_ExitSkippedSuite(self):
|
||||
stream = BufferedWriter()
|
||||
@@ -186,7 +187,7 @@ class Test_TestProgram(unittest.TestCase):
|
||||
self.assertEqual(cm.exception.code, 0)
|
||||
out = stream.getvalue()
|
||||
expected = '\n\nOK (skipped=1)\n'
|
||||
self.assertTrue(out.endswith(expected))
|
||||
self.assertEndsWith(out, expected)
|
||||
|
||||
def test_ExitEmptySuite(self):
|
||||
stream = BufferedWriter()
|
||||
@@ -506,7 +507,6 @@ class TestCommandLineArgs(unittest.TestCase):
|
||||
self.assertEqual(program.testNamePatterns, ['*foo*', '*bar*', '*pat*'])
|
||||
|
||||
@unittest.expectedFailureIf(sys.platform != 'win32', 'TODO: RUSTPYTHON')
|
||||
|
||||
def testSelectedTestNamesFunctionalTest(self):
|
||||
def run_unittest(args):
|
||||
# Use -E to ignore PYTHONSAFEPATH env var
|
||||
|
||||
+15
-11
@@ -4,8 +4,12 @@ import textwrap
|
||||
import traceback
|
||||
import unittest
|
||||
from unittest.util import strclass
|
||||
from test.support import warnings_helper
|
||||
from test.support import captured_stdout, force_not_colorized_test_class
|
||||
|
||||
from test.support import (
|
||||
captured_stdout,
|
||||
force_not_colorized_test_class,
|
||||
warnings_helper,
|
||||
)
|
||||
from test.test_unittest.support import BufferedWriter
|
||||
|
||||
|
||||
@@ -13,7 +17,7 @@ class MockTraceback(object):
|
||||
class TracebackException:
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.capture_locals = kwargs.get('capture_locals', False)
|
||||
def format(self):
|
||||
def format(self, **kwargs):
|
||||
result = ['A traceback']
|
||||
if self.capture_locals:
|
||||
result.append('locals')
|
||||
@@ -186,7 +190,7 @@ class Test_TestResult(unittest.TestCase):
|
||||
test = Foo('test_1')
|
||||
try:
|
||||
test.fail("foo")
|
||||
except:
|
||||
except AssertionError:
|
||||
exc_info_tuple = sys.exc_info()
|
||||
|
||||
result = unittest.TestResult()
|
||||
@@ -214,7 +218,7 @@ class Test_TestResult(unittest.TestCase):
|
||||
def get_exc_info():
|
||||
try:
|
||||
test.fail("foo")
|
||||
except:
|
||||
except AssertionError:
|
||||
return sys.exc_info()
|
||||
|
||||
exc_info_tuple = get_exc_info()
|
||||
@@ -241,9 +245,9 @@ class Test_TestResult(unittest.TestCase):
|
||||
try:
|
||||
try:
|
||||
test.fail("foo")
|
||||
except:
|
||||
except AssertionError:
|
||||
raise ValueError(42)
|
||||
except:
|
||||
except ValueError:
|
||||
return sys.exc_info()
|
||||
|
||||
exc_info_tuple = get_exc_info()
|
||||
@@ -271,7 +275,7 @@ class Test_TestResult(unittest.TestCase):
|
||||
loop.__cause__ = loop
|
||||
loop.__context__ = loop
|
||||
raise loop
|
||||
except:
|
||||
except Exception:
|
||||
return sys.exc_info()
|
||||
|
||||
exc_info_tuple = get_exc_info()
|
||||
@@ -300,7 +304,7 @@ class Test_TestResult(unittest.TestCase):
|
||||
ex1.__cause__ = ex2
|
||||
ex2.__context__ = ex1
|
||||
raise C
|
||||
except:
|
||||
except Exception:
|
||||
return sys.exc_info()
|
||||
|
||||
exc_info_tuple = get_exc_info()
|
||||
@@ -345,7 +349,7 @@ class Test_TestResult(unittest.TestCase):
|
||||
test = Foo('test_1')
|
||||
try:
|
||||
raise TypeError()
|
||||
except:
|
||||
except TypeError:
|
||||
exc_info_tuple = sys.exc_info()
|
||||
|
||||
result = unittest.TestResult()
|
||||
@@ -454,7 +458,7 @@ class Test_TestResult(unittest.TestCase):
|
||||
self.assertTrue(result.failfast)
|
||||
result = runner.run(test)
|
||||
stream.flush()
|
||||
self.assertTrue(stream.getvalue().endswith('\n\nOK\n'))
|
||||
self.assertEndsWith(stream.getvalue(), '\n\nOK\n')
|
||||
|
||||
|
||||
@force_not_colorized_test_class
|
||||
|
||||
+2
-3
@@ -1,13 +1,12 @@
|
||||
import io
|
||||
import os
|
||||
import sys
|
||||
import pickle
|
||||
import subprocess
|
||||
from test import support
|
||||
|
||||
import sys
|
||||
import unittest
|
||||
from unittest.case import _Outcome
|
||||
|
||||
from test import support
|
||||
from test.test_unittest.support import (
|
||||
BufferedWriter,
|
||||
LoggingResult,
|
||||
|
||||
-1
@@ -1,6 +1,5 @@
|
||||
import io
|
||||
import sys
|
||||
|
||||
import unittest
|
||||
|
||||
|
||||
|
||||
+3
@@ -1,5 +1,6 @@
|
||||
import unittest
|
||||
|
||||
from test.support import force_not_colorized
|
||||
from test.test_unittest.support import LoggingResult
|
||||
|
||||
|
||||
@@ -293,6 +294,7 @@ class Test_TestSkipping(unittest.TestCase):
|
||||
self.assertFalse(result.unexpectedSuccesses)
|
||||
self.assertTrue(result.wasSuccessful())
|
||||
|
||||
@force_not_colorized
|
||||
def test_expected_failure_and_fail_in_cleanup(self):
|
||||
class Foo(unittest.TestCase):
|
||||
@unittest.expectedFailure
|
||||
@@ -372,6 +374,7 @@ class Test_TestSkipping(unittest.TestCase):
|
||||
self.assertEqual(result.unexpectedSuccesses, [test])
|
||||
self.assertFalse(result.wasSuccessful())
|
||||
|
||||
@force_not_colorized
|
||||
def test_unexpected_success_and_fail_in_cleanup(self):
|
||||
class Foo(unittest.TestCase):
|
||||
@unittest.expectedFailure
|
||||
|
||||
Vendored
+2
-3
@@ -1,10 +1,9 @@
|
||||
import unittest
|
||||
|
||||
import gc
|
||||
import sys
|
||||
import unittest
|
||||
import weakref
|
||||
from test.test_unittest.support import LoggingResult, TestEquality
|
||||
|
||||
from test.test_unittest.support import LoggingResult, TestEquality
|
||||
|
||||
### Support code for Test_TestSuite
|
||||
################################################################
|
||||
|
||||
Vendored
+5
-1
@@ -1,5 +1,9 @@
|
||||
import unittest
|
||||
from unittest.util import safe_repr, sorted_list_difference, unorderable_list_difference
|
||||
from unittest.util import (
|
||||
safe_repr,
|
||||
sorted_list_difference,
|
||||
unorderable_list_difference,
|
||||
)
|
||||
|
||||
|
||||
class TestUtil(unittest.TestCase):
|
||||
|
||||
Vendored
+24
-9
@@ -27,7 +27,7 @@ Further information is available in the bundled documentation, and from
|
||||
http://docs.python.org/library/unittest.html
|
||||
|
||||
Copyright (c) 1999-2003 Steve Purcell
|
||||
Copyright (c) 2003-2010 Python Software Foundation
|
||||
Copyright (c) 2003 Python Software Foundation
|
||||
This module is free software, and you may redistribute it and/or modify
|
||||
it under the same terms as Python itself, so long as this copyright message
|
||||
and disclaimer are retained in their original form.
|
||||
@@ -53,15 +53,30 @@ __all__ = ['TestResult', 'TestCase', 'IsolatedAsyncioTestCase', 'TestSuite',
|
||||
|
||||
__unittest = True
|
||||
|
||||
from .result import TestResult
|
||||
from .case import (addModuleCleanup, TestCase, FunctionTestCase, SkipTest, skip,
|
||||
skipIf, skipUnless, expectedFailure, doModuleCleanups,
|
||||
enterModuleContext)
|
||||
from .suite import BaseTestSuite, TestSuite
|
||||
from .case import (
|
||||
FunctionTestCase,
|
||||
SkipTest,
|
||||
TestCase,
|
||||
addModuleCleanup,
|
||||
doModuleCleanups,
|
||||
enterModuleContext,
|
||||
expectedFailure,
|
||||
skip,
|
||||
skipIf,
|
||||
skipUnless,
|
||||
)
|
||||
from .loader import TestLoader, defaultTestLoader
|
||||
from .main import TestProgram, main
|
||||
from .runner import TextTestRunner, TextTestResult
|
||||
from .signals import installHandler, registerResult, removeResult, removeHandler
|
||||
from .main import TestProgram, main # noqa: F401
|
||||
from .result import TestResult
|
||||
from .runner import TextTestResult, TextTestRunner
|
||||
from .signals import (
|
||||
installHandler,
|
||||
registerResult,
|
||||
removeHandler,
|
||||
removeResult,
|
||||
)
|
||||
from .suite import BaseTestSuite, TestSuite # noqa: F401
|
||||
|
||||
# IsolatedAsyncioTestCase will be imported lazily.
|
||||
|
||||
|
||||
|
||||
Vendored
+1
@@ -1,6 +1,7 @@
|
||||
"""Main entry point"""
|
||||
|
||||
import sys
|
||||
|
||||
if sys.argv[0].endswith("__main__.py"):
|
||||
import os.path
|
||||
# We change sys.argv[0] to make help message more useful
|
||||
|
||||
Vendored
+1
-2
@@ -1,9 +1,8 @@
|
||||
import logging
|
||||
import collections
|
||||
import logging
|
||||
|
||||
from .case import _BaseTestCaseContext
|
||||
|
||||
|
||||
_LoggingWatcher = collections.namedtuple("_LoggingWatcher",
|
||||
["records", "output"])
|
||||
|
||||
|
||||
Vendored
+18
-6
@@ -75,9 +75,17 @@ class IsolatedAsyncioTestCase(TestCase):
|
||||
enter = cls.__aenter__
|
||||
exit = cls.__aexit__
|
||||
except AttributeError:
|
||||
raise TypeError(f"'{cls.__module__}.{cls.__qualname__}' object does "
|
||||
f"not support the asynchronous context manager protocol"
|
||||
) from None
|
||||
msg = (f"'{cls.__module__}.{cls.__qualname__}' object does "
|
||||
"not support the asynchronous context manager protocol")
|
||||
try:
|
||||
cls.__enter__
|
||||
cls.__exit__
|
||||
except AttributeError:
|
||||
pass
|
||||
else:
|
||||
msg += (" but it supports the context manager protocol. "
|
||||
"Did you mean to use enterContext()?")
|
||||
raise TypeError(msg) from None
|
||||
result = await enter(cm)
|
||||
self.addAsyncCleanup(exit, cm, None, None, None)
|
||||
return result
|
||||
@@ -91,9 +99,13 @@ class IsolatedAsyncioTestCase(TestCase):
|
||||
self._callAsync(self.asyncSetUp)
|
||||
|
||||
def _callTestMethod(self, method):
|
||||
if self._callMaybeAsync(method) is not None:
|
||||
warnings.warn(f'It is deprecated to return a value that is not None from a '
|
||||
f'test case ({method})', DeprecationWarning, stacklevel=4)
|
||||
result = self._callMaybeAsync(method)
|
||||
if result is not None:
|
||||
msg = (
|
||||
f'It is deprecated to return a value that is not None '
|
||||
f'from a test case ({method} returned {type(result).__name__!r})',
|
||||
)
|
||||
warnings.warn(msg, DeprecationWarning, stacklevel=4)
|
||||
|
||||
def _callTearDown(self):
|
||||
self._callAsync(self.asyncTearDown)
|
||||
|
||||
Vendored
+171
-16
@@ -1,20 +1,25 @@
|
||||
"""Test case implementation"""
|
||||
|
||||
import sys
|
||||
import functools
|
||||
import difflib
|
||||
import pprint
|
||||
import re
|
||||
import warnings
|
||||
import collections
|
||||
import contextlib
|
||||
import traceback
|
||||
import difflib
|
||||
import functools
|
||||
import pprint
|
||||
import re
|
||||
import sys
|
||||
import time
|
||||
import traceback
|
||||
import types
|
||||
import warnings
|
||||
|
||||
from . import result
|
||||
from .util import (strclass, safe_repr, _count_diff_all_purpose,
|
||||
_count_diff_hashable, _common_shorten_repr)
|
||||
from .util import (
|
||||
_common_shorten_repr,
|
||||
_count_diff_all_purpose,
|
||||
_count_diff_hashable,
|
||||
safe_repr,
|
||||
strclass,
|
||||
)
|
||||
|
||||
__unittest = True
|
||||
|
||||
@@ -111,8 +116,17 @@ def _enter_context(cm, addcleanup):
|
||||
enter = cls.__enter__
|
||||
exit = cls.__exit__
|
||||
except AttributeError:
|
||||
raise TypeError(f"'{cls.__module__}.{cls.__qualname__}' object does "
|
||||
f"not support the context manager protocol") from None
|
||||
msg = (f"'{cls.__module__}.{cls.__qualname__}' object does "
|
||||
"not support the context manager protocol")
|
||||
try:
|
||||
cls.__aenter__
|
||||
cls.__aexit__
|
||||
except AttributeError:
|
||||
pass
|
||||
else:
|
||||
msg += (" but it supports the asynchronous context manager "
|
||||
"protocol. Did you mean to use enterAsyncContext()?")
|
||||
raise TypeError(msg) from None
|
||||
result = enter(cm)
|
||||
addcleanup(exit, cm, None, None, None)
|
||||
return result
|
||||
@@ -603,9 +617,18 @@ class TestCase(object):
|
||||
self.setUp()
|
||||
|
||||
def _callTestMethod(self, method):
|
||||
if method() is not None:
|
||||
warnings.warn(f'It is deprecated to return a value that is not None from a '
|
||||
f'test case ({method})', DeprecationWarning, stacklevel=3)
|
||||
result = method()
|
||||
if result is not None:
|
||||
import inspect
|
||||
msg = (
|
||||
f'It is deprecated to return a value that is not None '
|
||||
f'from a test case ({method} returned {type(result).__name__!r})'
|
||||
)
|
||||
if inspect.iscoroutine(result):
|
||||
msg += (
|
||||
'. Maybe you forgot to use IsolatedAsyncioTestCase as the base class?'
|
||||
)
|
||||
warnings.warn(msg, DeprecationWarning, stacklevel=3)
|
||||
|
||||
def _callTearDown(self):
|
||||
self.tearDown()
|
||||
@@ -1312,13 +1335,71 @@ class TestCase(object):
|
||||
"""Same as self.assertTrue(isinstance(obj, cls)), with a nicer
|
||||
default message."""
|
||||
if not isinstance(obj, cls):
|
||||
standardMsg = '%s is not an instance of %r' % (safe_repr(obj), cls)
|
||||
if isinstance(cls, tuple):
|
||||
standardMsg = f'{safe_repr(obj)} is not an instance of any of {cls!r}'
|
||||
else:
|
||||
standardMsg = f'{safe_repr(obj)} is not an instance of {cls!r}'
|
||||
self.fail(self._formatMessage(msg, standardMsg))
|
||||
|
||||
def assertNotIsInstance(self, obj, cls, msg=None):
|
||||
"""Included for symmetry with assertIsInstance."""
|
||||
if isinstance(obj, cls):
|
||||
standardMsg = '%s is an instance of %r' % (safe_repr(obj), cls)
|
||||
if isinstance(cls, tuple):
|
||||
for x in cls:
|
||||
if isinstance(obj, x):
|
||||
cls = x
|
||||
break
|
||||
standardMsg = f'{safe_repr(obj)} is an instance of {cls!r}'
|
||||
self.fail(self._formatMessage(msg, standardMsg))
|
||||
|
||||
def assertIsSubclass(self, cls, superclass, msg=None):
|
||||
try:
|
||||
if issubclass(cls, superclass):
|
||||
return
|
||||
except TypeError:
|
||||
if not isinstance(cls, type):
|
||||
self.fail(self._formatMessage(msg, f'{cls!r} is not a class'))
|
||||
raise
|
||||
if isinstance(superclass, tuple):
|
||||
standardMsg = f'{cls!r} is not a subclass of any of {superclass!r}'
|
||||
else:
|
||||
standardMsg = f'{cls!r} is not a subclass of {superclass!r}'
|
||||
self.fail(self._formatMessage(msg, standardMsg))
|
||||
|
||||
def assertNotIsSubclass(self, cls, superclass, msg=None):
|
||||
try:
|
||||
if not issubclass(cls, superclass):
|
||||
return
|
||||
except TypeError:
|
||||
if not isinstance(cls, type):
|
||||
self.fail(self._formatMessage(msg, f'{cls!r} is not a class'))
|
||||
raise
|
||||
if isinstance(superclass, tuple):
|
||||
for x in superclass:
|
||||
if issubclass(cls, x):
|
||||
superclass = x
|
||||
break
|
||||
standardMsg = f'{cls!r} is a subclass of {superclass!r}'
|
||||
self.fail(self._formatMessage(msg, standardMsg))
|
||||
|
||||
def assertHasAttr(self, obj, name, msg=None):
|
||||
if not hasattr(obj, name):
|
||||
if isinstance(obj, types.ModuleType):
|
||||
standardMsg = f'module {obj.__name__!r} has no attribute {name!r}'
|
||||
elif isinstance(obj, type):
|
||||
standardMsg = f'type object {obj.__name__!r} has no attribute {name!r}'
|
||||
else:
|
||||
standardMsg = f'{type(obj).__name__!r} object has no attribute {name!r}'
|
||||
self.fail(self._formatMessage(msg, standardMsg))
|
||||
|
||||
def assertNotHasAttr(self, obj, name, msg=None):
|
||||
if hasattr(obj, name):
|
||||
if isinstance(obj, types.ModuleType):
|
||||
standardMsg = f'module {obj.__name__!r} has unexpected attribute {name!r}'
|
||||
elif isinstance(obj, type):
|
||||
standardMsg = f'type object {obj.__name__!r} has unexpected attribute {name!r}'
|
||||
else:
|
||||
standardMsg = f'{type(obj).__name__!r} object has unexpected attribute {name!r}'
|
||||
self.fail(self._formatMessage(msg, standardMsg))
|
||||
|
||||
def assertRaisesRegex(self, expected_exception, expected_regex,
|
||||
@@ -1382,6 +1463,80 @@ class TestCase(object):
|
||||
msg = self._formatMessage(msg, standardMsg)
|
||||
raise self.failureException(msg)
|
||||
|
||||
def _tail_type_check(self, s, tails, msg):
|
||||
if not isinstance(tails, tuple):
|
||||
tails = (tails,)
|
||||
for tail in tails:
|
||||
if isinstance(tail, str):
|
||||
if not isinstance(s, str):
|
||||
self.fail(self._formatMessage(msg,
|
||||
f'Expected str, not {type(s).__name__}'))
|
||||
elif isinstance(tail, (bytes, bytearray)):
|
||||
if not isinstance(s, (bytes, bytearray)):
|
||||
self.fail(self._formatMessage(msg,
|
||||
f'Expected bytes, not {type(s).__name__}'))
|
||||
|
||||
def assertStartsWith(self, s, prefix, msg=None):
|
||||
try:
|
||||
if s.startswith(prefix):
|
||||
return
|
||||
except (AttributeError, TypeError):
|
||||
self._tail_type_check(s, prefix, msg)
|
||||
raise
|
||||
a = safe_repr(s, short=True)
|
||||
b = safe_repr(prefix)
|
||||
if isinstance(prefix, tuple):
|
||||
standardMsg = f"{a} doesn't start with any of {b}"
|
||||
else:
|
||||
standardMsg = f"{a} doesn't start with {b}"
|
||||
self.fail(self._formatMessage(msg, standardMsg))
|
||||
|
||||
def assertNotStartsWith(self, s, prefix, msg=None):
|
||||
try:
|
||||
if not s.startswith(prefix):
|
||||
return
|
||||
except (AttributeError, TypeError):
|
||||
self._tail_type_check(s, prefix, msg)
|
||||
raise
|
||||
if isinstance(prefix, tuple):
|
||||
for x in prefix:
|
||||
if s.startswith(x):
|
||||
prefix = x
|
||||
break
|
||||
a = safe_repr(s, short=True)
|
||||
b = safe_repr(prefix)
|
||||
self.fail(self._formatMessage(msg, f"{a} starts with {b}"))
|
||||
|
||||
def assertEndsWith(self, s, suffix, msg=None):
|
||||
try:
|
||||
if s.endswith(suffix):
|
||||
return
|
||||
except (AttributeError, TypeError):
|
||||
self._tail_type_check(s, suffix, msg)
|
||||
raise
|
||||
a = safe_repr(s, short=True)
|
||||
b = safe_repr(suffix)
|
||||
if isinstance(suffix, tuple):
|
||||
standardMsg = f"{a} doesn't end with any of {b}"
|
||||
else:
|
||||
standardMsg = f"{a} doesn't end with {b}"
|
||||
self.fail(self._formatMessage(msg, standardMsg))
|
||||
|
||||
def assertNotEndsWith(self, s, suffix, msg=None):
|
||||
try:
|
||||
if not s.endswith(suffix):
|
||||
return
|
||||
except (AttributeError, TypeError):
|
||||
self._tail_type_check(s, suffix, msg)
|
||||
raise
|
||||
if isinstance(suffix, tuple):
|
||||
for x in suffix:
|
||||
if s.endswith(x):
|
||||
suffix = x
|
||||
break
|
||||
a = safe_repr(s, short=True)
|
||||
b = safe_repr(suffix)
|
||||
self.fail(self._formatMessage(msg, f"{a} ends with {b}"))
|
||||
|
||||
|
||||
class FunctionTestCase(TestCase):
|
||||
|
||||
Vendored
+46
-16
@@ -1,12 +1,11 @@
|
||||
"""Loading unittests."""
|
||||
|
||||
import functools
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
import traceback
|
||||
import types
|
||||
import functools
|
||||
|
||||
from fnmatch import fnmatch, fnmatchcase
|
||||
|
||||
from . import case, suite, util
|
||||
@@ -274,6 +273,8 @@ class TestLoader(object):
|
||||
self._top_level_dir = top_level_dir
|
||||
|
||||
is_not_importable = False
|
||||
is_namespace = False
|
||||
tests = []
|
||||
if os.path.isdir(os.path.abspath(start_dir)):
|
||||
start_dir = os.path.abspath(start_dir)
|
||||
if start_dir != top_level_dir:
|
||||
@@ -286,12 +287,25 @@ class TestLoader(object):
|
||||
is_not_importable = True
|
||||
else:
|
||||
the_module = sys.modules[start_dir]
|
||||
top_part = start_dir.split('.')[0]
|
||||
try:
|
||||
start_dir = os.path.abspath(
|
||||
os.path.dirname((the_module.__file__)))
|
||||
except AttributeError:
|
||||
if the_module.__name__ in sys.builtin_module_names:
|
||||
if not hasattr(the_module, "__file__") or the_module.__file__ is None:
|
||||
# look for namespace packages
|
||||
try:
|
||||
spec = the_module.__spec__
|
||||
except AttributeError:
|
||||
spec = None
|
||||
|
||||
if spec and spec.submodule_search_locations is not None:
|
||||
is_namespace = True
|
||||
|
||||
for path in the_module.__path__:
|
||||
if (not set_implicit_top and
|
||||
not path.startswith(top_level_dir)):
|
||||
continue
|
||||
self._top_level_dir = \
|
||||
(path.split(the_module.__name__
|
||||
.replace(".", os.path.sep))[0])
|
||||
tests.extend(self._find_tests(path, pattern, namespace=True))
|
||||
elif the_module.__name__ in sys.builtin_module_names:
|
||||
# builtin module
|
||||
raise TypeError('Can not use builtin modules '
|
||||
'as dotted module names') from None
|
||||
@@ -300,14 +314,27 @@ class TestLoader(object):
|
||||
f"don't know how to discover from {the_module!r}"
|
||||
) from None
|
||||
|
||||
else:
|
||||
top_part = start_dir.split('.')[0]
|
||||
start_dir = os.path.abspath(os.path.dirname((the_module.__file__)))
|
||||
|
||||
if set_implicit_top:
|
||||
self._top_level_dir = self._get_directory_containing_module(top_part)
|
||||
if not is_namespace:
|
||||
if sys.modules[top_part].__file__ is None:
|
||||
self._top_level_dir = os.path.dirname(the_module.__file__)
|
||||
if self._top_level_dir not in sys.path:
|
||||
sys.path.insert(0, self._top_level_dir)
|
||||
else:
|
||||
self._top_level_dir = \
|
||||
self._get_directory_containing_module(top_part)
|
||||
sys.path.remove(top_level_dir)
|
||||
|
||||
if is_not_importable:
|
||||
raise ImportError('Start directory is not importable: %r' % start_dir)
|
||||
|
||||
tests = list(self._find_tests(start_dir, pattern))
|
||||
if not is_namespace:
|
||||
tests = list(self._find_tests(start_dir, pattern))
|
||||
|
||||
self._top_level_dir = original_top_level_dir
|
||||
return self.suiteClass(tests)
|
||||
|
||||
@@ -343,7 +370,7 @@ class TestLoader(object):
|
||||
# override this method to use alternative matching strategy
|
||||
return fnmatch(path, pattern)
|
||||
|
||||
def _find_tests(self, start_dir, pattern):
|
||||
def _find_tests(self, start_dir, pattern, namespace=False):
|
||||
"""Used by discovery. Yields test suites it loads."""
|
||||
# Handle the __init__ in this package
|
||||
name = self._get_name_from_path(start_dir)
|
||||
@@ -352,7 +379,8 @@ class TestLoader(object):
|
||||
if name != '.' and name not in self._loading_packages:
|
||||
# name is in self._loading_packages while we have called into
|
||||
# loadTestsFromModule with name.
|
||||
tests, should_recurse = self._find_test_path(start_dir, pattern)
|
||||
tests, should_recurse = self._find_test_path(
|
||||
start_dir, pattern, namespace)
|
||||
if tests is not None:
|
||||
yield tests
|
||||
if not should_recurse:
|
||||
@@ -363,7 +391,8 @@ class TestLoader(object):
|
||||
paths = sorted(os.listdir(start_dir))
|
||||
for path in paths:
|
||||
full_path = os.path.join(start_dir, path)
|
||||
tests, should_recurse = self._find_test_path(full_path, pattern)
|
||||
tests, should_recurse = self._find_test_path(
|
||||
full_path, pattern, False)
|
||||
if tests is not None:
|
||||
yield tests
|
||||
if should_recurse:
|
||||
@@ -371,11 +400,11 @@ class TestLoader(object):
|
||||
name = self._get_name_from_path(full_path)
|
||||
self._loading_packages.add(name)
|
||||
try:
|
||||
yield from self._find_tests(full_path, pattern)
|
||||
yield from self._find_tests(full_path, pattern, False)
|
||||
finally:
|
||||
self._loading_packages.discard(name)
|
||||
|
||||
def _find_test_path(self, full_path, pattern):
|
||||
def _find_test_path(self, full_path, pattern, namespace=False):
|
||||
"""Used by discovery.
|
||||
|
||||
Loads tests from a single file, or a directories' __init__.py when
|
||||
@@ -419,7 +448,8 @@ class TestLoader(object):
|
||||
msg % (mod_name, module_dir, expected_dir))
|
||||
return self.loadTestsFromModule(module, pattern=pattern), False
|
||||
elif os.path.isdir(full_path):
|
||||
if not os.path.isfile(os.path.join(full_path, '__init__.py')):
|
||||
if (not namespace and
|
||||
not os.path.isfile(os.path.join(full_path, '__init__.py'))):
|
||||
return None, False
|
||||
|
||||
load_tests = None
|
||||
|
||||
Vendored
+3
-3
@@ -1,8 +1,8 @@
|
||||
"""Unittest main program"""
|
||||
|
||||
import sys
|
||||
import argparse
|
||||
import os
|
||||
import sys
|
||||
|
||||
from . import loader, runner
|
||||
from .signals import installHandler
|
||||
@@ -197,7 +197,7 @@ class TestProgram(object):
|
||||
return parser
|
||||
|
||||
def _getMainArgParser(self, parent):
|
||||
parser = argparse.ArgumentParser(parents=[parent])
|
||||
parser = argparse.ArgumentParser(parents=[parent], color=True)
|
||||
parser.prog = self.progName
|
||||
parser.print_help = self._print_help
|
||||
|
||||
@@ -208,7 +208,7 @@ class TestProgram(object):
|
||||
return parser
|
||||
|
||||
def _getDiscoveryArgParser(self, parent):
|
||||
parser = argparse.ArgumentParser(parents=[parent])
|
||||
parser = argparse.ArgumentParser(parents=[parent], color=True)
|
||||
parser.prog = '%s discover' % self.progName
|
||||
parser.epilog = ('For test discovery all test modules must be '
|
||||
'importable from the top level directory of the '
|
||||
|
||||
Vendored
+35
-17
@@ -25,19 +25,20 @@ __all__ = (
|
||||
|
||||
|
||||
import asyncio
|
||||
import builtins
|
||||
import contextlib
|
||||
import io
|
||||
import inspect
|
||||
import io
|
||||
import pkgutil
|
||||
import pprint
|
||||
import sys
|
||||
import builtins
|
||||
import pkgutil
|
||||
from asyncio import iscoroutinefunction
|
||||
import threading
|
||||
from types import CodeType, ModuleType, MethodType
|
||||
from unittest.util import safe_repr
|
||||
from functools import wraps, partial
|
||||
from dataclasses import fields, is_dataclass
|
||||
from functools import partial, wraps
|
||||
from inspect import iscoroutinefunction
|
||||
from threading import RLock
|
||||
from types import CodeType, MethodType, ModuleType
|
||||
from unittest.util import safe_repr
|
||||
|
||||
|
||||
class InvalidSpecError(Exception):
|
||||
@@ -568,6 +569,11 @@ class NonCallableMock(Base):
|
||||
__dict__['_mock_methods'] = spec
|
||||
__dict__['_spec_asyncs'] = _spec_asyncs
|
||||
|
||||
def _mock_extend_spec_methods(self, spec_methods):
|
||||
methods = self.__dict__.get('_mock_methods') or []
|
||||
methods.extend(spec_methods)
|
||||
self.__dict__['_mock_methods'] = methods
|
||||
|
||||
def __get_return_value(self):
|
||||
ret = self._mock_return_value
|
||||
if self._mock_delegate is not None:
|
||||
@@ -1766,7 +1772,7 @@ def patch(
|
||||
the patch is undone.
|
||||
|
||||
If `new` is omitted, then the target is replaced with an
|
||||
`AsyncMock if the patched object is an async function or a
|
||||
`AsyncMock` if the patched object is an async function or a
|
||||
`MagicMock` otherwise. If `patch` is used as a decorator and `new` is
|
||||
omitted, the created mock is passed in as an extra argument to the
|
||||
decorated function. If `patch` is used as a context manager the created
|
||||
@@ -1840,7 +1846,8 @@ def patch(
|
||||
class _patch_dict(object):
|
||||
"""
|
||||
Patch a dictionary, or dictionary like object, and restore the dictionary
|
||||
to its original state after the test.
|
||||
to its original state after the test, where the restored dictionary is
|
||||
a copy of the dictionary as it was before the test.
|
||||
|
||||
`in_dict` can be a dictionary or a mapping like container. If it is a
|
||||
mapping then it must at least support getting, setting and deleting items
|
||||
@@ -2176,8 +2183,6 @@ class MagicMixin(Base):
|
||||
|
||||
if getattr(self, "_mock_methods", None) is not None:
|
||||
these_magics = orig_magics.intersection(self._mock_methods)
|
||||
|
||||
remove_magics = set()
|
||||
remove_magics = orig_magics - these_magics
|
||||
|
||||
for entry in remove_magics:
|
||||
@@ -2477,7 +2482,7 @@ class AsyncMock(AsyncMockMixin, AsyncMagicMixin, Mock):
|
||||
recognized as an async function, and the result of a call is an awaitable:
|
||||
|
||||
>>> mock = AsyncMock()
|
||||
>>> iscoroutinefunction(mock)
|
||||
>>> inspect.iscoroutinefunction(mock)
|
||||
True
|
||||
>>> inspect.isawaitable(mock())
|
||||
True
|
||||
@@ -2767,6 +2772,16 @@ def create_autospec(spec, spec_set=False, instance=False, _parent=None,
|
||||
f'[object={spec!r}]')
|
||||
is_async_func = _is_async_func(spec)
|
||||
_kwargs = {'spec': spec}
|
||||
|
||||
entries = [(entry, _missing) for entry in dir(spec)]
|
||||
if is_type and instance and is_dataclass(spec):
|
||||
is_dataclass_spec = True
|
||||
dataclass_fields = fields(spec)
|
||||
entries.extend((f.name, f.type) for f in dataclass_fields)
|
||||
dataclass_spec_list = [f.name for f in dataclass_fields]
|
||||
else:
|
||||
is_dataclass_spec = False
|
||||
|
||||
if spec_set:
|
||||
_kwargs = {'spec_set': spec}
|
||||
elif spec is None:
|
||||
@@ -2802,6 +2817,8 @@ def create_autospec(spec, spec_set=False, instance=False, _parent=None,
|
||||
|
||||
mock = Klass(parent=_parent, _new_parent=_parent, _new_name=_new_name,
|
||||
name=_name, **_kwargs)
|
||||
if is_dataclass_spec:
|
||||
mock._mock_extend_spec_methods(dataclass_spec_list)
|
||||
|
||||
if isinstance(spec, FunctionTypes):
|
||||
# should only happen at the top level because we don't
|
||||
@@ -2823,7 +2840,7 @@ def create_autospec(spec, spec_set=False, instance=False, _parent=None,
|
||||
_name='()', _parent=mock,
|
||||
wraps=wrapped)
|
||||
|
||||
for entry in dir(spec):
|
||||
for entry, original in entries:
|
||||
if _is_magic(entry):
|
||||
# MagicMock already does the useful magic methods for us
|
||||
continue
|
||||
@@ -2837,10 +2854,11 @@ def create_autospec(spec, spec_set=False, instance=False, _parent=None,
|
||||
# AttributeError on being fetched?
|
||||
# we could be resilient against it, or catch and propagate the
|
||||
# exception when the attribute is fetched from the mock
|
||||
try:
|
||||
original = getattr(spec, entry)
|
||||
except AttributeError:
|
||||
continue
|
||||
if original is _missing:
|
||||
try:
|
||||
original = getattr(spec, entry)
|
||||
except AttributeError:
|
||||
continue
|
||||
|
||||
child_kwargs = {'spec': original}
|
||||
# Wrap child attributes also.
|
||||
|
||||
Vendored
+5
-2
@@ -3,9 +3,9 @@
|
||||
import io
|
||||
import sys
|
||||
import traceback
|
||||
from functools import wraps
|
||||
|
||||
from . import util
|
||||
from functools import wraps
|
||||
|
||||
__unittest = True
|
||||
|
||||
@@ -189,7 +189,10 @@ class TestResult(object):
|
||||
tb_e = traceback.TracebackException(
|
||||
exctype, value, tb,
|
||||
capture_locals=self.tb_locals, compact=True)
|
||||
msgLines = list(tb_e.format())
|
||||
from _colorize import can_colorize
|
||||
|
||||
colorize = hasattr(self, "stream") and can_colorize(file=self.stream)
|
||||
msgLines = list(tb_e.format(colorize=colorize))
|
||||
|
||||
if self.buffer:
|
||||
output = sys.stdout.getvalue()
|
||||
|
||||
Vendored
+61
-40
@@ -4,6 +4,8 @@ import sys
|
||||
import time
|
||||
import warnings
|
||||
|
||||
from _colorize import get_theme
|
||||
|
||||
from . import result
|
||||
from .case import _SubTest
|
||||
from .signals import registerResult
|
||||
@@ -13,18 +15,18 @@ __unittest = True
|
||||
|
||||
class _WritelnDecorator(object):
|
||||
"""Used to decorate file-like objects with a handy 'writeln' method"""
|
||||
def __init__(self,stream):
|
||||
def __init__(self, stream):
|
||||
self.stream = stream
|
||||
|
||||
def __getattr__(self, attr):
|
||||
if attr in ('stream', '__getstate__'):
|
||||
raise AttributeError(attr)
|
||||
return getattr(self.stream,attr)
|
||||
return getattr(self.stream, attr)
|
||||
|
||||
def writeln(self, arg=None):
|
||||
if arg:
|
||||
self.write(arg)
|
||||
self.write('\n') # text-mode streams translate to \r\n if needed
|
||||
self.write('\n') # text-mode streams translate to \r\n if needed
|
||||
|
||||
|
||||
class TextTestResult(result.TestResult):
|
||||
@@ -43,6 +45,7 @@ class TextTestResult(result.TestResult):
|
||||
self.showAll = verbosity > 1
|
||||
self.dots = verbosity == 1
|
||||
self.descriptions = descriptions
|
||||
self._theme = get_theme(tty_file=stream).unittest
|
||||
self._newline = True
|
||||
self.durations = durations
|
||||
|
||||
@@ -76,86 +79,100 @@ class TextTestResult(result.TestResult):
|
||||
|
||||
def addSubTest(self, test, subtest, err):
|
||||
if err is not None:
|
||||
t = self._theme
|
||||
if self.showAll:
|
||||
if issubclass(err[0], subtest.failureException):
|
||||
self._write_status(subtest, "FAIL")
|
||||
self._write_status(subtest, f"{t.fail}FAIL{t.reset}")
|
||||
else:
|
||||
self._write_status(subtest, "ERROR")
|
||||
self._write_status(subtest, f"{t.fail}ERROR{t.reset}")
|
||||
elif self.dots:
|
||||
if issubclass(err[0], subtest.failureException):
|
||||
self.stream.write('F')
|
||||
self.stream.write(f"{t.fail}F{t.reset}")
|
||||
else:
|
||||
self.stream.write('E')
|
||||
self.stream.write(f"{t.fail}E{t.reset}")
|
||||
self.stream.flush()
|
||||
super(TextTestResult, self).addSubTest(test, subtest, err)
|
||||
|
||||
def addSuccess(self, test):
|
||||
super(TextTestResult, self).addSuccess(test)
|
||||
t = self._theme
|
||||
if self.showAll:
|
||||
self._write_status(test, "ok")
|
||||
self._write_status(test, f"{t.passed}ok{t.reset}")
|
||||
elif self.dots:
|
||||
self.stream.write('.')
|
||||
self.stream.write(f"{t.passed}.{t.reset}")
|
||||
self.stream.flush()
|
||||
|
||||
def addError(self, test, err):
|
||||
super(TextTestResult, self).addError(test, err)
|
||||
t = self._theme
|
||||
if self.showAll:
|
||||
self._write_status(test, "ERROR")
|
||||
self._write_status(test, f"{t.fail}ERROR{t.reset}")
|
||||
elif self.dots:
|
||||
self.stream.write('E')
|
||||
self.stream.write(f"{t.fail}E{t.reset}")
|
||||
self.stream.flush()
|
||||
|
||||
def addFailure(self, test, err):
|
||||
super(TextTestResult, self).addFailure(test, err)
|
||||
t = self._theme
|
||||
if self.showAll:
|
||||
self._write_status(test, "FAIL")
|
||||
self._write_status(test, f"{t.fail}FAIL{t.reset}")
|
||||
elif self.dots:
|
||||
self.stream.write('F')
|
||||
self.stream.write(f"{t.fail}F{t.reset}")
|
||||
self.stream.flush()
|
||||
|
||||
def addSkip(self, test, reason):
|
||||
super(TextTestResult, self).addSkip(test, reason)
|
||||
t = self._theme
|
||||
if self.showAll:
|
||||
self._write_status(test, "skipped {0!r}".format(reason))
|
||||
self._write_status(test, f"{t.warn}skipped{t.reset} {reason!r}")
|
||||
elif self.dots:
|
||||
self.stream.write("s")
|
||||
self.stream.write(f"{t.warn}s{t.reset}")
|
||||
self.stream.flush()
|
||||
|
||||
def addExpectedFailure(self, test, err):
|
||||
super(TextTestResult, self).addExpectedFailure(test, err)
|
||||
t = self._theme
|
||||
if self.showAll:
|
||||
self.stream.writeln("expected failure")
|
||||
self.stream.writeln(f"{t.warn}expected failure{t.reset}")
|
||||
self.stream.flush()
|
||||
elif self.dots:
|
||||
self.stream.write("x")
|
||||
self.stream.write(f"{t.warn}x{t.reset}")
|
||||
self.stream.flush()
|
||||
|
||||
def addUnexpectedSuccess(self, test):
|
||||
super(TextTestResult, self).addUnexpectedSuccess(test)
|
||||
t = self._theme
|
||||
if self.showAll:
|
||||
self.stream.writeln("unexpected success")
|
||||
self.stream.writeln(f"{t.fail}unexpected success{t.reset}")
|
||||
self.stream.flush()
|
||||
elif self.dots:
|
||||
self.stream.write("u")
|
||||
self.stream.write(f"{t.fail}u{t.reset}")
|
||||
self.stream.flush()
|
||||
|
||||
def printErrors(self):
|
||||
t = self._theme
|
||||
if self.dots or self.showAll:
|
||||
self.stream.writeln()
|
||||
self.stream.flush()
|
||||
self.printErrorList('ERROR', self.errors)
|
||||
self.printErrorList('FAIL', self.failures)
|
||||
unexpectedSuccesses = getattr(self, 'unexpectedSuccesses', ())
|
||||
self.printErrorList(f"{t.fail}ERROR{t.reset}", self.errors)
|
||||
self.printErrorList(f"{t.fail}FAIL{t.reset}", self.failures)
|
||||
unexpectedSuccesses = getattr(self, "unexpectedSuccesses", ())
|
||||
if unexpectedSuccesses:
|
||||
self.stream.writeln(self.separator1)
|
||||
for test in unexpectedSuccesses:
|
||||
self.stream.writeln(f"UNEXPECTED SUCCESS: {self.getDescription(test)}")
|
||||
self.stream.writeln(
|
||||
f"{t.fail}UNEXPECTED SUCCESS{t.fail_info}: "
|
||||
f"{self.getDescription(test)}{t.reset}"
|
||||
)
|
||||
self.stream.flush()
|
||||
|
||||
def printErrorList(self, flavour, errors):
|
||||
t = self._theme
|
||||
for test, err in errors:
|
||||
self.stream.writeln(self.separator1)
|
||||
self.stream.writeln("%s: %s" % (flavour,self.getDescription(test)))
|
||||
self.stream.writeln(
|
||||
f"{flavour}{t.fail_info}: {self.getDescription(test)}{t.reset}"
|
||||
)
|
||||
self.stream.writeln(self.separator2)
|
||||
self.stream.writeln("%s" % err)
|
||||
self.stream.flush()
|
||||
@@ -232,7 +249,7 @@ class TextTestRunner(object):
|
||||
if self.warnings:
|
||||
# if self.warnings is set, use it to filter all the warnings
|
||||
warnings.simplefilter(self.warnings)
|
||||
startTime = time.perf_counter()
|
||||
start_time = time.perf_counter()
|
||||
startTestRun = getattr(result, 'startTestRun', None)
|
||||
if startTestRun is not None:
|
||||
startTestRun()
|
||||
@@ -242,8 +259,8 @@ class TextTestRunner(object):
|
||||
stopTestRun = getattr(result, 'stopTestRun', None)
|
||||
if stopTestRun is not None:
|
||||
stopTestRun()
|
||||
stopTime = time.perf_counter()
|
||||
timeTaken = stopTime - startTime
|
||||
stop_time = time.perf_counter()
|
||||
time_taken = stop_time - start_time
|
||||
result.printErrors()
|
||||
if self.durations is not None:
|
||||
self._printDurations(result)
|
||||
@@ -253,10 +270,10 @@ class TextTestRunner(object):
|
||||
|
||||
run = result.testsRun
|
||||
self.stream.writeln("Ran %d test%s in %.3fs" %
|
||||
(run, run != 1 and "s" or "", timeTaken))
|
||||
(run, run != 1 and "s" or "", time_taken))
|
||||
self.stream.writeln()
|
||||
|
||||
expectedFails = unexpectedSuccesses = skipped = 0
|
||||
expected_fails = unexpected_successes = skipped = 0
|
||||
try:
|
||||
results = map(len, (result.expectedFailures,
|
||||
result.unexpectedSuccesses,
|
||||
@@ -264,26 +281,30 @@ class TextTestRunner(object):
|
||||
except AttributeError:
|
||||
pass
|
||||
else:
|
||||
expectedFails, unexpectedSuccesses, skipped = results
|
||||
expected_fails, unexpected_successes, skipped = results
|
||||
|
||||
infos = []
|
||||
t = get_theme(tty_file=self.stream).unittest
|
||||
|
||||
if not result.wasSuccessful():
|
||||
self.stream.write("FAILED")
|
||||
self.stream.write(f"{t.fail_info}FAILED{t.reset}")
|
||||
failed, errored = len(result.failures), len(result.errors)
|
||||
if failed:
|
||||
infos.append("failures=%d" % failed)
|
||||
infos.append(f"{t.fail_info}failures={failed}{t.reset}")
|
||||
if errored:
|
||||
infos.append("errors=%d" % errored)
|
||||
infos.append(f"{t.fail_info}errors={errored}{t.reset}")
|
||||
elif run == 0 and not skipped:
|
||||
self.stream.write("NO TESTS RAN")
|
||||
self.stream.write(f"{t.warn}NO TESTS RAN{t.reset}")
|
||||
else:
|
||||
self.stream.write("OK")
|
||||
self.stream.write(f"{t.passed}OK{t.reset}")
|
||||
if skipped:
|
||||
infos.append("skipped=%d" % skipped)
|
||||
if expectedFails:
|
||||
infos.append("expected failures=%d" % expectedFails)
|
||||
if unexpectedSuccesses:
|
||||
infos.append("unexpected successes=%d" % unexpectedSuccesses)
|
||||
infos.append(f"{t.warn}skipped={skipped}{t.reset}")
|
||||
if expected_fails:
|
||||
infos.append(f"{t.warn}expected failures={expected_fails}{t.reset}")
|
||||
if unexpected_successes:
|
||||
infos.append(
|
||||
f"{t.fail}unexpected successes={unexpected_successes}{t.reset}"
|
||||
)
|
||||
if infos:
|
||||
self.stream.writeln(" (%s)" % (", ".join(infos),))
|
||||
else:
|
||||
|
||||
Vendored
-1
@@ -1,6 +1,5 @@
|
||||
import signal
|
||||
import weakref
|
||||
|
||||
from functools import wraps
|
||||
|
||||
__unittest = True
|
||||
|
||||
Vendored
+1
-2
@@ -2,8 +2,7 @@
|
||||
|
||||
import sys
|
||||
|
||||
from . import case
|
||||
from . import util
|
||||
from . import case, util
|
||||
|
||||
__unittest = True
|
||||
|
||||
|
||||
Vendored
+1
-1
@@ -1,6 +1,6 @@
|
||||
"""Various utility functions."""
|
||||
|
||||
from collections import namedtuple, Counter
|
||||
from collections import Counter, namedtuple
|
||||
from os.path import commonprefix
|
||||
|
||||
__unittest = True
|
||||
|
||||
Reference in new issue
Block a user