pytest_helper_main module¶
Description¶
This module contains helper functions for using the pytest unit testing framework.
Functions to help with running tests¶
-
pytest_helper.pytest_helper_main.
script_run
(testfile_paths=None, self_test=False, pytest_args=None, pyargs=False, modify_syspath=None, calling_mod_name=None, calling_mod_path=None, single_call=True, exit=True, always_run=False, skip=False, pskip=False, level=2)[source]¶ Run pytest on the specified test files when the calling module is run as a script. Using this function requires at least pytest 2.0. If the module from which this script is called is not
__main__
then this script immediately returns and does nothing (unlessalways_run
is set true).The argument
testfile_paths
should be either the pathname of a file or directory to run pytest on, or else a list of such file and directory paths. Any relative paths will be interpreted relative to the directory of the module which calls this function.The calculation of relative paths can fail in cases where Python’s CWD is changed between the time when the calling module is loaded and a pytest-helper function is called. (Most programs do not change the CWD like that, or if they do they return it to its previous value.) In those cases the
pytest_helper.init()
function can be called just after importingpytest_helper
(or absolute pathnames can be used).The recommended use of
script_run
is to place it inside a guard conditional which runs only for scripts, and to call it before doing any other non-system imports. The early call avoids possible problems with relative imports when running it from inside modules that are part of packages. The use of the guard conditional is optional, but is more explicit and slightly more efficient.If
self_test
isTrue
then pytest will be run on the file of the calling script itself, i.e., tests are assumed to be in the same file as the code to test.The
pytest_args
allows command-line arguments to be passed to pytest when it is run. It can be set to a string of all the options or else a list of strings (with one item in the list for each flag and for each flag argument). Options containing non-separator spaces, such as whitespace in quoted filenames, are currently not allowed in the string form. In that case the list form should be used.The pytest command-line argument
--pyargs
allows a mix of filenames and Python package names to be passed to pytest as test files. Note that pytest always imports modules as part of a package if there is an__init__.py
file in the directory; the--pyargs
just allows Python-style module names. Whenpyargs
is set true pytest will be run with the--pyargs
option set, and any items intestfile_paths
which contain no path-separator character (slash) will be left unprocessed rather than being converted into absolute pathnames. The pytest option--pyargs
will not work correctly unless this flag is set. The default ispyargs=False
, i.e., by default all paths are converted to absolute pathnames. It usually will not matter, but in this mode you can specify a directory name relative to the current directory and not have it treated as a Python module name by using./dirname
rather than simplyfilename
.If
modify_syspath
is explicitly setTrue
then the first item in thesys.path
list is deleted, but only if it has not been deleted before (by this package or by theset_package_attribute
package). Ifmodify_syspath
is set false then the system path is not modified. The default isNone
, which modifies the system path if the calling module is part of a package and otherwise does not. The reason for this option is that when a module is run as a script Python always adds the directory of the script as the first item insys.path
. This can sometimes cause hard-to-trace import errors when directories inside paths are inserted insys.path
. Deleting that added directory first prevents those errors. Ifscript_run
does not call exit at the end (becauseexit==False
) then, before returning, any modified system path is restored to a saved copy of its full, original condition.The
calling_mod_name
argument is a fallback in case the calling function’s module is not correctly located by introspection. It is usually not required (though it is slightly more efficient). Use it as:module_name=__name__
. Similarly forcalling_mod_path
, but that should be passed the pathname of the calling module’s file.By default the script-run program passes all the user-specified testfile paths to a single run of pytest. If
single_call
is set false then instead the paths are looped over, one by one, with a separate call to pytest on each one.If
exit
is set falsesys.exit(0)
will not be called after the tests finish. The default is to exit after the tests finish (otherwise when tests run from the top of a module are finished the rest of the file will still be executed). Settingexit
false can be used to make several separatescript_run
calls in sequence.If
always_run
is true then tests will be run regardless of whether or not the function was called from a script.If
skip
is set to true from the default false then the function returns immediately without doing anything. This is just a keyword argument switch that can be used to temporarily turn off test-running without large changes to the code. The module runs normally without pytest being invoked. Thepskip
option is the same, except that it also sets the package attribute viaset_package_attribute
. This option is useful if the script is being run inside a package, since it allows relative imports to be used in the script. (In this case themodify_syspath
argument is passed to theinit
function ofset_package_attribute
).The parameter
level
is the level up the calling stack to look for the calling module and should not usually need to be set.
-
pytest_helper.pytest_helper_main.
sys_path
(dirs_to_add=None, add_parent=False, add_grandparent=False, add_gn_parent=False, add_self=False, insert_position=1, calling_mod_name=None, calling_mod_path=None, level=2)[source]¶ Add the canonical absolute pathname of each directory in the list
dirs_to_add
tosys.path
(but only if it isn’t there already). A single string representing a path can also be passed todirs_to_add
. Relative pathnames are always interpreted relative to the directory of the calling module (i.e., the directory of the module that calls this function). The notes about relative paths for thescript_run
function also apply here.The keyword arguments
add_parent
andadd_grandparent
are shortcuts that can be used instead of putting the equivalent relative path on the listdirs_to_add
. If the keyword argumentadd_gn_parent
is set to a non-negative integern
then the (grand)nparent is added to the path, where (grand)1parent is the grandparent. Ifadd_self
is true then the directory of the calling module is added to the systemsys.path
list.The keyword argument
insert_position
determines where insys.path
the the pathnames are placed (usinginsert
). The default is 1. If inserting at 0 watch for conflicts with themodify_syspath
options toscript_run
andinit
.The parameters
calling_mod_name
andcalling_mod_dir
can be set as a fallback in case the introspection for finding the calling module’s information fails for some reason. The parameterlevel
is the level up the calling stack to look for the calling module and should not usually need to be set.
-
pytest_helper.pytest_helper_main.
restore_previous_sys_path
()[source]¶ This function undoes the effect of the last call to
sys_path
, returningsys.path
to its previous, saved value. This can be useful at times.
-
pytest_helper.pytest_helper_main.
init
(modify_syspath=None, conf=True, calling_mod_name=None, calling_mod_path=None, level=2)[source]¶ A function to initialize the
pytest_helper
module just after importing it. This function is useful, for example, in rare cases where Python’s current working directory (CWD) is changed between the time when the executing module is first loaded and whenscript_run
orsys_path
is called from that module. In those cases the module’s pathname relative to the previous CWD will be incorrectly expanded relative to the new CWD. Calling this function causes the earlier-expanded pathname to be cached. This function should be called before any function call or import which changes the CWD and which doesn’t change it back afterward. Importingpytest_helper
just after the system imports and then immediately calling this function should work.The
modify_syspath
option affects whether or not thesys.path[0]
element is removed. The defaultNone
is to remove it for scripts run from inside packages since that can mess up the imports of modules running as packages.If the parameter
conf
is set false then no configuration files will be searched for or used. Otherwise, the configuration file will be searched for by any function which has an option settable in a config file (including theinit
function itself). The configuration information for modules is cached, and so is only looked up once.
Functions to help in writing tests¶
-
pytest_helper.pytest_helper_main.
autoimport
(noclobber=True, skip=None, calling_mod_name=None, calling_mod_path=None, level=2)[source]¶ This function imports some pytest-helper and pytest attributes into the calling module’s global namespace. This avoids having to explicitly do common imports. Even if
autoimport
is called from inside a test function it will still place its imports in the module’s global namespace. APytestHelperException
will be raised if any of those globals already exist, unlessnoclobber
is set false.The
imports
option is a list of (name,value) pairs to import automatically. Since using it each time would be as much trouble as doing the imports, explicitly, it is mainly meant to be set in configuration files. In a config file the values are evaluated in the global namespace ofpytest_helper
. Theskip
option is a list of names to skip in importing, if just one or two are causing problems locally to a file.The default variables that are imported from the
pytest_helper
module arelocals_to_globals
,clear_locals_from_globals
, andunindent
. The modulepytest
is imported aspytest
. The functions from pytest that are imported by default areraises
,fail
,fixture
, andskip
,xfail
, andapprox
.
-
pytest_helper.pytest_helper_main.
locals_to_globals
(fun_locals=None, fun_globals=None, clear=False, noclobber=True, ignore_params=True, level=2)[source]¶ Copy all local variables in the calling test function’s local scope to the global scope of the module from which that function was called. The test function’s parameters are ignored (i.e., they are local variables but they are not made global). Setting
ignore_params
false copies them, too.This routine should generally be called near the end of a test function or fixture. It allows for variables to be shared with other test functions, as globals.
Calls to
locals_to_globals
do not allow existing global variables to be overwritten unless they were either 1) set by a previous run of this function, or 2)noclobber
is set false. Otherwise aLocalsToGlobalsError
will be raised. This avoids accidentally overwriting important global attributes (especially when tests are in the same module being tested).This routine’s effect is similar to the effect of explicitly declaring each of a function’s local variables to be
global
, or doingglobals().update(locals())
, except that 1) it ignores local variables which are function parameters, 2) it adds more error checks, and 3) it can clear any previously-set values.Note that the globals set with
locals_to_globals
can be accessed and used in any other test function in the module, but they are still read-only (as usual with globals). An attribute must be explicitly declaredglobal
in order to modify the global value. (It is then no longer local to the function, solocals_to_globals
will not affect it, butclear
will still remember it and clear it if called.)If
clear
is true (the default is false) then any variable that was set on the last run of this function will be automatically cleared before any new ones are set. This is good to call in the first-run fixture or setup function, since it helps avoid “false positives” where a later test succeeds only because of a global left over from a previous test. Note globals on the saved list of globals are cleared even if their values were later modified.The argument
fun_locals
can be used as a fallback to pass thelocals()
dict from the function in case the introspection technique does not work for some reason. Thefun_globals
argument can similarly be passed globals() as a fallback. So you could call:locals_to_globals(locals(), globals())
to bypass the introspection used to locate the two dicts.
The
level
argument is the level up the calling stack to look for the calling function. In order to call an intermediate function which then calls this function, for example,level
would need to be increased by one.
-
pytest_helper.pytest_helper_main.
clear_locals_from_globals
(level=2)[source]¶ Clear all the global variables that were added by locals_to_globals. This is called automatically by
locals_to_globals
unless that function is run withclear
set false. This only affects the module from which the function is called.
-
pytest_helper.pytest_helper_main.
unindent
(unindent_level, string)[source]¶ Strip indentation from a docstring. This function is useful in tests where you have assertions that something equals a multi-line string. It allows the strings to be represented as multi-line docstrings but indented in a way that matches the surrounding code.
Calling this function on a string 1) splits it into lines (keeping empty lines, too), 2) discards the first and last line, and 3) removes
unindent_level
characters from the beginning of each line. Then 4) the modified lines are joined with newline and returned. Raises an exception on an attempt to strip non-whitespace or if there are fewer than two lines.