2013-05-27 22:32:03 -03:00
|
|
|
README FOR IDLE TESTS IN IDLELIB.IDLE_TEST
|
|
|
|
|
2015-05-16 15:23:39 -03:00
|
|
|
0. Quick Start
|
|
|
|
|
2016-05-16 00:52:56 -03:00
|
|
|
Automated unit tests were added in 3.3 for Python 3.x.
|
2015-05-16 15:23:39 -03:00
|
|
|
To run the tests from a command line:
|
|
|
|
|
|
|
|
python -m test.test_idle
|
|
|
|
|
2016-05-16 00:52:56 -03:00
|
|
|
Human-mediated tests were added later in 3.4.
|
2015-05-16 15:23:39 -03:00
|
|
|
|
|
|
|
python -m idlelib.idle_test.htest
|
|
|
|
|
2013-06-29 19:22:02 -03:00
|
|
|
|
|
|
|
1. Test Files
|
|
|
|
|
2013-05-27 22:32:03 -03:00
|
|
|
The idle directory, idlelib, has over 60 xyz.py files. The idle_test
|
2016-05-16 00:52:56 -03:00
|
|
|
subdirectory should contain a test_xyz.py for each, where 'xyz' is
|
|
|
|
lowercased even if xyz.py is not. Here is a possible template, with the
|
2016-05-30 01:04:50 -03:00
|
|
|
blanks after '.' and 'as', and before and after '_' to be filled in.
|
2015-05-16 15:23:39 -03:00
|
|
|
|
2013-05-27 22:32:03 -03:00
|
|
|
import unittest
|
2013-06-29 19:22:02 -03:00
|
|
|
from test.support import requires
|
|
|
|
import idlelib. as
|
2013-05-27 22:32:03 -03:00
|
|
|
|
2013-06-29 19:22:02 -03:00
|
|
|
class _Test(unittest.TestCase):
|
2013-05-27 22:32:03 -03:00
|
|
|
|
|
|
|
def test_(self):
|
|
|
|
|
|
|
|
if __name__ == '__main__':
|
2015-05-16 15:23:39 -03:00
|
|
|
unittest.main(verbosity=2)
|
|
|
|
|
2016-05-16 00:52:56 -03:00
|
|
|
Add the following at the end of xyy.py, with the appropriate name added
|
|
|
|
after 'test_'. Some files already have something like this for htest.
|
|
|
|
If so, insert the import and unittest.main lines before the htest lines.
|
2013-05-27 22:32:03 -03:00
|
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
import unittest
|
|
|
|
unittest.main('idlelib.idle_test.test_', verbosity=2, exit=False)
|
|
|
|
|
2013-06-29 19:22:02 -03:00
|
|
|
|
|
|
|
|
2015-05-16 15:23:39 -03:00
|
|
|
2. GUI Tests
|
|
|
|
|
2016-05-16 00:52:56 -03:00
|
|
|
When run as part of the Python test suite, Idle GUI tests need to run
|
|
|
|
test.support.requires('gui'). A test is a GUI test if it creates a
|
|
|
|
tkinter.Tk root or master object either directly or indirectly by
|
|
|
|
instantiating a tkinter or idle class. GUI tests cannot run in test
|
|
|
|
processes that either have no graphical environment available or are not
|
|
|
|
allowed to use it.
|
2015-05-16 15:23:39 -03:00
|
|
|
|
2016-05-16 00:52:56 -03:00
|
|
|
To guard a module consisting entirely of GUI tests, start with
|
|
|
|
|
|
|
|
from test.support import requires
|
|
|
|
requires('gui')
|
|
|
|
|
|
|
|
To guard a test class, put "requires('gui')" in its setUpClass function.
|
|
|
|
|
2016-06-04 03:32:18 -03:00
|
|
|
To avoid interfering with other GUI tests, all GUI objects must be destroyed and
|
2016-06-03 23:19:17 -03:00
|
|
|
deleted by the end of the test. The Tk root created in a setUpX function should
|
|
|
|
be destroyed in the corresponding tearDownX and the module or class attribute
|
|
|
|
deleted. Others widgets should descend from the single root and the attributes
|
|
|
|
deleted BEFORE root is destroyed. See https://bugs.python.org/issue20567.
|
2013-07-28 17:39:44 -03:00
|
|
|
|
2013-06-29 19:22:02 -03:00
|
|
|
@classmethod
|
|
|
|
def setUpClass(cls):
|
|
|
|
requires('gui')
|
2013-07-28 17:39:44 -03:00
|
|
|
cls.root = tk.Tk()
|
2016-06-03 23:19:17 -03:00
|
|
|
cls.text = tk.Text(root)
|
2013-07-28 17:39:44 -03:00
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def tearDownClass(cls):
|
2016-06-03 23:19:17 -03:00
|
|
|
del cls.text
|
2016-06-04 00:53:56 -03:00
|
|
|
cls.root.update_idletasks()
|
2013-07-28 17:39:44 -03:00
|
|
|
cls.root.destroy()
|
2014-02-27 19:47:49 -04:00
|
|
|
del cls.root
|
2013-06-29 19:22:02 -03:00
|
|
|
|
2016-06-04 00:53:56 -03:00
|
|
|
The update_idletasks call is sometimes needed to prevent the following warning
|
|
|
|
either when running a test alone or as part of the test suite (#27196).
|
|
|
|
can't invoke "event" command: application has been destroyed
|
|
|
|
...
|
|
|
|
"ttk::ThemeChanged"
|
2015-05-16 15:23:39 -03:00
|
|
|
|
|
|
|
Requires('gui') causes the test(s) it guards to be skipped if any of
|
2016-06-03 23:19:17 -03:00
|
|
|
these conditions are met:
|
|
|
|
|
2016-05-16 00:52:56 -03:00
|
|
|
- The tests are being run by regrtest.py, and it was started without
|
|
|
|
enabling the "gui" resource with the "-u" command line option.
|
2016-06-03 23:19:17 -03:00
|
|
|
|
2016-05-16 00:52:56 -03:00
|
|
|
- The tests are being run on Windows by a service that is not allowed
|
|
|
|
to interact with the graphical environment.
|
2016-06-03 23:19:17 -03:00
|
|
|
|
|
|
|
- The tests are being run on Linux and X Windows is not available.
|
|
|
|
|
2016-05-16 00:52:56 -03:00
|
|
|
- The tests are being run on Mac OSX in a process that cannot make a
|
|
|
|
window manager connection.
|
2016-06-03 23:19:17 -03:00
|
|
|
|
2014-06-02 18:01:29 -03:00
|
|
|
- tkinter.Tk cannot be successfully instantiated for some reason.
|
2016-06-03 23:19:17 -03:00
|
|
|
|
2014-06-02 18:01:29 -03:00
|
|
|
- test.support.use_resources has been set by something other than
|
|
|
|
regrtest.py and does not contain "gui".
|
2016-06-03 23:19:17 -03:00
|
|
|
|
2016-05-16 00:52:56 -03:00
|
|
|
Tests of non-GUI operations should avoid creating tk widgets. Incidental
|
|
|
|
uses of tk variables and messageboxes can be replaced by the mock
|
|
|
|
classes in idle_test/mock_tk.py. The mock text handles some uses of the
|
|
|
|
tk Text widget.
|
2013-06-29 19:22:02 -03:00
|
|
|
|
|
|
|
|
2015-05-16 15:23:39 -03:00
|
|
|
3. Running Unit Tests
|
2013-06-29 19:22:02 -03:00
|
|
|
|
2015-05-16 15:23:39 -03:00
|
|
|
Assume that xyz.py and test_xyz.py both end with a unittest.main() call.
|
2016-05-16 00:52:56 -03:00
|
|
|
Running either from an Idle editor runs all tests in the test_xyz file
|
|
|
|
with the version of Python running Idle. Test output appears in the
|
|
|
|
Shell window. The 'verbosity=2' option lists all test methods in the
|
|
|
|
file, which is appropriate when developing tests. The 'exit=False'
|
|
|
|
option is needed in xyx.py files when an htest follows.
|
2013-06-29 19:22:02 -03:00
|
|
|
|
2015-05-16 15:23:39 -03:00
|
|
|
The following command lines also run all test methods, including
|
2016-06-04 03:32:18 -03:00
|
|
|
GUI tests, in test_xyz.py. (Both '-m idlelib' and '-m idlelib.idle'
|
2016-05-16 00:52:56 -03:00
|
|
|
start Idle and so cannot run tests.)
|
2013-05-27 22:32:03 -03:00
|
|
|
|
2015-05-16 15:23:39 -03:00
|
|
|
python -m idlelib.xyz
|
2013-06-29 19:22:02 -03:00
|
|
|
python -m idlelib.idle_test.test_xyz
|
2013-05-27 22:32:03 -03:00
|
|
|
|
2015-05-16 15:23:39 -03:00
|
|
|
The following runs all idle_test/test_*.py tests interactively.
|
|
|
|
|
|
|
|
>>> import unittest
|
|
|
|
>>> unittest.main('idlelib.idle_test', verbosity=2)
|
|
|
|
|
2016-05-16 00:52:56 -03:00
|
|
|
The following run all Idle tests at a command line. Option '-v' is the
|
|
|
|
same as 'verbosity=2'.
|
2013-05-27 22:32:03 -03:00
|
|
|
|
|
|
|
python -m unittest -v idlelib.idle_test
|
2013-06-29 19:22:02 -03:00
|
|
|
python -m test -v -ugui test_idle
|
2013-05-27 22:32:03 -03:00
|
|
|
python -m test.test_idle
|
|
|
|
|
2016-05-16 00:52:56 -03:00
|
|
|
The idle tests are 'discovered' by
|
|
|
|
idlelib.idle_test.__init__.load_tests, which is also imported into
|
|
|
|
test.test_idle. Normally, neither file should be changed when working on
|
|
|
|
individual test modules. The third command runs unittest indirectly
|
|
|
|
through regrtest. The same happens when the entire test suite is run
|
|
|
|
with 'python -m test'. So that command must work for buildbots to stay
|
|
|
|
green. Idle tests must not disturb the environment in a way that makes
|
|
|
|
other tests fail (issue 18081).
|
2013-05-27 22:32:03 -03:00
|
|
|
|
2016-05-16 00:52:56 -03:00
|
|
|
To run an individual Testcase or test method, extend the dotted name
|
|
|
|
given to unittest on the command line.
|
2013-05-27 22:32:03 -03:00
|
|
|
|
2014-02-15 07:01:08 -04:00
|
|
|
python -m unittest -v idlelib.idle_test.test_xyz.Test_case.test_meth
|
2015-05-16 15:23:39 -03:00
|
|
|
|
|
|
|
|
|
|
|
4. Human-mediated Tests
|
|
|
|
|
2016-05-16 00:52:56 -03:00
|
|
|
Human-mediated tests are widget tests that cannot be automated but need
|
|
|
|
human verification. They are contained in idlelib/idle_test/htest.py,
|
|
|
|
which has instructions. (Some modules need an auxiliary function,
|
|
|
|
identified with "# htest # on the header line.) The set is about
|
|
|
|
complete, though some tests need improvement. To run all htests, run the
|
|
|
|
htest file from an editor or from the command line with:
|
2015-05-16 15:23:39 -03:00
|
|
|
|
|
|
|
python -m idlelib.idle_test.htest
|
2017-07-16 01:39:59 -03:00
|
|
|
|
|
|
|
|
|
|
|
5. Test Coverage
|
|
|
|
|
|
|
|
Install the coverage package into your Python 3.6 site-packages
|
|
|
|
directory. (Its exact location depends on the OS).
|
|
|
|
> python3 -m pip install coverage
|
|
|
|
(On Windows, replace 'python3 with 'py -3.6' or perhaps just 'python'.)
|
|
|
|
|
|
|
|
The problem with running coverage with repository python is that
|
|
|
|
coverage uses absolute imports for its submodules, hence it needs to be
|
|
|
|
in a directory in sys.path. One solution: copy the package to the
|
|
|
|
directory containing the cpython repository. Call it 'dev'. Then run
|
|
|
|
coverage either directly or from a script in that directory so that
|
|
|
|
'dev' is prepended to sys.path.
|
|
|
|
|
|
|
|
Either edit or add dev/.coveragerc so it looks something like this.
|
|
|
|
---
|
|
|
|
# .coveragerc sets coverage options.
|
|
|
|
[run]
|
|
|
|
branch = True
|
|
|
|
|
|
|
|
[report]
|
|
|
|
# Regexes for lines to exclude from consideration
|
|
|
|
exclude_lines =
|
|
|
|
# Don't complain if non-runnable code isn't run:
|
|
|
|
if 0:
|
|
|
|
if __name__ == .__main__.:
|
|
|
|
|
|
|
|
.*# htest #
|
|
|
|
if not _utest:
|
|
|
|
if _htest:
|
|
|
|
---
|
|
|
|
The additions for IDLE are 'branch = True', to test coverage both ways,
|
|
|
|
and the last three exclude lines, to exclude things peculiar to IDLE
|
|
|
|
that are not executed during tests.
|
|
|
|
|
|
|
|
A script like the following cover.bat (for Windows) is very handy.
|
|
|
|
---
|
|
|
|
@echo off
|
|
|
|
rem Usage: cover filename [test_ suffix] # proper case required by coverage
|
|
|
|
rem filename without .py, 2nd parameter if test is not test_filename
|
|
|
|
setlocal
|
|
|
|
set py=f:\dev\3x\pcbuild\win32\python_d.exe
|
|
|
|
set src=idlelib.%1
|
|
|
|
if "%2" EQU "" set tst=f:/dev/3x/Lib/idlelib/idle_test/test_%1.py
|
|
|
|
if "%2" NEQ "" set tst=f:/dev/ex/Lib/idlelib/idle_test/test_%2.py
|
|
|
|
|
|
|
|
%py% -m coverage run --pylib --source=%src% %tst%
|
|
|
|
%py% -m coverage report --show-missing
|
|
|
|
%py% -m coverage html
|
|
|
|
start htmlcov\3x_Lib_idlelib_%1_py.html
|
|
|
|
rem Above opens new report; htmlcov\index.html displays report index
|
|
|
|
---
|
|
|
|
The second parameter was added for tests of module x not named test_x.
|
|
|
|
(There were several before modules were renamed, now only one is left.)
|