Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Z
Zope
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
Zope
Commits
efe70c9e
Commit
efe70c9e
authored
May 15, 2004
by
Andreas Jung
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
removed
parent
3fd60861
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
0 additions
and
534 deletions
+0
-534
utilities/testrunner.py
utilities/testrunner.py
+0
-534
No files found.
utilities/testrunner.py
deleted
100755 → 0
View file @
3fd60861
#!/usr/bin/env python2.3
"""testrunner - a Zope test suite utility.
The testrunner utility is used to execute PyUnit test suites. This utility
should be run from the root of your Zope source directory. It will set up the
correct python path environment based on your source directory so that
test suites can import Zope modules in a way that is fairly independent of
the location of the test suite. It does *not* import the Zope package, so
a test thats depend on dynamic aspects of the Zope environment (such as
SOFTWARE_HOME being defined) may need to 'import Zope' as a part of the
test suite.
Testrunner will look for and execute test suites that follow some simple
conventions. Test modules should have a name prefixed with 'test', such as
'testMyModule.py', and test modules are expected to define a module function
named 'test_suite' that returns a TestSuite object. By convention,
we put test modules in a 'tests' sub-package of the package they test.
Testrunner is used to run all checked in test suites before (final) releases
are made, and can be used to quickly run a particular suite or all suites in
a particular directory."""
import
getopt
import
imp
import
os
import
sys
import
time
import
traceback
import
unittest
VERBOSE
=
2
class
TestRunner
:
"""Test suite runner"""
def
__init__
(
self
,
path
,
verbosity
,
mega_suite
,
verbose_on_error
):
self
.
basepath
=
path
self
.
verbosity
=
verbosity
self
.
verbose_on_error
=
verbose_on_error
self
.
results
=
[]
self
.
mega_suite
=
mega_suite
# initialize python path
pjoin
=
os
.
path
.
join
if
sys
.
platform
==
'win32'
:
newpaths
=
[
pjoin
(
path
,
'lib'
,
'python'
),
pjoin
(
path
,
'bin'
,
'lib'
),
pjoin
(
path
,
'bin'
,
'lib'
,
'plat-win'
),
pjoin
(
path
,
'bin'
,
'lib'
,
'win32'
),
pjoin
(
path
,
'bin'
,
'lib'
,
'win32'
,
'lib'
),
path
]
else
:
newpaths
=
[
pjoin
(
path
,
'lib'
,
'python'
),
path
]
sys
.
path
[:
0
]
=
newpaths
def
getSuiteFromFile
(
self
,
filepath
):
if
not
os
.
path
.
isfile
(
filepath
):
raise
ValueError
,
'%s is not a file'
%
filepath
path
,
filename
=
os
.
path
.
split
(
filepath
)
name
,
ext
=
os
.
path
.
splitext
(
filename
)
file
,
pathname
,
desc
=
imp
.
find_module
(
name
,
[
path
])
saved_syspath
=
sys
.
path
[:]
module
=
None
try
:
sys
.
path
.
append
(
path
)
# let module find things in its dir
try
:
module
=
imp
.
load_module
(
name
,
file
,
pathname
,
desc
)
except
KeyboardInterrupt
:
raise
except
:
(
tb_t
,
tb_v
,
tb_tb
)
=
sys
.
exc_info
()
self
.
report
(
"Module %s failed to load
\
n
%s: %s"
%
(
pathname
,
tb_t
,
tb_v
))
self
.
report
(
''
.
join
(
traceback
.
format_tb
(
tb_tb
))
+
'
\
n
'
)
del
tb_tb
finally
:
file
.
close
()
sys
.
path
.
pop
()
# Remove module level path
sys
.
path
[:]
=
saved_syspath
function
=
getattr
(
module
,
'test_suite'
,
None
)
if
function
is
None
:
return
None
return
function
()
def
smellsLikeATest
(
self
,
filepath
):
path
,
name
=
os
.
path
.
split
(
filepath
)
fname
,
ext
=
os
.
path
.
splitext
(
name
)
if
(
name
[:
4
]
==
'test'
and
name
[
-
3
:]
==
'.py'
and
name
!=
'testrunner.py'
):
file
=
open
(
filepath
,
'r'
)
lines
=
file
.
readlines
()
file
.
close
()
for
line
in
lines
:
if
(
line
.
find
(
'def test_suite('
)
>
-
1
)
or
\
(
line
.
find
(
'framework('
)
>
-
1
):
return
True
return
False
def
runSuite
(
self
,
suite
):
if
suite
:
runner
=
self
.
getTestRunner
()
self
.
results
.
append
(
runner
.
run
(
suite
))
else
:
self
.
report
(
'No suitable tests found'
)
_runner
=
None
def
getTestRunner
(
self
):
if
self
.
_runner
is
None
:
self
.
_runner
=
self
.
createTestRunner
()
return
self
.
_runner
def
createTestRunner
(
self
):
return
FancyTestRunner
(
stream
=
sys
.
stderr
,
verbosity
=
self
.
verbosity
,
verbose_on_error
=
self
.
verbose_on_error
)
def
report
(
self
,
message
):
print
>>
sys
.
stderr
,
message
def
runAllTests
(
self
):
"""Run all tests found in the current working directory and
all subdirectories."""
self
.
runPath
(
self
.
basepath
)
def
listTestableNames
(
self
,
pathname
):
"""Return a list of the names to be traversed to build tests."""
names
=
os
.
listdir
(
pathname
)
for
ignore
in
(
'build'
,
'build-base'
):
if
ignore
in
names
:
# Don't recurse into build directories created by setup.py
names
.
remove
(
ignore
)
if
'.testinfo'
in
names
:
# allow local control
f
=
open
(
os
.
path
.
join
(
pathname
,
'.testinfo'
))
lines
=
filter
(
None
,
f
.
readlines
())
lines
=
map
(
lambda
x
:
x
[
-
1
]
==
'
\
n
'
and
x
[:
-
1
]
or
x
,
lines
)
names
=
filter
(
lambda
x
:
x
and
x
[
0
]
!=
'#'
,
lines
)
f
.
close
()
return
names
def
extractSuite
(
self
,
pathname
):
"""Extract and return the appropriate test suite."""
if
os
.
path
.
isdir
(
pathname
):
suite
=
unittest
.
TestSuite
()
for
name
in
self
.
listTestableNames
(
pathname
):
fullpath
=
os
.
path
.
join
(
pathname
,
name
)
sub_suite
=
self
.
extractSuite
(
fullpath
)
if
sub_suite
:
suite
.
addTest
(
sub_suite
)
return
suite
.
countTestCases
()
and
suite
or
None
elif
self
.
smellsLikeATest
(
pathname
):
dirname
,
name
=
os
.
path
.
split
(
pathname
)
working_dir
=
os
.
getcwd
()
try
:
if
dirname
:
os
.
chdir
(
dirname
)
try
:
suite
=
self
.
getSuiteFromFile
(
name
)
except
KeyboardInterrupt
:
raise
except
:
self
.
report
(
'No test suite found in file:
\
n
%s
\
n
'
%
pathname
)
if
self
.
verbosity
>
1
:
traceback
.
print_exc
()
suite
=
None
finally
:
os
.
chdir
(
working_dir
)
return
suite
else
:
# no test there!
return
None
def
runPath
(
self
,
pathname
):
"""Run all tests found in the directory named by pathname
and all subdirectories."""
if
not
os
.
path
.
isabs
(
pathname
):
pathname
=
os
.
path
.
join
(
self
.
basepath
,
pathname
)
if
self
.
mega_suite
:
suite
=
self
.
extractSuite
(
pathname
)
self
.
runSuite
(
suite
)
else
:
for
name
in
self
.
listTestableNames
(
pathname
):
fullpath
=
os
.
path
.
join
(
pathname
,
name
)
if
os
.
path
.
isdir
(
fullpath
):
self
.
runPath
(
fullpath
)
elif
self
.
smellsLikeATest
(
fullpath
):
self
.
runFile
(
fullpath
)
def
runFile
(
self
,
filename
):
"""Run the test suite defined by filename."""
working_dir
=
os
.
getcwd
()
dirname
,
name
=
os
.
path
.
split
(
filename
)
if
dirname
:
if
self
.
verbosity
>
2
:
print
>>
sys
.
stderr
,
'*** Changing directory to:'
,
dirname
os
.
chdir
(
dirname
)
self
.
report
(
'Running: %s'
%
filename
)
try
:
suite
=
self
.
getSuiteFromFile
(
name
)
except
KeyboardInterrupt
:
raise
except
:
traceback
.
print_exc
()
suite
=
None
if
suite
is
not
None
:
self
.
runSuite
(
suite
)
else
:
self
.
report
(
'No test suite found in file:
\
n
%s
\
n
'
%
filename
)
if
self
.
verbosity
>
2
:
print
>>
sys
.
stderr
,
'*** Restoring directory to:'
,
working_dir
os
.
chdir
(
working_dir
)
class
FancyTestResult
(
unittest
.
_TextTestResult
):
have_blank_line
=
1
verbose_on_error
=
0
def
__init__
(
self
,
*
args
,
**
kw
):
if
"verbose_on_error"
in
kw
:
self
.
verbose_on_error
=
kw
[
"verbose_on_error"
]
del
kw
[
"verbose_on_error"
]
unittest
.
_TextTestResult
.
__init__
(
self
,
*
args
,
**
kw
)
def
addSuccess
(
self
,
test
):
unittest
.
TestResult
.
addSuccess
(
self
,
test
)
if
self
.
showAll
:
self
.
stream
.
writeln
(
"ok"
)
elif
self
.
dots
:
self
.
stream
.
write
(
'.'
)
self
.
have_blank_line
=
0
def
addError
(
self
,
test
,
err
):
unittest
.
TestResult
.
addError
(
self
,
test
,
err
)
if
self
.
showAll
:
if
isinstance
(
err
[
0
],
str
):
self
.
stream
.
writeln
(
err
[
0
])
else
:
self
.
stream
.
writeln
(
excname
(
err
[
0
]))
elif
self
.
verbose_on_error
:
if
not
self
.
have_blank_line
:
self
.
stream
.
writeln
()
self
.
stream
.
write
(
self
.
getDescription
(
test
)
+
": "
)
if
isinstance
(
err
[
0
],
str
):
self
.
stream
.
writeln
(
err
[
0
])
else
:
self
.
stream
.
writeln
(
excname
(
err
[
0
]))
self
.
have_blank_line
=
1
elif
self
.
dots
:
self
.
stream
.
write
(
"E"
)
self
.
have_blank_line
=
0
def
addFailure
(
self
,
test
,
err
):
unittest
.
TestResult
.
addFailure
(
self
,
test
,
err
)
if
self
.
showAll
:
self
.
stream
.
writeln
(
"FAIL"
)
elif
self
.
verbose_on_error
:
if
not
self
.
have_blank_line
:
self
.
stream
.
writeln
()
self
.
stream
.
writeln
(
self
.
getDescription
(
test
)
+
": FAIL"
)
self
.
have_blank_line
=
1
elif
self
.
dots
:
self
.
stream
.
write
(
"F"
)
self
.
have_blank_line
=
0
def
excname
(
cls
):
if
cls
.
__module__
==
"exceptions"
:
return
cls
.
__name__
else
:
return
"%s.%s"
%
(
cls
.
__module__
,
cls
.
__name__
)
class
FancyTestRunner
(
unittest
.
TextTestRunner
):
def
__init__
(
self
,
*
args
,
**
kw
):
if
"verbose_on_error"
in
kw
:
self
.
verbose_on_error
=
kw
[
"verbose_on_error"
]
del
kw
[
"verbose_on_error"
]
else
:
self
.
verbose_on_error
=
False
unittest
.
TextTestRunner
.
__init__
(
self
,
*
args
,
**
kw
)
def
_makeResult
(
self
):
return
FancyTestResult
(
self
.
stream
,
self
.
descriptions
,
self
.
verbosity
,
verbose_on_error
=
self
.
verbose_on_error
)
class
TimingTestResult
(
FancyTestResult
):
def
__init__
(
self
,
*
args
,
**
kw
):
self
.
timings
=
[]
FancyTestResult
.
__init__
(
self
,
*
args
,
**
kw
)
def
startTest
(
self
,
test
):
FancyTestResult
.
startTest
(
self
,
test
)
self
.
_t2
=
None
self
.
_t1
=
time
.
time
()
def
stopTest
(
self
,
test
):
t2
=
time
.
time
()
if
self
.
_t2
is
not
None
:
t2
=
self
.
_t2
t
=
t2
-
self
.
_t1
self
.
timings
.
append
((
t
,
str
(
test
)))
FancyTestResult
.
stopTest
(
self
,
test
)
def
addSuccess
(
self
,
test
):
self
.
_t2
=
time
.
time
()
FancyTestResult
.
addSuccess
(
self
,
test
)
def
addError
(
self
,
test
,
err
):
self
.
_t2
=
time
.
time
()
FancyTestResult
.
addError
(
self
,
test
,
err
)
def
addFailure
(
self
,
test
,
err
):
self
.
_t2
=
time
.
time
()
FancyTestResult
.
addFailure
(
self
,
test
,
err
)
class
TimingTestRunner
(
FancyTestRunner
):
def
__init__
(
self
,
*
args
,
**
kw
):
FancyTestRunner
.
__init__
(
self
,
*
args
,
**
kw
)
self
.
timings
=
[]
def
_makeResult
(
self
):
r
=
TimingTestResult
(
self
.
stream
,
self
.
descriptions
,
self
.
verbosity
,
verbose_on_error
=
self
.
verbose_on_error
)
self
.
timings
=
r
.
timings
return
r
class
TestTimer
(
TestRunner
):
def
createTestRunner
(
self
):
return
TimingTestRunner
(
stream
=
sys
.
stderr
,
verbosity
=
self
.
verbosity
,
verbose_on_error
=
self
.
verbose_on_error
)
def
reportTimes
(
self
,
num
):
r
=
self
.
getTestRunner
()
r
.
timings
.
sort
()
for
item
in
r
.
timings
[
-
num
:]:
print
"%.1f %s"
%
item
def
remove_stale_bytecode
(
arg
,
dirname
,
names
):
names
=
map
(
os
.
path
.
normcase
,
names
)
for
name
in
names
:
if
name
.
endswith
(
".pyc"
)
or
name
.
endswith
(
".pyo"
):
srcname
=
name
[:
-
1
]
if
srcname
not
in
names
:
fullname
=
os
.
path
.
join
(
dirname
,
name
)
print
"Removing stale bytecode file"
,
fullname
os
.
unlink
(
fullname
)
def
main
(
args
):
usage_msg
=
"""Usage: python testrunner.py options
If run without options, testrunner will display this usage
message. If you want to run all test suites found in all
subdirectories of the current working directory, use the
-a option.
options:
-a
Run all tests found in all subdirectories of the current
working directory.
-m
Run all tests in a single, giant suite (consolidates error
reporting). [default]
-M
Run each test file's suite separately (noisier output, may
help in isolating global effects later).
-p
Add 'lib/python' to the Python search path. [default]
-P
*Don't* add 'lib/python' to the Python search path.
-d dirpath
Run all tests found in the directory specified by dirpath,
and recursively in all its subdirectories. The dirpath
should be a full system path.
-f filepath
Run the test suite found in the file specified. The filepath
should be a fully qualified path to the file to be run.
-v level
Set the Verbosity level to level. Newer versions of
unittest.py allow more options than older ones. Allowed
values are:
0 - Silent
1 - Quiet (produces a dot for each succesful test)
2 - Verbose (default - produces a line of output for each test)
-e
Modifier to the verbosity level. This causes a errors and
failures to generate a one-line report the test instead of
an 'E' or 'F'. This can make it easier to work on solving
problem while the tests are still running. This causes the
'silent' mode (-v0) to be less than completely silent.
-q
Run tests without producing verbose output. The tests are
normally run in verbose mode, which produces a line of
output for each test that includes the name of the test and
whether it succeeded. Running with -q is the same as
running with -v1.
-o filename
Output test results to the specified file rather than
to stderr.
-t N
Report time taken by the most expensive N tests.
-h
Display usage information.
"""
pathname
=
None
filename
=
None
test_all
=
False
verbosity
=
VERBOSE
mega_suite
=
True
set_python_path
=
True
timed
=
0
verbose_on_error
=
False
options
,
arg
=
getopt
.
getopt
(
args
,
'aemPhd:f:v:qMo:t:'
)
if
not
options
:
err_exit
(
usage_msg
)
for
name
,
value
in
options
:
if
name
==
'-a'
:
test_all
=
True
elif
name
==
'-m'
:
mega_suite
=
True
elif
name
==
'-M'
:
mega_suite
=
False
elif
name
==
'-p'
:
set_python_path
=
True
elif
name
==
'-P'
:
set_python_path
=
False
elif
name
==
'-d'
:
pathname
=
value
.
strip
()
elif
name
==
'-f'
:
filename
=
value
.
strip
()
elif
name
==
'-h'
:
err_exit
(
usage_msg
,
0
)
elif
name
==
'-e'
:
verbose_on_error
=
True
elif
name
==
'-v'
:
verbosity
=
int
(
value
)
elif
name
==
'-q'
:
verbosity
=
1
elif
name
==
'-t'
:
timed
=
int
(
value
)
assert
timed
>=
0
elif
name
==
'-o'
:
f
=
open
(
value
,
'w'
)
sys
.
stderr
=
f
else
:
err_exit
(
usage_msg
)
os
.
path
.
walk
(
os
.
curdir
,
remove_stale_bytecode
,
None
)
if
timed
:
testrunner
=
TestTimer
(
os
.
getcwd
(),
verbosity
,
mega_suite
,
verbose_on_error
)
else
:
testrunner
=
TestRunner
(
os
.
getcwd
(),
verbosity
,
mega_suite
,
verbose_on_error
)
if
set_python_path
:
script
=
sys
.
argv
[
0
]
script_dir
=
os
.
path
.
dirname
(
os
.
path
.
abspath
(
script
))
zope_dir
=
os
.
path
.
dirname
(
script_dir
)
sw_home
=
os
.
path
.
join
(
zope_dir
,
'lib'
,
'python'
)
if
verbosity
>
1
:
testrunner
.
report
(
"Adding %s to sys.path."
%
sw_home
)
sys
.
path
.
insert
(
0
,
sw_home
)
os
.
environ
[
'SOFTWARE_HOME'
]
=
sw_home
try
:
# Try to set up the testing environment (esp. INSTANCE_HOME,
# so we use the right custom_zodb.py.)
import
Testing
except
ImportError
:
pass
if
test_all
:
testrunner
.
runAllTests
()
elif
pathname
:
testrunner
.
runPath
(
pathname
)
elif
filename
:
testrunner
.
runFile
(
filename
)
if
timed
:
testrunner
.
reportTimes
(
timed
)
## Report overall errors / failures if there were any
fails
=
reduce
(
lambda
x
,
y
:
x
+
len
(
y
.
failures
),
testrunner
.
results
,
0
)
errs
=
reduce
(
lambda
x
,
y
:
x
+
len
(
y
.
errors
),
testrunner
.
results
,
0
)
if
fails
or
errs
:
msg
=
'='
*
70
msg
+=
"
\
n
OVERALL FAILED ("
if
fails
:
msg
+=
"total failures=%d"
%
fails
if
errs
:
if
fails
:
msg
+=
", "
msg
+=
"total errors=%d"
%
errs
msg
+=
")"
err_exit
(
msg
,
1
)
sys
.
exit
(
0
)
def
err_exit
(
message
,
rc
=
2
):
sys
.
stderr
.
write
(
"
\
n
%s
\
n
"
%
message
)
sys
.
exit
(
rc
)
if
__name__
==
'__main__'
:
main
(
sys
.
argv
[
1
:])
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