Skip to content
Projeler
Gruplar
Parçacıklar
Yardım
Yükleniyor...
Oturum aç / Kaydol
Gezinmeyi değiştir
C
cpython
Proje
Proje
Ayrıntılar
Etkinlik
Cycle Analytics
Depo (repository)
Depo (repository)
Dosyalar
Kayıtlar (commit)
Dallar (branch)
Etiketler
Katkıda bulunanlar
Grafik
Karşılaştır
Grafikler
Konular (issue)
0
Konular (issue)
0
Liste
Pano
Etiketler
Kilometre Taşları
Birleştirme (merge) Talepleri
0
Birleştirme (merge) Talepleri
0
CI / CD
CI / CD
İş akışları (pipeline)
İşler
Zamanlamalar
Grafikler
Paketler
Paketler
Wiki
Wiki
Parçacıklar
Parçacıklar
Üyeler
Üyeler
Collapse sidebar
Close sidebar
Etkinlik
Grafik
Grafikler
Yeni bir konu (issue) oluştur
İşler
Kayıtlar (commit)
Konu (issue) Panoları
Kenar çubuğunu aç
Batuhan Osman TASKAYA
cpython
Commits
d7b0eebc
Kaydet (Commit)
d7b0eebc
authored
Tem 19, 2009
tarafından
Benjamin Peterson
Dosyalara gözat
Seçenekler
Dosyalara Gözat
İndir
Eposta Yamaları
Sade Fark
split unittest.py into a package
üst
5fee460b
Hide whitespace changes
Inline
Side-by-side
Showing
14 changed files
with
920 additions
and
902 deletions
+920
-902
test_doctest.py
Lib/test/test_doctest.py
+19
-19
test_linecache.py
Lib/test/test_linecache.py
+1
-1
test_pyclbr.py
Lib/test/test_pyclbr.py
+1
-1
test_unittest.py
Lib/test/test_unittest.py
+4
-2
__init__.py
Lib/unittest/__init__.py
+63
-0
__main__.py
Lib/unittest/__main__.py
+8
-0
case.py
Lib/unittest/case.py
+13
-879
loader.py
Lib/unittest/loader.py
+234
-0
main.py
Lib/unittest/main.py
+175
-0
result.py
Lib/unittest/result.py
+113
-0
runner.py
Lib/unittest/runner.py
+172
-0
suite.py
Lib/unittest/suite.py
+71
-0
util.py
Lib/unittest/util.py
+44
-0
NEWS
Misc/NEWS
+2
-0
No files found.
Lib/test/test_doctest.py
Dosyayı görüntüle @
d7b0eebc
...
...
@@ -1809,19 +1809,19 @@ def test_DocTestSuite():
>>> import test.sample_doctest
>>> suite = doctest.DocTestSuite(test.sample_doctest)
>>> suite.run(unittest.TestResult())
<unittest.TestResult run=9 errors=0 failures=4>
<unittest.
result.
TestResult run=9 errors=0 failures=4>
We can also supply the module by name:
>>> suite = doctest.DocTestSuite('test.sample_doctest')
>>> suite.run(unittest.TestResult())
<unittest.TestResult run=9 errors=0 failures=4>
<unittest.
result.
TestResult run=9 errors=0 failures=4>
We can use the current module:
>>> suite = test.sample_doctest.test_suite()
>>> suite.run(unittest.TestResult())
<unittest.TestResult run=9 errors=0 failures=4>
<unittest.
result.
TestResult run=9 errors=0 failures=4>
We can supply global variables. If we pass globs, they will be
used instead of the module globals. Here we'll pass an empty
...
...
@@ -1829,7 +1829,7 @@ def test_DocTestSuite():
>>> suite = doctest.DocTestSuite('test.sample_doctest', globs={})
>>> suite.run(unittest.TestResult())
<unittest.TestResult run=9 errors=0 failures=5>
<unittest.
result.
TestResult run=9 errors=0 failures=5>
Alternatively, we can provide extra globals. Here we'll make an
error go away by providing an extra global variable:
...
...
@@ -1837,7 +1837,7 @@ def test_DocTestSuite():
>>> suite = doctest.DocTestSuite('test.sample_doctest',
... extraglobs={'y': 1})
>>> suite.run(unittest.TestResult())
<unittest.TestResult run=9 errors=0 failures=3>
<unittest.
result.
TestResult run=9 errors=0 failures=3>
You can pass option flags. Here we'll cause an extra error
by disabling the blank-line feature:
...
...
@@ -1845,7 +1845,7 @@ def test_DocTestSuite():
>>> suite = doctest.DocTestSuite('test.sample_doctest',
... optionflags=doctest.DONT_ACCEPT_BLANKLINE)
>>> suite.run(unittest.TestResult())
<unittest.TestResult run=9 errors=0 failures=5>
<unittest.
result.
TestResult run=9 errors=0 failures=5>
You can supply setUp and tearDown functions:
...
...
@@ -1862,7 +1862,7 @@ def test_DocTestSuite():
>>> suite = doctest.DocTestSuite('test.sample_doctest',
... setUp=setUp, tearDown=tearDown)
>>> suite.run(unittest.TestResult())
<unittest.TestResult run=9 errors=0 failures=3>
<unittest.
result.
TestResult run=9 errors=0 failures=3>
But the tearDown restores sanity:
...
...
@@ -1880,7 +1880,7 @@ def test_DocTestSuite():
>>> suite = doctest.DocTestSuite('test.sample_doctest', setUp=setUp)
>>> suite.run(unittest.TestResult())
<unittest.TestResult run=9 errors=0 failures=3>
<unittest.
result.
TestResult run=9 errors=0 failures=3>
Here, we didn't need to use a tearDown function because we
modified the test globals, which are a copy of the
...
...
@@ -1899,7 +1899,7 @@ def test_DocFileSuite():
... 'test_doctest2.txt',
... 'test_doctest4.txt')
>>> suite.run(unittest.TestResult())
<unittest.TestResult run=3 errors=0 failures=3>
<unittest.
result.
TestResult run=3 errors=0 failures=3>
The test files are looked for in the directory containing the
calling module. A package keyword argument can be provided to
...
...
@@ -1911,7 +1911,7 @@ def test_DocFileSuite():
... 'test_doctest4.txt',
... package='test')
>>> suite.run(unittest.TestResult())
<unittest.TestResult run=3 errors=0 failures=3>
<unittest.
result.
TestResult run=3 errors=0 failures=3>
Support for using a package's __loader__.get_data() is also
provided.
...
...
@@ -1930,14 +1930,14 @@ def test_DocFileSuite():
... finally:
... if added_loader:
... del test.__loader__
<unittest.TestResult run=3 errors=0 failures=3>
<unittest.
result.
TestResult run=3 errors=0 failures=3>
'/' should be used as a path separator. It will be converted
to a native separator at run time:
>>> suite = doctest.DocFileSuite('../test/test_doctest.txt')
>>> suite.run(unittest.TestResult())
<unittest.TestResult run=1 errors=0 failures=1>
<unittest.
result.
TestResult run=1 errors=0 failures=1>
If DocFileSuite is used from an interactive session, then files
are resolved relative to the directory of sys.argv[0]:
...
...
@@ -1962,7 +1962,7 @@ def test_DocFileSuite():
>>> suite = doctest.DocFileSuite(test_file, module_relative=False)
>>> suite.run(unittest.TestResult())
<unittest.TestResult run=1 errors=0 failures=1>
<unittest.
result.
TestResult run=1 errors=0 failures=1>
It is an error to specify `package` when `module_relative=False`:
...
...
@@ -1978,7 +1978,7 @@ def test_DocFileSuite():
... 'test_doctest4.txt',
... globs={'favorite_color': 'blue'})
>>> suite.run(unittest.TestResult())
<unittest.TestResult run=3 errors=0 failures=2>
<unittest.
result.
TestResult run=3 errors=0 failures=2>
In this case, we supplied a missing favorite color. You can
provide doctest options:
...
...
@@ -1989,7 +1989,7 @@ def test_DocFileSuite():
... optionflags=doctest.DONT_ACCEPT_BLANKLINE,
... globs={'favorite_color': 'blue'})
>>> suite.run(unittest.TestResult())
<unittest.TestResult run=3 errors=0 failures=3>
<unittest.
result.
TestResult run=3 errors=0 failures=3>
And, you can provide setUp and tearDown functions:
...
...
@@ -2008,7 +2008,7 @@ def test_DocFileSuite():
... 'test_doctest4.txt',
... setUp=setUp, tearDown=tearDown)
>>> suite.run(unittest.TestResult())
<unittest.TestResult run=3 errors=0 failures=2>
<unittest.
result.
TestResult run=3 errors=0 failures=2>
But the tearDown restores sanity:
...
...
@@ -2027,7 +2027,7 @@ def test_DocFileSuite():
>>> suite = doctest.DocFileSuite('test_doctest.txt', setUp=setUp)
>>> suite.run(unittest.TestResult())
<unittest.TestResult run=1 errors=0 failures=0>
<unittest.
result.
TestResult run=1 errors=0 failures=0>
Here, we didn't need to use a tearDown function because we
modified the test globals. The test globals are
...
...
@@ -2039,7 +2039,7 @@ def test_DocFileSuite():
>>> suite = doctest.DocFileSuite('test_doctest3.txt')
>>> suite.run(unittest.TestResult())
<unittest.TestResult run=1 errors=0 failures=0>
<unittest.
result.
TestResult run=1 errors=0 failures=0>
If the tests contain non-ASCII characters, we have to specify which
encoding the file is encoded with. We do so by using the `encoding`
...
...
@@ -2050,7 +2050,7 @@ def test_DocFileSuite():
... 'test_doctest4.txt',
... encoding='utf-8')
>>> suite.run(unittest.TestResult())
<unittest.TestResult run=3 errors=0 failures=2>
<unittest.
result.
TestResult run=3 errors=0 failures=2>
"""
...
...
Lib/test/test_linecache.py
Dosyayı görüntüle @
d7b0eebc
...
...
@@ -12,7 +12,7 @@ EMPTY = ''
TESTS
=
'cjkencodings_test inspect_fodder inspect_fodder2 mapping_tests'
TESTS
=
TESTS
.
split
()
TEST_PATH
=
os
.
path
.
dirname
(
support
.
__file__
)
MODULES
=
"linecache
unittest
"
.
split
()
MODULES
=
"linecache
abc
"
.
split
()
MODULE_PATH
=
os
.
path
.
dirname
(
FILENAME
)
SOURCE_1
=
'''
...
...
Lib/test/test_pyclbr.py
Dosyayı görüntüle @
d7b0eebc
...
...
@@ -148,7 +148,7 @@ class PyclbrTest(TestCase):
def
test_easy
(
self
):
self
.
checkModule
(
'pyclbr'
)
self
.
checkModule
(
'doctest'
)
self
.
checkModule
(
'doctest'
,
ignore
=
(
"DocTestCase"
,)
)
self
.
checkModule
(
'rfc822'
)
self
.
checkModule
(
'difflib'
)
...
...
Lib/test/test_unittest.py
Dosyayı görüntüle @
d7b0eebc
...
...
@@ -7,6 +7,7 @@ Still need testing:
"""
from
StringIO
import
StringIO
import
__builtin__
import
os
import
re
import
sys
...
...
@@ -3410,9 +3411,10 @@ class TestDiscovery(TestCase):
def
test_get_module_from_path
(
self
):
loader
=
unittest
.
TestLoader
()
old_import
=
__import__
def
restore_import
():
unittest
.
__import__
=
__import__
unittest
.
__import__
=
lambda
*
_
:
None
__builtin__
.
__import__
=
old_import
__builtin__
.
__import__
=
lambda
*
_
:
None
self
.
addCleanup
(
restore_import
)
expected_module
=
object
()
...
...
Lib/unittest/__init__.py
0 → 100644
Dosyayı görüntüle @
d7b0eebc
"""
Python unit testing framework, based on Erich Gamma's JUnit and Kent Beck's
Smalltalk testing framework.
This module contains the core framework classes that form the basis of
specific test cases and suites (TestCase, TestSuite etc.), and also a
text-based utility class for running the tests and reporting the results
(TextTestRunner).
Simple usage:
import unittest
class IntegerArithmenticTestCase(unittest.TestCase):
def testAdd(self): ## test method names begin 'test*'
self.assertEqual((1 + 2), 3)
self.assertEqual(0 + 1, 1)
def testMultiply(self):
self.assertEqual((0 * 10), 0)
self.assertEqual((5 * 8), 40)
if __name__ == '__main__':
unittest.main()
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-2009 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.
IN NO EVENT SHALL THE AUTHOR BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF
THIS CODE, EVEN IF THE AUTHOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
DAMAGE.
THE AUTHOR SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE. THE CODE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS,
AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
"""
__all__
=
[
'TestResult'
,
'TestCase'
,
'TestSuite'
,
'TextTestRunner'
,
'TestLoader'
,
'FunctionTestCase'
,
'main'
,
'defaultTestLoader'
,
'SkipTest'
,
'skip'
,
'skipIf'
,
'skipUnless'
,
'expectedFailure'
]
# Expose obsolete functions for backwards compatibility
__all__
.
extend
([
'getTestCaseNames'
,
'makeSuite'
,
'findTestCases'
])
from
.result
import
TestResult
from
.case
import
(
TestCase
,
FunctionTestCase
,
SkipTest
,
skip
,
skipIf
,
skipUnless
,
expectedFailure
)
from
.suite
import
TestSuite
from
.loader
import
(
TestLoader
,
defaultTestLoader
,
makeSuite
,
getTestCaseNames
,
findTestCases
)
from
.main
import
TestProgram
,
main
from
.runner
import
TextTestRunner
Lib/unittest/__main__.py
0 → 100644
Dosyayı görüntüle @
d7b0eebc
"""Main entry point"""
import
sys
if
sys
.
argv
[
0
]
.
endswith
(
"__main__.py"
):
sys
.
argv
[
0
]
=
"unittest"
from
.main
import
main
main
(
module
=
None
)
Lib/unittest.py
→
Lib/unittest
/case
.py
Dosyayı görüntüle @
d7b0eebc
#!/usr/bin/env python
'''
Python unit testing framework, based on Erich Gamma's JUnit and Kent Beck's
Smalltalk testing framework.
"""Test case implementation"""
This module contains the core framework classes that form the basis of
specific test cases and suites (TestCase, TestSuite etc.), and also a
text-based utility class for running the tests and reporting the results
(TextTestRunner).
Simple usage:
import unittest
class IntegerArithmenticTestCase(unittest.TestCase):
def testAdd(self): ## test method names begin 'test*'
self.assertEqual((1 + 2), 3)
self.assertEqual(0 + 1, 1)
def testMultiply(self):
self.assertEqual((0 * 10), 0)
self.assertEqual((5 * 8), 40)
if __name__ == '__main__':
unittest.main()
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-2009 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.
IN NO EVENT SHALL THE AUTHOR BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF
THIS CODE, EVEN IF THE AUTHOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
DAMAGE.
THE AUTHOR SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE. THE CODE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS,
AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
'''
import
difflib
import
sys
import
functools
import
os
import
difflib
import
pprint
import
re
import
sys
import
time
import
traceback
import
types
import
warnings
from
fnmatch
import
fnmatch
##############################################################################
# Exported classes and functions
##############################################################################
__all__
=
[
'TestResult'
,
'TestCase'
,
'TestSuite'
,
'TextTestRunner'
,
'TestLoader'
,
'FunctionTestCase'
,
'main'
,
'defaultTestLoader'
,
'SkipTest'
,
'skip'
,
'skipIf'
,
'skipUnless'
,
'expectedFailure'
]
# Expose obsolete functions for backwards compatibility
__all__
.
extend
([
'getTestCaseNames'
,
'makeSuite'
,
'findTestCases'
])
##############################################################################
# Backward compatibility
##############################################################################
def
_CmpToKey
(
mycmp
):
'Convert a cmp= function into a key= function'
class
K
(
object
):
def
__init__
(
self
,
obj
):
self
.
obj
=
obj
def
__lt__
(
self
,
other
):
return
mycmp
(
self
.
obj
,
other
.
obj
)
==
-
1
return
K
##############################################################################
# Test framework core
##############################################################################
def
_strclass
(
cls
):
return
"
%
s.
%
s"
%
(
cls
.
__module__
,
cls
.
__name__
)
from
.
import
result
,
util
class
SkipTest
(
Exception
):
...
...
@@ -163,111 +81,6 @@ def expectedFailure(func):
raise
_UnexpectedSuccess
return
wrapper
__unittest
=
1
class
TestResult
(
object
):
"""Holder for test result information.
Test results are automatically managed by the TestCase and TestSuite
classes, and do not need to be explicitly manipulated by writers of tests.
Each instance holds the total number of tests run, and collections of
failures and errors that occurred among those test runs. The collections
contain tuples of (testcase, exceptioninfo), where exceptioninfo is the
formatted traceback of the error that occurred.
"""
def
__init__
(
self
):
self
.
failures
=
[]
self
.
errors
=
[]
self
.
testsRun
=
0
self
.
skipped
=
[]
self
.
expectedFailures
=
[]
self
.
unexpectedSuccesses
=
[]
self
.
shouldStop
=
False
def
startTest
(
self
,
test
):
"Called when the given test is about to be run"
self
.
testsRun
=
self
.
testsRun
+
1
def
startTestRun
(
self
):
"""Called once before any tests are executed.
See startTest for a method called before each test.
"""
def
stopTest
(
self
,
test
):
"Called when the given test has been run"
pass
def
stopTestRun
(
self
):
"""Called once after all tests are executed.
See stopTest for a method called after each test.
"""
def
addError
(
self
,
test
,
err
):
"""Called when an error has occurred. 'err' is a tuple of values as
returned by sys.exc_info().
"""
self
.
errors
.
append
((
test
,
self
.
_exc_info_to_string
(
err
,
test
)))
def
addFailure
(
self
,
test
,
err
):
"""Called when an error has occurred. 'err' is a tuple of values as
returned by sys.exc_info()."""
self
.
failures
.
append
((
test
,
self
.
_exc_info_to_string
(
err
,
test
)))
def
addSuccess
(
self
,
test
):
"Called when a test has completed successfully"
pass
def
addSkip
(
self
,
test
,
reason
):
"""Called when a test is skipped."""
self
.
skipped
.
append
((
test
,
reason
))
def
addExpectedFailure
(
self
,
test
,
err
):
"""Called when an expected failure/error occured."""
self
.
expectedFailures
.
append
(
(
test
,
self
.
_exc_info_to_string
(
err
,
test
)))
def
addUnexpectedSuccess
(
self
,
test
):
"""Called when a test was expected to fail, but succeed."""
self
.
unexpectedSuccesses
.
append
(
test
)
def
wasSuccessful
(
self
):
"Tells whether or not this result was a success"
return
len
(
self
.
failures
)
==
len
(
self
.
errors
)
==
0
def
stop
(
self
):
"Indicates that the tests should be aborted"
self
.
shouldStop
=
True
def
_exc_info_to_string
(
self
,
err
,
test
):
"""Converts a sys.exc_info()-style tuple of values into a string."""
exctype
,
value
,
tb
=
err
# Skip test runner traceback levels
while
tb
and
self
.
_is_relevant_tb_level
(
tb
):
tb
=
tb
.
tb_next
if
exctype
is
test
.
failureException
:
# Skip assert*() traceback levels
length
=
self
.
_count_relevant_tb_levels
(
tb
)
return
''
.
join
(
traceback
.
format_exception
(
exctype
,
value
,
tb
,
length
))
return
''
.
join
(
traceback
.
format_exception
(
exctype
,
value
,
tb
))
def
_is_relevant_tb_level
(
self
,
tb
):
return
'__unittest'
in
tb
.
tb_frame
.
f_globals
def
_count_relevant_tb_levels
(
self
,
tb
):
length
=
0
while
tb
and
not
self
.
_is_relevant_tb_level
(
tb
):
length
+=
1
tb
=
tb
.
tb_next
return
length
def
__repr__
(
self
):
return
"<
%
s run=
%
i errors=
%
i failures=
%
i>"
%
\
(
_strclass
(
self
.
__class__
),
self
.
testsRun
,
len
(
self
.
errors
),
len
(
self
.
failures
))
class
_AssertRaisesContext
(
object
):
"""A context manager used to implement TestCase.assertRaises* methods."""
...
...
@@ -409,7 +222,7 @@ class TestCase(object):
return
1
def
defaultTestResult
(
self
):
return
TestResult
()
return
result
.
TestResult
()
def
shortDescription
(
self
):
"""Returns both the test method name and first line of its docstring.
...
...
@@ -430,7 +243,7 @@ class TestCase(object):
return
desc
def
id
(
self
):
return
"
%
s.
%
s"
%
(
_
strclass
(
self
.
__class__
),
self
.
_testMethodName
)
return
"
%
s.
%
s"
%
(
util
.
strclass
(
self
.
__class__
),
self
.
_testMethodName
)
def
__eq__
(
self
,
other
):
if
type
(
self
)
is
not
type
(
other
):
...
...
@@ -445,11 +258,11 @@ class TestCase(object):
return
hash
((
type
(
self
),
self
.
_testMethodName
))
def
__str__
(
self
):
return
"
%
s (
%
s)"
%
(
self
.
_testMethodName
,
_
strclass
(
self
.
__class__
))
return
"
%
s (
%
s)"
%
(
self
.
_testMethodName
,
util
.
strclass
(
self
.
__class__
))
def
__repr__
(
self
):
return
"<
%
s testMethod=
%
s>"
%
\
(
_
strclass
(
self
.
__class__
),
self
.
_testMethodName
)
(
util
.
strclass
(
self
.
__class__
),
self
.
_testMethodName
)
def
run
(
self
,
result
=
None
):
orig_result
=
result
...
...
@@ -935,7 +748,7 @@ class TestCase(object):
actual
=
list
(
actual_seq
)
expected
.
sort
()
actual
.
sort
()
missing
,
unexpected
=
_SortedListD
ifference
(
expected
,
actual
)
missing
,
unexpected
=
util
.
sorted_list_d
ifference
(
expected
,
actual
)
errors
=
[]
if
missing
:
errors
.
append
(
'Expected, but missing:
\n
%
r'
%
missing
)
...
...
@@ -1019,114 +832,6 @@ class TestCase(object):
raise
self
.
failureException
(
msg
)
def
_SortedListDifference
(
expected
,
actual
):
"""Finds elements in only one or the other of two, sorted input lists.
Returns a two-element tuple of lists. The first list contains those
elements in the "expected" list but not in the "actual" list, and the
second contains those elements in the "actual" list but not in the
"expected" list. Duplicate elements in either input list are ignored.
"""
i
=
j
=
0
missing
=
[]
unexpected
=
[]
while
True
:
try
:
e
=
expected
[
i
]
a
=
actual
[
j
]
if
e
<
a
:
missing
.
append
(
e
)
i
+=
1
while
expected
[
i
]
==
e
:
i
+=
1
elif
e
>
a
:
unexpected
.
append
(
a
)
j
+=
1
while
actual
[
j
]
==
a
:
j
+=
1
else
:
i
+=
1
try
:
while
expected
[
i
]
==
e
:
i
+=
1
finally
:
j
+=
1
while
actual
[
j
]
==
a
:
j
+=
1
except
IndexError
:
missing
.
extend
(
expected
[
i
:])
unexpected
.
extend
(
actual
[
j
:])
break
return
missing
,
unexpected
class
TestSuite
(
object
):
"""A test suite is a composite test consisting of a number of TestCases.
For use, create an instance of TestSuite, then add test case instances.
When all tests have been added, the suite can be passed to a test
runner, such as TextTestRunner. It will run the individual test cases
in the order in which they were added, aggregating the results. When
subclassing, do not forget to call the base class constructor.
"""
def
__init__
(
self
,
tests
=
()):
self
.
_tests
=
[]
self
.
addTests
(
tests
)
def
__repr__
(
self
):
return
"<
%
s tests=
%
s>"
%
(
_strclass
(
self
.
__class__
),
list
(
self
))
def
__eq__
(
self
,
other
):
if
not
isinstance
(
other
,
self
.
__class__
):
return
NotImplemented
return
list
(
self
)
==
list
(
other
)
def
__ne__
(
self
,
other
):
return
not
self
==
other
# Can't guarantee hash invariant, so flag as unhashable
__hash__
=
None
def
__iter__
(
self
):
return
iter
(
self
.
_tests
)
def
countTestCases
(
self
):
cases
=
0
for
test
in
self
:
cases
+=
test
.
countTestCases
()
return
cases
def
addTest
(
self
,
test
):
# sanity checks
if
not
hasattr
(
test
,
'__call__'
):
raise
TypeError
(
"the test to add must be callable"
)
if
isinstance
(
test
,
type
)
and
issubclass
(
test
,
(
TestCase
,
TestSuite
)):
raise
TypeError
(
"TestCases and TestSuites must be instantiated "
"before passing them to addTest()"
)
self
.
_tests
.
append
(
test
)
def
addTests
(
self
,
tests
):
if
isinstance
(
tests
,
basestring
):
raise
TypeError
(
"tests must be an iterable of tests, not a string"
)
for
test
in
tests
:
self
.
addTest
(
test
)
def
run
(
self
,
result
):
for
test
in
self
:
if
result
.
shouldStop
:
break
test
(
result
)
return
result
def
__call__
(
self
,
*
args
,
**
kwds
):
return
self
.
run
(
*
args
,
**
kwds
)
def
debug
(
self
):
"""Run the tests without collecting errors in a TestResult"""
for
test
in
self
:
test
.
debug
()
class
FunctionTestCase
(
TestCase
):
"""A test case that wraps a test function.
...
...
@@ -1174,586 +879,15 @@ class FunctionTestCase(TestCase):
self
.
_testFunc
,
self
.
_description
))
def
__str__
(
self
):
return
"
%
s (
%
s)"
%
(
_strclass
(
self
.
__class__
),
self
.
_testFunc
.
__name__
)
return
"
%
s (
%
s)"
%
(
util
.
strclass
(
self
.
__class__
),
self
.
_testFunc
.
__name__
)
def
__repr__
(
self
):
return
"<
%
s testFunc=
%
s>"
%
(
_strclass
(
self
.
__class__
),
self
.
_testFunc
)
return
"<
%
s testFunc=
%
s>"
%
(
util
.
strclass
(
self
.
__class__
),
self
.
_testFunc
)
def
shortDescription
(
self
):
if
self
.
_description
is
not
None
:
return
self
.
_description
doc
=
self
.
_testFunc
.
__doc__
return
doc
and
doc
.
split
(
"
\n
"
)[
0
]
.
strip
()
or
None
##############################################################################
# Locating and loading tests
##############################################################################
class
TestLoader
(
object
):
"""
This class is responsible for loading tests according to various criteria
and returning them wrapped in a TestSuite
"""
testMethodPrefix
=
'test'
sortTestMethodsUsing
=
cmp
suiteClass
=
TestSuite
_top_level_dir
=
None
def
loadTestsFromTestCase
(
self
,
testCaseClass
):
"""Return a suite of all tests cases contained in testCaseClass"""
if
issubclass
(
testCaseClass
,
TestSuite
):
raise
TypeError
(
"Test cases should not be derived from TestSuite."
\
" Maybe you meant to derive from TestCase?"
)
testCaseNames
=
self
.
getTestCaseNames
(
testCaseClass
)
if
not
testCaseNames
and
hasattr
(
testCaseClass
,
'runTest'
):
testCaseNames
=
[
'runTest'
]
suite
=
self
.
suiteClass
(
map
(
testCaseClass
,
testCaseNames
))
return
suite
def
loadTestsFromModule
(
self
,
module
,
use_load_tests
=
True
):
"""Return a suite of all tests cases contained in the given module"""
tests
=
[]
for
name
in
dir
(
module
):
obj
=
getattr
(
module
,
name
)
if
isinstance
(
obj
,
type
)
and
issubclass
(
obj
,
TestCase
):
tests
.
append
(
self
.
loadTestsFromTestCase
(
obj
))
load_tests
=
getattr
(
module
,
'load_tests'
,
None
)
if
use_load_tests
and
load_tests
is
not
None
:
return
load_tests
(
self
,
tests
,
None
)
return
self
.
suiteClass
(
tests
)
def
loadTestsFromName
(
self
,
name
,
module
=
None
):
"""Return a suite of all tests cases given a string specifier.
The name may resolve either to a module, a test case class, a
test method within a test case class, or a callable object which
returns a TestCase or TestSuite instance.
The method optionally resolves the names relative to a given module.
"""
parts
=
name
.
split
(
'.'
)
if
module
is
None
:
parts_copy
=
parts
[:]
while
parts_copy
:
try
:
module
=
__import__
(
'.'
.
join
(
parts_copy
))
break
except
ImportError
:
del
parts_copy
[
-
1
]
if
not
parts_copy
:
raise
parts
=
parts
[
1
:]
obj
=
module
for
part
in
parts
:
parent
,
obj
=
obj
,
getattr
(
obj
,
part
)
if
isinstance
(
obj
,
types
.
ModuleType
):
return
self
.
loadTestsFromModule
(
obj
)
elif
isinstance
(
obj
,
type
)
and
issubclass
(
obj
,
TestCase
):
return
self
.
loadTestsFromTestCase
(
obj
)
elif
(
isinstance
(
obj
,
types
.
UnboundMethodType
)
and
isinstance
(
parent
,
type
)
and
issubclass
(
parent
,
TestCase
)):
return
TestSuite
([
parent
(
obj
.
__name__
)])
elif
isinstance
(
obj
,
TestSuite
):
return
obj
elif
hasattr
(
obj
,
'__call__'
):
test
=
obj
()
if
isinstance
(
test
,
TestSuite
):
return
test
elif
isinstance
(
test
,
TestCase
):
return
TestSuite
([
test
])
else
:
raise
TypeError
(
"calling
%
s returned
%
s, not a test"
%
(
obj
,
test
))
else
:
raise
TypeError
(
"don't know how to make test from:
%
s"
%
obj
)
def
loadTestsFromNames
(
self
,
names
,
module
=
None
):
"""Return a suite of all tests cases found using the given sequence
of string specifiers. See 'loadTestsFromName()'.
"""
suites
=
[
self
.
loadTestsFromName
(
name
,
module
)
for
name
in
names
]
return
self
.
suiteClass
(
suites
)
def
getTestCaseNames
(
self
,
testCaseClass
):
"""Return a sorted sequence of method names found within testCaseClass
"""
def
isTestMethod
(
attrname
,
testCaseClass
=
testCaseClass
,
prefix
=
self
.
testMethodPrefix
):
return
attrname
.
startswith
(
prefix
)
and
\
hasattr
(
getattr
(
testCaseClass
,
attrname
),
'__call__'
)
testFnNames
=
filter
(
isTestMethod
,
dir
(
testCaseClass
))
if
self
.
sortTestMethodsUsing
:
testFnNames
.
sort
(
key
=
_CmpToKey
(
self
.
sortTestMethodsUsing
))
return
testFnNames
def
discover
(
self
,
start_dir
,
pattern
=
'test*.py'
,
top_level_dir
=
None
):
"""Find and return all test modules from the specified start
directory, recursing into subdirectories to find them. Only test files
that match the pattern will be loaded. (Using shell style pattern
matching.)
All test modules must be importable from the top level of the project.
If the start directory is not the top level directory then the top
level directory must be specified separately.
If a test package name (directory with '__init__.py') matches the
pattern then the package will be checked for a 'load_tests' function. If
this exists then it will be called with loader, tests, pattern.
If load_tests exists then discovery does *not* recurse into the package,
load_tests is responsible for loading all tests in the package.
The pattern is deliberately not stored as a loader attribute so that
packages can continue discovery themselves. top_level_dir is stored so
load_tests does not need to pass this argument in to loader.discover().
"""
if
top_level_dir
is
None
and
self
.
_top_level_dir
is
not
None
:
# make top_level_dir optional if called from load_tests in a package
top_level_dir
=
self
.
_top_level_dir
elif
top_level_dir
is
None
:
top_level_dir
=
start_dir
top_level_dir
=
os
.
path
.
abspath
(
os
.
path
.
normpath
(
top_level_dir
))
start_dir
=
os
.
path
.
abspath
(
os
.
path
.
normpath
(
start_dir
))
if
not
top_level_dir
in
sys
.
path
:
# all test modules must be importable from the top level directory
sys
.
path
.
append
(
top_level_dir
)
self
.
_top_level_dir
=
top_level_dir
if
start_dir
!=
top_level_dir
and
not
os
.
path
.
isfile
(
os
.
path
.
join
(
start_dir
,
'__init__.py'
)):
# what about __init__.pyc or pyo (etc)
raise
ImportError
(
'Start directory is not importable:
%
r'
%
start_dir
)
tests
=
list
(
self
.
_find_tests
(
start_dir
,
pattern
))
return
self
.
suiteClass
(
tests
)
def
_get_module_from_path
(
self
,
path
):
"""Load a module from a path relative to the top-level directory
of a project. Used by discovery."""
path
=
os
.
path
.
splitext
(
os
.
path
.
normpath
(
path
))[
0
]
relpath
=
os
.
path
.
relpath
(
path
,
self
.
_top_level_dir
)
assert
not
os
.
path
.
isabs
(
relpath
),
"Path must be within the project"
assert
not
relpath
.
startswith
(
'..'
),
"Path must be within the project"
name
=
relpath
.
replace
(
os
.
path
.
sep
,
'.'
)
__import__
(
name
)
return
sys
.
modules
[
name
]
def
_find_tests
(
self
,
start_dir
,
pattern
):
"""Used by discovery. Yields test suites it loads."""
paths
=
os
.
listdir
(
start_dir
)
for
path
in
paths
:
full_path
=
os
.
path
.
join
(
start_dir
,
path
)
# what about __init__.pyc or pyo (etc)
# we would need to avoid loading the same tests multiple times
# from '.py', '.pyc' *and* '.pyo'
if
os
.
path
.
isfile
(
full_path
)
and
path
.
lower
()
.
endswith
(
'.py'
):
if
fnmatch
(
path
,
pattern
):
# if the test file matches, load it
module
=
self
.
_get_module_from_path
(
full_path
)
yield
self
.
loadTestsFromModule
(
module
)
elif
os
.
path
.
isdir
(
full_path
):
if
not
os
.
path
.
isfile
(
os
.
path
.
join
(
full_path
,
'__init__.py'
)):
continue
load_tests
=
None
tests
=
None
if
fnmatch
(
path
,
pattern
):
# only check load_tests if the package directory itself matches the filter
package
=
self
.
_get_module_from_path
(
full_path
)
load_tests
=
getattr
(
package
,
'load_tests'
,
None
)
tests
=
self
.
loadTestsFromModule
(
package
,
use_load_tests
=
False
)
if
load_tests
is
None
:
if
tests
is
not
None
:
# tests loaded from package file
yield
tests
# recurse into the package
for
test
in
self
.
_find_tests
(
full_path
,
pattern
):
yield
test
else
:
yield
load_tests
(
self
,
tests
,
pattern
)
defaultTestLoader
=
TestLoader
()
##############################################################################
# Patches for old functions: these functions should be considered obsolete
##############################################################################
def
_makeLoader
(
prefix
,
sortUsing
,
suiteClass
=
None
):
loader
=
TestLoader
()
loader
.
sortTestMethodsUsing
=
sortUsing
loader
.
testMethodPrefix
=
prefix
if
suiteClass
:
loader
.
suiteClass
=
suiteClass
return
loader
def
getTestCaseNames
(
testCaseClass
,
prefix
,
sortUsing
=
cmp
):
return
_makeLoader
(
prefix
,
sortUsing
)
.
getTestCaseNames
(
testCaseClass
)
def
makeSuite
(
testCaseClass
,
prefix
=
'test'
,
sortUsing
=
cmp
,
suiteClass
=
TestSuite
):
return
_makeLoader
(
prefix
,
sortUsing
,
suiteClass
)
.
loadTestsFromTestCase
(
testCaseClass
)
def
findTestCases
(
module
,
prefix
=
'test'
,
sortUsing
=
cmp
,
suiteClass
=
TestSuite
):
return
_makeLoader
(
prefix
,
sortUsing
,
suiteClass
)
.
loadTestsFromModule
(
module
)
##############################################################################
# Text UI
##############################################################################
class
_WritelnDecorator
(
object
):
"""Used to decorate file-like objects with a handy 'writeln' method"""
def
__init__
(
self
,
stream
):
self
.
stream
=
stream
def
__getattr__
(
self
,
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
class
_TextTestResult
(
TestResult
):
"""A test result class that can print formatted text results to a stream.
Used by TextTestRunner.
"""
separator1
=
'='
*
70
separator2
=
'-'
*
70
def
__init__
(
self
,
stream
,
descriptions
,
verbosity
):
super
(
_TextTestResult
,
self
)
.
__init__
()
self
.
stream
=
stream
self
.
showAll
=
verbosity
>
1
self
.
dots
=
verbosity
==
1
self
.
descriptions
=
descriptions
def
getDescription
(
self
,
test
):
if
self
.
descriptions
:
return
test
.
shortDescription
()
or
str
(
test
)
else
:
return
str
(
test
)
def
startTest
(
self
,
test
):
super
(
_TextTestResult
,
self
)
.
startTest
(
test
)
if
self
.
showAll
:
self
.
stream
.
write
(
self
.
getDescription
(
test
))
self
.
stream
.
write
(
" ... "
)
self
.
stream
.
flush
()
def
addSuccess
(
self
,
test
):
super
(
_TextTestResult
,
self
)
.
addSuccess
(
test
)
if
self
.
showAll
:
self
.
stream
.
writeln
(
"ok"
)
elif
self
.
dots
:
self
.
stream
.
write
(
'.'
)
self
.
stream
.
flush
()
def
addError
(
self
,
test
,
err
):
super
(
_TextTestResult
,
self
)
.
addError
(
test
,
err
)
if
self
.
showAll
:
self
.
stream
.
writeln
(
"ERROR"
)
elif
self
.
dots
:
self
.
stream
.
write
(
'E'
)
self
.
stream
.
flush
()
def
addFailure
(
self
,
test
,
err
):
super
(
_TextTestResult
,
self
)
.
addFailure
(
test
,
err
)
if
self
.
showAll
:
self
.
stream
.
writeln
(
"FAIL"
)
elif
self
.
dots
:
self
.
stream
.
write
(
'F'
)
self
.
stream
.
flush
()
def
addSkip
(
self
,
test
,
reason
):
super
(
_TextTestResult
,
self
)
.
addSkip
(
test
,
reason
)
if
self
.
showAll
:
self
.
stream
.
writeln
(
"skipped {0!r}"
.
format
(
reason
))
elif
self
.
dots
:
self
.
stream
.
write
(
"s"
)
self
.
stream
.
flush
()
def
addExpectedFailure
(
self
,
test
,
err
):
super
(
_TextTestResult
,
self
)
.
addExpectedFailure
(
test
,
err
)
if
self
.
showAll
:
self
.
stream
.
writeln
(
"expected failure"
)
elif
self
.
dots
:
self
.
stream
.
write
(
"x"
)
self
.
stream
.
flush
()
def
addUnexpectedSuccess
(
self
,
test
):
super
(
_TextTestResult
,
self
)
.
addUnexpectedSuccess
(
test
)
if
self
.
showAll
:
self
.
stream
.
writeln
(
"unexpected success"
)
elif
self
.
dots
:
self
.
stream
.
write
(
"u"
)
self
.
stream
.
flush
()
def
printErrors
(
self
):
if
self
.
dots
or
self
.
showAll
:
self
.
stream
.
writeln
()
self
.
printErrorList
(
'ERROR'
,
self
.
errors
)
self
.
printErrorList
(
'FAIL'
,
self
.
failures
)
def
printErrorList
(
self
,
flavour
,
errors
):
for
test
,
err
in
errors
:
self
.
stream
.
writeln
(
self
.
separator1
)
self
.
stream
.
writeln
(
"
%
s:
%
s"
%
(
flavour
,
self
.
getDescription
(
test
)))
self
.
stream
.
writeln
(
self
.
separator2
)
self
.
stream
.
writeln
(
"
%
s"
%
err
)
class
TextTestRunner
(
object
):
"""A test runner class that displays results in textual form.
It prints out the names of tests as they are run, errors as they
occur, and a summary of the results at the end of the test run.
"""
def
__init__
(
self
,
stream
=
sys
.
stderr
,
descriptions
=
1
,
verbosity
=
1
):
self
.
stream
=
_WritelnDecorator
(
stream
)
self
.
descriptions
=
descriptions
self
.
verbosity
=
verbosity
def
_makeResult
(
self
):
return
_TextTestResult
(
self
.
stream
,
self
.
descriptions
,
self
.
verbosity
)
def
run
(
self
,
test
):
"Run the given test case or test suite."
result
=
self
.
_makeResult
()
startTime
=
time
.
time
()
startTestRun
=
getattr
(
result
,
'startTestRun'
,
None
)
if
startTestRun
is
not
None
:
startTestRun
()
try
:
test
(
result
)
finally
:
stopTestRun
=
getattr
(
result
,
'stopTestRun'
,
None
)
if
stopTestRun
is
not
None
:
stopTestRun
()
stopTime
=
time
.
time
()
timeTaken
=
stopTime
-
startTime
result
.
printErrors
()
self
.
stream
.
writeln
(
result
.
separator2
)
run
=
result
.
testsRun
self
.
stream
.
writeln
(
"Ran
%
d test
%
s in
%.3
fs"
%
(
run
,
run
!=
1
and
"s"
or
""
,
timeTaken
))
self
.
stream
.
writeln
()
results
=
map
(
len
,
(
result
.
expectedFailures
,
result
.
unexpectedSuccesses
,
result
.
skipped
))
expectedFails
,
unexpectedSuccesses
,
skipped
=
results
infos
=
[]
if
not
result
.
wasSuccessful
():
self
.
stream
.
write
(
"FAILED"
)
failed
,
errored
=
map
(
len
,
(
result
.
failures
,
result
.
errors
))
if
failed
:
infos
.
append
(
"failures=
%
d"
%
failed
)
if
errored
:
infos
.
append
(
"errors=
%
d"
%
errored
)
else
:
self
.
stream
.
write
(
"OK"
)
if
skipped
:
infos
.
append
(
"skipped=
%
d"
%
skipped
)
if
expectedFails
:
infos
.
append
(
"expected failures=
%
d"
%
expectedFails
)
if
unexpectedSuccesses
:
infos
.
append
(
"unexpected successes=
%
d"
%
unexpectedSuccesses
)
if
infos
:
self
.
stream
.
writeln
(
" (
%
s)"
%
(
", "
.
join
(
infos
),))
else
:
self
.
stream
.
write
(
"
\n
"
)
return
result
##############################################################################
# Facilities for running tests from the command line
##############################################################################
USAGE_AS_MAIN
=
"""
\
Usage:
%(progName)
s [options] [tests]
Options:
-h, --help Show this message
-v, --verbose Verbose output
-q, --quiet Minimal output
Examples:
%(progName)
s test_module - run tests from test_module
%(progName)
s test_module.TestClass - run tests from
test_module.TestClass
%(progName)
s test_module.TestClass.test_method - run specified test method
[tests] can be a list of any number of test modules, classes and test
methods.
Alternative Usage:
%(progName)
s discover [options]
Options:
-v, --verbose Verbose output
-s directory Directory to start discovery ('.' default)
-p pattern Pattern to match test files ('test*.py' default)
-t directory Top level directory of project (default to
start directory)
For test discovery all test modules must be importable from the top
level directory of the project.
"""
USAGE_FROM_MODULE
=
"""
\
Usage:
%(progName)
s [options] [test] [...]
Options:
-h, --help Show this message
-v, --verbose Verbose output
-q, --quiet Minimal output
Examples:
%(progName)
s - run default set of tests
%(progName)
s MyTestSuite - run suite 'MyTestSuite'
%(progName)
s MyTestCase.testSomething - run MyTestCase.testSomething
%(progName)
s MyTestCase - run all 'test*' test methods
in MyTestCase
"""
if
__name__
==
'__main__'
:
USAGE
=
USAGE_AS_MAIN
else
:
USAGE
=
USAGE_FROM_MODULE
class
TestProgram
(
object
):
"""A command-line program that runs a set of tests; this is primarily
for making test modules conveniently executable.
"""
USAGE
=
USAGE
def
__init__
(
self
,
module
=
'__main__'
,
defaultTest
=
None
,
argv
=
None
,
testRunner
=
None
,
testLoader
=
defaultTestLoader
,
exit
=
True
,
verbosity
=
1
):
if
isinstance
(
module
,
basestring
):
self
.
module
=
__import__
(
module
)
for
part
in
module
.
split
(
'.'
)[
1
:]:
self
.
module
=
getattr
(
self
.
module
,
part
)
else
:
self
.
module
=
module
if
argv
is
None
:
argv
=
sys
.
argv
self
.
exit
=
exit
self
.
verbosity
=
verbosity
self
.
defaultTest
=
defaultTest
self
.
testRunner
=
testRunner
self
.
testLoader
=
testLoader
self
.
progName
=
os
.
path
.
basename
(
argv
[
0
])
self
.
parseArgs
(
argv
)
self
.
runTests
()
def
usageExit
(
self
,
msg
=
None
):
if
msg
:
print
msg
print
self
.
USAGE
%
self
.
__dict__
sys
.
exit
(
2
)
def
parseArgs
(
self
,
argv
):
if
len
(
argv
)
>
1
and
argv
[
1
]
.
lower
()
==
'discover'
:
self
.
_do_discovery
(
argv
[
2
:])
return
import
getopt
long_opts
=
[
'help'
,
'verbose'
,
'quiet'
]
try
:
options
,
args
=
getopt
.
getopt
(
argv
[
1
:],
'hHvq'
,
long_opts
)
for
opt
,
value
in
options
:
if
opt
in
(
'-h'
,
'-H'
,
'--help'
):
self
.
usageExit
()
if
opt
in
(
'-q'
,
'--quiet'
):
self
.
verbosity
=
0
if
opt
in
(
'-v'
,
'--verbose'
):
self
.
verbosity
=
2
if
len
(
args
)
==
0
and
self
.
defaultTest
is
None
:
self
.
test
=
self
.
testLoader
.
loadTestsFromModule
(
self
.
module
)
return
if
len
(
args
)
>
0
:
self
.
testNames
=
args
if
__name__
==
'__main__'
:
# to support python -m unittest ...
self
.
module
=
None
else
:
self
.
testNames
=
(
self
.
defaultTest
,)
self
.
createTests
()
except
getopt
.
error
,
msg
:
self
.
usageExit
(
msg
)
def
createTests
(
self
):
self
.
test
=
self
.
testLoader
.
loadTestsFromNames
(
self
.
testNames
,
self
.
module
)
def
_do_discovery
(
self
,
argv
,
Loader
=
TestLoader
):
# handle command line args for test discovery
import
optparse
parser
=
optparse
.
OptionParser
()
parser
.
add_option
(
'-v'
,
'--verbose'
,
dest
=
'verbose'
,
default
=
False
,
help
=
'Verbose output'
,
action
=
'store_true'
)
parser
.
add_option
(
'-s'
,
'--start-directory'
,
dest
=
'start'
,
default
=
'.'
,
help
=
"Directory to start discovery ('.' default)"
)
parser
.
add_option
(
'-p'
,
'--pattern'
,
dest
=
'pattern'
,
default
=
'test*.py'
,
help
=
"Pattern to match tests ('test*.py' default)"
)
parser
.
add_option
(
'-t'
,
'--top-level-directory'
,
dest
=
'top'
,
default
=
None
,
help
=
'Top level directory of project (defaults to start directory)'
)
options
,
args
=
parser
.
parse_args
(
argv
)
if
len
(
args
)
>
3
:
self
.
usageExit
()
for
name
,
value
in
zip
((
'start'
,
'pattern'
,
'top'
),
args
):
setattr
(
options
,
name
,
value
)
if
options
.
verbose
:
self
.
verbosity
=
2
start_dir
=
options
.
start
pattern
=
options
.
pattern
top_level_dir
=
options
.
top
loader
=
Loader
()
self
.
test
=
loader
.
discover
(
start_dir
,
pattern
,
top_level_dir
)
def
runTests
(
self
):
if
self
.
testRunner
is
None
:
self
.
testRunner
=
TextTestRunner
if
isinstance
(
self
.
testRunner
,
(
type
,
types
.
ClassType
)):
try
:
testRunner
=
self
.
testRunner
(
verbosity
=
self
.
verbosity
)
except
TypeError
:
# didn't accept the verbosity argument
testRunner
=
self
.
testRunner
()
else
:
# it is assumed to be a TestRunner instance
testRunner
=
self
.
testRunner
self
.
result
=
testRunner
.
run
(
self
.
test
)
if
self
.
exit
:
sys
.
exit
(
not
self
.
result
.
wasSuccessful
())
main
=
TestProgram
##############################################################################
# Executing this module from the command line
##############################################################################
if
__name__
==
"__main__"
:
sys
.
modules
[
'unittest'
]
=
sys
.
modules
[
'__main__'
]
main
(
module
=
None
)
Lib/unittest/loader.py
0 → 100644
Dosyayı görüntüle @
d7b0eebc
"""Loading unittests."""
import
os
import
sys
import
types
from
fnmatch
import
fnmatch
from
.
import
case
,
suite
def
_CmpToKey
(
mycmp
):
'Convert a cmp= function into a key= function'
class
K
(
object
):
def
__init__
(
self
,
obj
):
self
.
obj
=
obj
def
__lt__
(
self
,
other
):
return
mycmp
(
self
.
obj
,
other
.
obj
)
==
-
1
return
K
class
TestLoader
(
object
):
"""
This class is responsible for loading tests according to various criteria
and returning them wrapped in a TestSuite
"""
testMethodPrefix
=
'test'
sortTestMethodsUsing
=
cmp
suiteClass
=
suite
.
TestSuite
_top_level_dir
=
None
def
loadTestsFromTestCase
(
self
,
testCaseClass
):
"""Return a suite of all tests cases contained in testCaseClass"""
if
issubclass
(
testCaseClass
,
suite
.
TestSuite
):
raise
TypeError
(
"Test cases should not be derived from TestSuite."
\
" Maybe you meant to derive from TestCase?"
)
testCaseNames
=
self
.
getTestCaseNames
(
testCaseClass
)
if
not
testCaseNames
and
hasattr
(
testCaseClass
,
'runTest'
):
testCaseNames
=
[
'runTest'
]
loaded_suite
=
self
.
suiteClass
(
map
(
testCaseClass
,
testCaseNames
))
return
loaded_suite
def
loadTestsFromModule
(
self
,
module
,
use_load_tests
=
True
):
"""Return a suite of all tests cases contained in the given module"""
tests
=
[]
for
name
in
dir
(
module
):
obj
=
getattr
(
module
,
name
)
if
isinstance
(
obj
,
type
)
and
issubclass
(
obj
,
case
.
TestCase
):
tests
.
append
(
self
.
loadTestsFromTestCase
(
obj
))
load_tests
=
getattr
(
module
,
'load_tests'
,
None
)
if
use_load_tests
and
load_tests
is
not
None
:
return
load_tests
(
self
,
tests
,
None
)
return
self
.
suiteClass
(
tests
)
def
loadTestsFromName
(
self
,
name
,
module
=
None
):
"""Return a suite of all tests cases given a string specifier.
The name may resolve either to a module, a test case class, a
test method within a test case class, or a callable object which
returns a TestCase or TestSuite instance.
The method optionally resolves the names relative to a given module.
"""
parts
=
name
.
split
(
'.'
)
if
module
is
None
:
parts_copy
=
parts
[:]
while
parts_copy
:
try
:
module
=
__import__
(
'.'
.
join
(
parts_copy
))
break
except
ImportError
:
del
parts_copy
[
-
1
]
if
not
parts_copy
:
raise
parts
=
parts
[
1
:]
obj
=
module
for
part
in
parts
:
parent
,
obj
=
obj
,
getattr
(
obj
,
part
)
if
isinstance
(
obj
,
types
.
ModuleType
):
return
self
.
loadTestsFromModule
(
obj
)
elif
isinstance
(
obj
,
type
)
and
issubclass
(
obj
,
case
.
TestCase
):
return
self
.
loadTestsFromTestCase
(
obj
)
elif
(
isinstance
(
obj
,
types
.
UnboundMethodType
)
and
isinstance
(
parent
,
type
)
and
issubclass
(
parent
,
case
.
TestCase
)):
return
suite
.
TestSuite
([
parent
(
obj
.
__name__
)])
elif
isinstance
(
obj
,
suite
.
TestSuite
):
return
obj
elif
hasattr
(
obj
,
'__call__'
):
test
=
obj
()
if
isinstance
(
test
,
suite
.
TestSuite
):
return
test
elif
isinstance
(
test
,
case
.
TestCase
):
return
suite
.
TestSuite
([
test
])
else
:
raise
TypeError
(
"calling
%
s returned
%
s, not a test"
%
(
obj
,
test
))
else
:
raise
TypeError
(
"don't know how to make test from:
%
s"
%
obj
)
def
loadTestsFromNames
(
self
,
names
,
module
=
None
):
"""Return a suite of all tests cases found using the given sequence
of string specifiers. See 'loadTestsFromName()'.
"""
suites
=
[
self
.
loadTestsFromName
(
name
,
module
)
for
name
in
names
]
return
self
.
suiteClass
(
suites
)
def
getTestCaseNames
(
self
,
testCaseClass
):
"""Return a sorted sequence of method names found within testCaseClass
"""
def
isTestMethod
(
attrname
,
testCaseClass
=
testCaseClass
,
prefix
=
self
.
testMethodPrefix
):
return
attrname
.
startswith
(
prefix
)
and
\
hasattr
(
getattr
(
testCaseClass
,
attrname
),
'__call__'
)
testFnNames
=
filter
(
isTestMethod
,
dir
(
testCaseClass
))
if
self
.
sortTestMethodsUsing
:
testFnNames
.
sort
(
key
=
_CmpToKey
(
self
.
sortTestMethodsUsing
))
return
testFnNames
def
discover
(
self
,
start_dir
,
pattern
=
'test*.py'
,
top_level_dir
=
None
):
"""Find and return all test modules from the specified start
directory, recursing into subdirectories to find them. Only test files
that match the pattern will be loaded. (Using shell style pattern
matching.)
All test modules must be importable from the top level of the project.
If the start directory is not the top level directory then the top
level directory must be specified separately.
If a test package name (directory with '__init__.py') matches the
pattern then the package will be checked for a 'load_tests' function. If
this exists then it will be called with loader, tests, pattern.
If load_tests exists then discovery does *not* recurse into the package,
load_tests is responsible for loading all tests in the package.
The pattern is deliberately not stored as a loader attribute so that
packages can continue discovery themselves. top_level_dir is stored so
load_tests does not need to pass this argument in to loader.discover().
"""
if
top_level_dir
is
None
and
self
.
_top_level_dir
is
not
None
:
# make top_level_dir optional if called from load_tests in a package
top_level_dir
=
self
.
_top_level_dir
elif
top_level_dir
is
None
:
top_level_dir
=
start_dir
top_level_dir
=
os
.
path
.
abspath
(
os
.
path
.
normpath
(
top_level_dir
))
start_dir
=
os
.
path
.
abspath
(
os
.
path
.
normpath
(
start_dir
))
if
not
top_level_dir
in
sys
.
path
:
# all test modules must be importable from the top level directory
sys
.
path
.
append
(
top_level_dir
)
self
.
_top_level_dir
=
top_level_dir
if
start_dir
!=
top_level_dir
and
not
os
.
path
.
isfile
(
os
.
path
.
join
(
start_dir
,
'__init__.py'
)):
# what about __init__.pyc or pyo (etc)
raise
ImportError
(
'Start directory is not importable:
%
r'
%
start_dir
)
tests
=
list
(
self
.
_find_tests
(
start_dir
,
pattern
))
return
self
.
suiteClass
(
tests
)
def
_get_module_from_path
(
self
,
path
):
"""Load a module from a path relative to the top-level directory
of a project. Used by discovery."""
path
=
os
.
path
.
splitext
(
os
.
path
.
normpath
(
path
))[
0
]
relpath
=
os
.
path
.
relpath
(
path
,
self
.
_top_level_dir
)
assert
not
os
.
path
.
isabs
(
relpath
),
"Path must be within the project"
assert
not
relpath
.
startswith
(
'..'
),
"Path must be within the project"
name
=
relpath
.
replace
(
os
.
path
.
sep
,
'.'
)
__import__
(
name
)
return
sys
.
modules
[
name
]
def
_find_tests
(
self
,
start_dir
,
pattern
):
"""Used by discovery. Yields test suites it loads."""
paths
=
os
.
listdir
(
start_dir
)
for
path
in
paths
:
full_path
=
os
.
path
.
join
(
start_dir
,
path
)
# what about __init__.pyc or pyo (etc)
# we would need to avoid loading the same tests multiple times
# from '.py', '.pyc' *and* '.pyo'
if
os
.
path
.
isfile
(
full_path
)
and
path
.
lower
()
.
endswith
(
'.py'
):
if
fnmatch
(
path
,
pattern
):
# if the test file matches, load it
module
=
self
.
_get_module_from_path
(
full_path
)
yield
self
.
loadTestsFromModule
(
module
)
elif
os
.
path
.
isdir
(
full_path
):
if
not
os
.
path
.
isfile
(
os
.
path
.
join
(
full_path
,
'__init__.py'
)):
continue
load_tests
=
None
tests
=
None
if
fnmatch
(
path
,
pattern
):
# only check load_tests if the package directory itself matches the filter
package
=
self
.
_get_module_from_path
(
full_path
)
load_tests
=
getattr
(
package
,
'load_tests'
,
None
)
tests
=
self
.
loadTestsFromModule
(
package
,
use_load_tests
=
False
)
if
load_tests
is
None
:
if
tests
is
not
None
:
# tests loaded from package file
yield
tests
# recurse into the package
for
test
in
self
.
_find_tests
(
full_path
,
pattern
):
yield
test
else
:
yield
load_tests
(
self
,
tests
,
pattern
)
defaultTestLoader
=
TestLoader
()
def
_makeLoader
(
prefix
,
sortUsing
,
suiteClass
=
None
):
loader
=
TestLoader
()
loader
.
sortTestMethodsUsing
=
sortUsing
loader
.
testMethodPrefix
=
prefix
if
suiteClass
:
loader
.
suiteClass
=
suiteClass
return
loader
def
getTestCaseNames
(
testCaseClass
,
prefix
,
sortUsing
=
cmp
):
return
_makeLoader
(
prefix
,
sortUsing
)
.
getTestCaseNames
(
testCaseClass
)
def
makeSuite
(
testCaseClass
,
prefix
=
'test'
,
sortUsing
=
cmp
,
suiteClass
=
suite
.
TestSuite
):
return
_makeLoader
(
prefix
,
sortUsing
,
suiteClass
)
.
loadTestsFromTestCase
(
testCaseClass
)
def
findTestCases
(
module
,
prefix
=
'test'
,
sortUsing
=
cmp
,
suiteClass
=
suite
.
TestSuite
):
return
_makeLoader
(
prefix
,
sortUsing
,
suiteClass
)
.
loadTestsFromModule
(
module
)
Lib/unittest/main.py
0 → 100644
Dosyayı görüntüle @
d7b0eebc
"""Unittest main program"""
import
sys
import
os
import
types
from
.
import
loader
,
runner
USAGE_AS_MAIN
=
"""
\
Usage:
%(progName)
s [options] [tests]
Options:
-h, --help Show this message
-v, --verbose Verbose output
-q, --quiet Minimal output
Examples:
%(progName)
s test_module - run tests from test_module
%(progName)
s test_module.TestClass - run tests from
test_module.TestClass
%(progName)
s test_module.TestClass.test_method - run specified test method
[tests] can be a list of any number of test modules, classes and test
methods.
Alternative Usage:
%(progName)
s discover [options]
Options:
-v, --verbose Verbose output
-s directory Directory to start discovery ('.' default)
-p pattern Pattern to match test files ('test*.py' default)
-t directory Top level directory of project (default to
start directory)
For test discovery all test modules must be importable from the top
level directory of the project.
"""
USAGE_FROM_MODULE
=
"""
\
Usage:
%(progName)
s [options] [test] [...]
Options:
-h, --help Show this message
-v, --verbose Verbose output
-q, --quiet Minimal output
Examples:
%(progName)
s - run default set of tests
%(progName)
s MyTestSuite - run suite 'MyTestSuite'
%(progName)
s MyTestCase.testSomething - run MyTestCase.testSomething
%(progName)
s MyTestCase - run all 'test*' test methods
in MyTestCase
"""
if
__name__
==
'__main__'
:
USAGE
=
USAGE_AS_MAIN
else
:
USAGE
=
USAGE_FROM_MODULE
class
TestProgram
(
object
):
"""A command-line program that runs a set of tests; this is primarily
for making test modules conveniently executable.
"""
USAGE
=
USAGE
def
__init__
(
self
,
module
=
'__main__'
,
defaultTest
=
None
,
argv
=
None
,
testRunner
=
None
,
testLoader
=
loader
.
defaultTestLoader
,
exit
=
True
,
verbosity
=
1
):
if
isinstance
(
module
,
basestring
):
self
.
module
=
__import__
(
module
)
for
part
in
module
.
split
(
'.'
)[
1
:]:
self
.
module
=
getattr
(
self
.
module
,
part
)
else
:
self
.
module
=
module
if
argv
is
None
:
argv
=
sys
.
argv
self
.
exit
=
exit
self
.
verbosity
=
verbosity
self
.
defaultTest
=
defaultTest
self
.
testRunner
=
testRunner
self
.
testLoader
=
testLoader
self
.
progName
=
os
.
path
.
basename
(
argv
[
0
])
self
.
parseArgs
(
argv
)
self
.
runTests
()
def
usageExit
(
self
,
msg
=
None
):
if
msg
:
print
msg
print
self
.
USAGE
%
self
.
__dict__
sys
.
exit
(
2
)
def
parseArgs
(
self
,
argv
):
if
len
(
argv
)
>
1
and
argv
[
1
]
.
lower
()
==
'discover'
:
self
.
_do_discovery
(
argv
[
2
:])
return
import
getopt
long_opts
=
[
'help'
,
'verbose'
,
'quiet'
]
try
:
options
,
args
=
getopt
.
getopt
(
argv
[
1
:],
'hHvq'
,
long_opts
)
for
opt
,
value
in
options
:
if
opt
in
(
'-h'
,
'-H'
,
'--help'
):
self
.
usageExit
()
if
opt
in
(
'-q'
,
'--quiet'
):
self
.
verbosity
=
0
if
opt
in
(
'-v'
,
'--verbose'
):
self
.
verbosity
=
2
if
len
(
args
)
==
0
and
self
.
defaultTest
is
None
:
self
.
test
=
self
.
testLoader
.
loadTestsFromModule
(
self
.
module
)
return
if
len
(
args
)
>
0
:
self
.
testNames
=
args
if
__name__
==
'__main__'
:
# to support python -m unittest ...
self
.
module
=
None
else
:
self
.
testNames
=
(
self
.
defaultTest
,)
self
.
createTests
()
except
getopt
.
error
,
msg
:
self
.
usageExit
(
msg
)
def
createTests
(
self
):
self
.
test
=
self
.
testLoader
.
loadTestsFromNames
(
self
.
testNames
,
self
.
module
)
def
_do_discovery
(
self
,
argv
,
Loader
=
loader
.
TestLoader
):
# handle command line args for test discovery
import
optparse
parser
=
optparse
.
OptionParser
()
parser
.
add_option
(
'-v'
,
'--verbose'
,
dest
=
'verbose'
,
default
=
False
,
help
=
'Verbose output'
,
action
=
'store_true'
)
parser
.
add_option
(
'-s'
,
'--start-directory'
,
dest
=
'start'
,
default
=
'.'
,
help
=
"Directory to start discovery ('.' default)"
)
parser
.
add_option
(
'-p'
,
'--pattern'
,
dest
=
'pattern'
,
default
=
'test*.py'
,
help
=
"Pattern to match tests ('test*.py' default)"
)
parser
.
add_option
(
'-t'
,
'--top-level-directory'
,
dest
=
'top'
,
default
=
None
,
help
=
'Top level directory of project (defaults to start directory)'
)
options
,
args
=
parser
.
parse_args
(
argv
)
if
len
(
args
)
>
3
:
self
.
usageExit
()
for
name
,
value
in
zip
((
'start'
,
'pattern'
,
'top'
),
args
):
setattr
(
options
,
name
,
value
)
if
options
.
verbose
:
self
.
verbosity
=
2
start_dir
=
options
.
start
pattern
=
options
.
pattern
top_level_dir
=
options
.
top
loader
=
Loader
()
self
.
test
=
loader
.
discover
(
start_dir
,
pattern
,
top_level_dir
)
def
runTests
(
self
):
if
self
.
testRunner
is
None
:
self
.
testRunner
=
runner
.
TextTestRunner
if
isinstance
(
self
.
testRunner
,
(
type
,
types
.
ClassType
)):
try
:
testRunner
=
self
.
testRunner
(
verbosity
=
self
.
verbosity
)
except
TypeError
:
# didn't accept the verbosity argument
testRunner
=
self
.
testRunner
()
else
:
# it is assumed to be a TestRunner instance
testRunner
=
self
.
testRunner
self
.
result
=
testRunner
.
run
(
self
.
test
)
if
self
.
exit
:
sys
.
exit
(
not
self
.
result
.
wasSuccessful
())
main
=
TestProgram
Lib/unittest/result.py
0 → 100644
Dosyayı görüntüle @
d7b0eebc
"""Test result object"""
import
traceback
from
.
import
util
class
TestResult
(
object
):
"""Holder for test result information.
Test results are automatically managed by the TestCase and TestSuite
classes, and do not need to be explicitly manipulated by writers of tests.
Each instance holds the total number of tests run, and collections of
failures and errors that occurred among those test runs. The collections
contain tuples of (testcase, exceptioninfo), where exceptioninfo is the
formatted traceback of the error that occurred.
"""
def
__init__
(
self
):
self
.
failures
=
[]
self
.
errors
=
[]
self
.
testsRun
=
0
self
.
skipped
=
[]
self
.
expectedFailures
=
[]
self
.
unexpectedSuccesses
=
[]
self
.
shouldStop
=
False
def
startTest
(
self
,
test
):
"Called when the given test is about to be run"
self
.
testsRun
=
self
.
testsRun
+
1
def
startTestRun
(
self
):
"""Called once before any tests are executed.
See startTest for a method called before each test.
"""
def
stopTest
(
self
,
test
):
"Called when the given test has been run"
pass
def
stopTestRun
(
self
):
"""Called once after all tests are executed.
See stopTest for a method called after each test.
"""
def
addError
(
self
,
test
,
err
):
"""Called when an error has occurred. 'err' is a tuple of values as
returned by sys.exc_info().
"""
self
.
errors
.
append
((
test
,
self
.
_exc_info_to_string
(
err
,
test
)))
def
addFailure
(
self
,
test
,
err
):
"""Called when an error has occurred. 'err' is a tuple of values as
returned by sys.exc_info()."""
self
.
failures
.
append
((
test
,
self
.
_exc_info_to_string
(
err
,
test
)))
def
addSuccess
(
self
,
test
):
"Called when a test has completed successfully"
pass
def
addSkip
(
self
,
test
,
reason
):
"""Called when a test is skipped."""
self
.
skipped
.
append
((
test
,
reason
))
def
addExpectedFailure
(
self
,
test
,
err
):
"""Called when an expected failure/error occured."""
self
.
expectedFailures
.
append
(
(
test
,
self
.
_exc_info_to_string
(
err
,
test
)))
def
addUnexpectedSuccess
(
self
,
test
):
"""Called when a test was expected to fail, but succeed."""
self
.
unexpectedSuccesses
.
append
(
test
)
def
wasSuccessful
(
self
):
"Tells whether or not this result was a success"
return
len
(
self
.
failures
)
==
len
(
self
.
errors
)
==
0
def
stop
(
self
):
"Indicates that the tests should be aborted"
self
.
shouldStop
=
True
def
_exc_info_to_string
(
self
,
err
,
test
):
"""Converts a sys.exc_info()-style tuple of values into a string."""
exctype
,
value
,
tb
=
err
# Skip test runner traceback levels
while
tb
and
self
.
_is_relevant_tb_level
(
tb
):
tb
=
tb
.
tb_next
if
exctype
is
test
.
failureException
:
# Skip assert*() traceback levels
length
=
self
.
_count_relevant_tb_levels
(
tb
)
return
''
.
join
(
traceback
.
format_exception
(
exctype
,
value
,
tb
,
length
))
return
''
.
join
(
traceback
.
format_exception
(
exctype
,
value
,
tb
))
def
_is_relevant_tb_level
(
self
,
tb
):
globs
=
tb
.
tb_frame
.
f_globals
is_relevant
=
'__name__'
in
globs
and
\
globs
[
"__name__"
]
.
startswith
(
"unittest"
)
del
globs
return
is_relevant
def
_count_relevant_tb_levels
(
self
,
tb
):
length
=
0
while
tb
and
not
self
.
_is_relevant_tb_level
(
tb
):
length
+=
1
tb
=
tb
.
tb_next
return
length
def
__repr__
(
self
):
return
"<
%
s run=
%
i errors=
%
i failures=
%
i>"
%
\
(
util
.
strclass
(
self
.
__class__
),
self
.
testsRun
,
len
(
self
.
errors
),
len
(
self
.
failures
))
Lib/unittest/runner.py
0 → 100644
Dosyayı görüntüle @
d7b0eebc
"""Running tests"""
import
sys
import
time
from
.
import
result
class
_WritelnDecorator
(
object
):
"""Used to decorate file-like objects with a handy 'writeln' method"""
def
__init__
(
self
,
stream
):
self
.
stream
=
stream
def
__getattr__
(
self
,
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
class
_TextTestResult
(
result
.
TestResult
):
"""A test result class that can print formatted text results to a stream.
Used by TextTestRunner.
"""
separator1
=
'='
*
70
separator2
=
'-'
*
70
def
__init__
(
self
,
stream
,
descriptions
,
verbosity
):
super
(
_TextTestResult
,
self
)
.
__init__
()
self
.
stream
=
stream
self
.
showAll
=
verbosity
>
1
self
.
dots
=
verbosity
==
1
self
.
descriptions
=
descriptions
def
getDescription
(
self
,
test
):
if
self
.
descriptions
:
return
test
.
shortDescription
()
or
str
(
test
)
else
:
return
str
(
test
)
def
startTest
(
self
,
test
):
super
(
_TextTestResult
,
self
)
.
startTest
(
test
)
if
self
.
showAll
:
self
.
stream
.
write
(
self
.
getDescription
(
test
))
self
.
stream
.
write
(
" ... "
)
self
.
stream
.
flush
()
def
addSuccess
(
self
,
test
):
super
(
_TextTestResult
,
self
)
.
addSuccess
(
test
)
if
self
.
showAll
:
self
.
stream
.
writeln
(
"ok"
)
elif
self
.
dots
:
self
.
stream
.
write
(
'.'
)
self
.
stream
.
flush
()
def
addError
(
self
,
test
,
err
):
super
(
_TextTestResult
,
self
)
.
addError
(
test
,
err
)
if
self
.
showAll
:
self
.
stream
.
writeln
(
"ERROR"
)
elif
self
.
dots
:
self
.
stream
.
write
(
'E'
)
self
.
stream
.
flush
()
def
addFailure
(
self
,
test
,
err
):
super
(
_TextTestResult
,
self
)
.
addFailure
(
test
,
err
)
if
self
.
showAll
:
self
.
stream
.
writeln
(
"FAIL"
)
elif
self
.
dots
:
self
.
stream
.
write
(
'F'
)
self
.
stream
.
flush
()
def
addSkip
(
self
,
test
,
reason
):
super
(
_TextTestResult
,
self
)
.
addSkip
(
test
,
reason
)
if
self
.
showAll
:
self
.
stream
.
writeln
(
"skipped {0!r}"
.
format
(
reason
))
elif
self
.
dots
:
self
.
stream
.
write
(
"s"
)
self
.
stream
.
flush
()
def
addExpectedFailure
(
self
,
test
,
err
):
super
(
_TextTestResult
,
self
)
.
addExpectedFailure
(
test
,
err
)
if
self
.
showAll
:
self
.
stream
.
writeln
(
"expected failure"
)
elif
self
.
dots
:
self
.
stream
.
write
(
"x"
)
self
.
stream
.
flush
()
def
addUnexpectedSuccess
(
self
,
test
):
super
(
_TextTestResult
,
self
)
.
addUnexpectedSuccess
(
test
)
if
self
.
showAll
:
self
.
stream
.
writeln
(
"unexpected success"
)
elif
self
.
dots
:
self
.
stream
.
write
(
"u"
)
self
.
stream
.
flush
()
def
printErrors
(
self
):
if
self
.
dots
or
self
.
showAll
:
self
.
stream
.
writeln
()
self
.
printErrorList
(
'ERROR'
,
self
.
errors
)
self
.
printErrorList
(
'FAIL'
,
self
.
failures
)
def
printErrorList
(
self
,
flavour
,
errors
):
for
test
,
err
in
errors
:
self
.
stream
.
writeln
(
self
.
separator1
)
self
.
stream
.
writeln
(
"
%
s:
%
s"
%
(
flavour
,
self
.
getDescription
(
test
)))
self
.
stream
.
writeln
(
self
.
separator2
)
self
.
stream
.
writeln
(
"
%
s"
%
err
)
class
TextTestRunner
(
object
):
"""A test runner class that displays results in textual form.
It prints out the names of tests as they are run, errors as they
occur, and a summary of the results at the end of the test run.
"""
def
__init__
(
self
,
stream
=
sys
.
stderr
,
descriptions
=
1
,
verbosity
=
1
):
self
.
stream
=
_WritelnDecorator
(
stream
)
self
.
descriptions
=
descriptions
self
.
verbosity
=
verbosity
def
_makeResult
(
self
):
return
_TextTestResult
(
self
.
stream
,
self
.
descriptions
,
self
.
verbosity
)
def
run
(
self
,
test
):
"Run the given test case or test suite."
result
=
self
.
_makeResult
()
startTime
=
time
.
time
()
startTestRun
=
getattr
(
result
,
'startTestRun'
,
None
)
if
startTestRun
is
not
None
:
startTestRun
()
try
:
test
(
result
)
finally
:
stopTestRun
=
getattr
(
result
,
'stopTestRun'
,
None
)
if
stopTestRun
is
not
None
:
stopTestRun
()
stopTime
=
time
.
time
()
timeTaken
=
stopTime
-
startTime
result
.
printErrors
()
self
.
stream
.
writeln
(
result
.
separator2
)
run
=
result
.
testsRun
self
.
stream
.
writeln
(
"Ran
%
d test
%
s in
%.3
fs"
%
(
run
,
run
!=
1
and
"s"
or
""
,
timeTaken
))
self
.
stream
.
writeln
()
results
=
map
(
len
,
(
result
.
expectedFailures
,
result
.
unexpectedSuccesses
,
result
.
skipped
))
expectedFails
,
unexpectedSuccesses
,
skipped
=
results
infos
=
[]
if
not
result
.
wasSuccessful
():
self
.
stream
.
write
(
"FAILED"
)
failed
,
errored
=
map
(
len
,
(
result
.
failures
,
result
.
errors
))
if
failed
:
infos
.
append
(
"failures=
%
d"
%
failed
)
if
errored
:
infos
.
append
(
"errors=
%
d"
%
errored
)
else
:
self
.
stream
.
write
(
"OK"
)
if
skipped
:
infos
.
append
(
"skipped=
%
d"
%
skipped
)
if
expectedFails
:
infos
.
append
(
"expected failures=
%
d"
%
expectedFails
)
if
unexpectedSuccesses
:
infos
.
append
(
"unexpected successes=
%
d"
%
unexpectedSuccesses
)
if
infos
:
self
.
stream
.
writeln
(
" (
%
s)"
%
(
", "
.
join
(
infos
),))
else
:
self
.
stream
.
write
(
"
\n
"
)
return
result
Lib/unittest/suite.py
0 → 100644
Dosyayı görüntüle @
d7b0eebc
"""TestSuite"""
from
.
import
case
class
TestSuite
(
object
):
"""A test suite is a composite test consisting of a number of TestCases.
For use, create an instance of TestSuite, then add test case instances.
When all tests have been added, the suite can be passed to a test
runner, such as TextTestRunner. It will run the individual test cases
in the order in which they were added, aggregating the results. When
subclassing, do not forget to call the base class constructor.
"""
def
__init__
(
self
,
tests
=
()):
self
.
_tests
=
[]
self
.
addTests
(
tests
)
def
__repr__
(
self
):
return
"<
%
s tests=
%
s>"
%
(
_strclass
(
self
.
__class__
),
list
(
self
))
def
__eq__
(
self
,
other
):
if
not
isinstance
(
other
,
self
.
__class__
):
return
NotImplemented
return
list
(
self
)
==
list
(
other
)
def
__ne__
(
self
,
other
):
return
not
self
==
other
# Can't guarantee hash invariant, so flag as unhashable
__hash__
=
None
def
__iter__
(
self
):
return
iter
(
self
.
_tests
)
def
countTestCases
(
self
):
cases
=
0
for
test
in
self
:
cases
+=
test
.
countTestCases
()
return
cases
def
addTest
(
self
,
test
):
# sanity checks
if
not
hasattr
(
test
,
'__call__'
):
raise
TypeError
(
"the test to add must be callable"
)
if
isinstance
(
test
,
type
)
and
issubclass
(
test
,
(
case
.
TestCase
,
TestSuite
)):
raise
TypeError
(
"TestCases and TestSuites must be instantiated "
"before passing them to addTest()"
)
self
.
_tests
.
append
(
test
)
def
addTests
(
self
,
tests
):
if
isinstance
(
tests
,
basestring
):
raise
TypeError
(
"tests must be an iterable of tests, not a string"
)
for
test
in
tests
:
self
.
addTest
(
test
)
def
run
(
self
,
result
):
for
test
in
self
:
if
result
.
shouldStop
:
break
test
(
result
)
return
result
def
__call__
(
self
,
*
args
,
**
kwds
):
return
self
.
run
(
*
args
,
**
kwds
)
def
debug
(
self
):
"""Run the tests without collecting errors in a TestResult"""
for
test
in
self
:
test
.
debug
()
Lib/unittest/util.py
0 → 100644
Dosyayı görüntüle @
d7b0eebc
"""Various utility functions."""
def
strclass
(
cls
):
return
"
%
s.
%
s"
%
(
cls
.
__module__
,
cls
.
__name__
)
def
sorted_list_difference
(
expected
,
actual
):
"""Finds elements in only one or the other of two, sorted input lists.
Returns a two-element tuple of lists. The first list contains those
elements in the "expected" list but not in the "actual" list, and the
second contains those elements in the "actual" list but not in the
"expected" list. Duplicate elements in either input list are ignored.
"""
i
=
j
=
0
missing
=
[]
unexpected
=
[]
while
True
:
try
:
e
=
expected
[
i
]
a
=
actual
[
j
]
if
e
<
a
:
missing
.
append
(
e
)
i
+=
1
while
expected
[
i
]
==
e
:
i
+=
1
elif
e
>
a
:
unexpected
.
append
(
a
)
j
+=
1
while
actual
[
j
]
==
a
:
j
+=
1
else
:
i
+=
1
try
:
while
expected
[
i
]
==
e
:
i
+=
1
finally
:
j
+=
1
while
actual
[
j
]
==
a
:
j
+=
1
except
IndexError
:
missing
.
extend
(
expected
[
i
:])
unexpected
.
extend
(
actual
[
j
:])
break
return
missing
,
unexpected
Misc/NEWS
Dosyayı görüntüle @
d7b0eebc
...
...
@@ -352,6 +352,8 @@ Core and Builtins
Library
-------
- unittest has been split up into a package. All old names should still work.
- Issue #6431: Make Fraction type return NotImplemented when it doesn't
know how to handle a comparison without loss of precision. Also add
correct handling of infinities and nans for comparisons with float.
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment