Coverage for src/bob/io/base/testing_utils.py: 76%
37 statements
« prev ^ index » next coverage.py v7.0.5, created at 2023-06-16 13:56 +0200
« prev ^ index » next coverage.py v7.0.5, created at 2023-06-16 13:56 +0200
1#!/usr/bin/env python
2# Andre Anjos <andre.anjos@idiap.ch>
3# Thu Feb 7 09:58:22 2013
4#
5# Copyright (C) 2011-2013 Idiap Research Institute, Martigny, Switzerland
7"""Re-usable decorators and utilities for bob test code."""
9import functools
10import os
11import traceback
12import unittest
14from typing import Optional
16import click.testing
19def datafile(f, module=None, path="data"):
20 """datafile(f, [module], [data]) -> filename.
22 Returns the test file on the "data" subdirectory of the current module.
24 **Parameters:**
26 ``f`` : str
27 This is the filename of the file you want to retrieve. Something like ``'movie.avi'``.
29 ``module``: str
30 [optional] This is the python-style package name of the module you want to retrieve
31 the data from. This should be something like ``bob.io.base``, but you
32 normally refer it using the ``__name__`` property of the module you want to
33 find the path relative to.
35 ``path``: str
36 [Default: ``'data'``] The subdirectory where the datafile will be taken from inside the module.
37 It can be set to ``None`` if it should be taken from the module path root (where the ``__init__.py`` file sits).
39 **Returns:**
41 ``filename`` : str
42 The full path of the file
43 """
44 resource = __name__ if module is None else module
45 final_path = f if path is None else os.path.join(path, f)
46 import pkg_resources
48 return pkg_resources.resource_filename(resource, final_path)
51def temporary_filename(prefix="bobtest_", suffix=".hdf5"):
52 """temporary_filename([prefix], [suffix]) -> filename.
54 Generates a temporary filename to be used in tests, using the default ``temp`` directory (on Unix-like systems, usually ``/tmp``).
55 Please note that you are responsible for deleting the file after your test finished.
56 A common way to assure the file to be deleted is:
58 .. code-block:: py
60 import bob.io.base.testing_utils
61 temp = bob.io.base.testing_utils.temporary_filename()
62 try:
63 # use the temp file
64 ...
65 finally:
66 if os.path.exist(temp): os.remove(temp)
68 **Parameters:**
70 ``prefix`` : str
71 [Default: ``'bobtest_'``] The file name prefix to be added in front of the random file name
73 ``suffix`` : str
74 [Default: ``'.hdf5'``] The file name extension of the temporary file name
76 **Returns:**
78 ``filename`` : str
79 The name of a temporary file that you can use in your test.
80 Don't forget to delete!
81 """
82 import tempfile
84 fd, name = tempfile.mkstemp(suffix, prefix)
85 os.close(fd)
86 os.unlink(name)
87 return name
90def extension_available(extension):
91 """Decorator to check if a extension is available before enabling a test.
93 This decorator is mainly used to decorate a test function, in order to skip tests when the extension is not available.
94 The syntax is:
96 .. code-block:: py
98 import bob.io.base.testing_utils
100 @bob.io.base.testing_utils.extension_available('.ext')
101 def my_test():
102 ...
103 """
105 def test_wrapper(test):
106 @functools.wraps(test)
107 def wrapper(*args, **kwargs):
108 from . import extensions
110 if extension in extensions():
111 return test(*args, **kwargs)
112 else:
113 raise unittest.SkipTest(
114 'Extension to handle "%s" files was not available at compile time'
115 % extension
116 )
118 return wrapper
120 return test_wrapper
123def assert_click_runner_result(
124 result: click.testing.Result,
125 exit_code: int = 0,
126 exception_type: Optional[type] = None,
127):
128 """Helper for asserting click runner results.
130 Parameters
131 ----------
132 result
133 The return value on ``click.testing.CLIRunner.invoke()``.
134 exit_code
135 The expected command exit code (defaults to 0).
136 exception_type
137 If given, will ensure that the raised exception is of that type.
138 """
140 m = (
141 "Click command exited with code '{}', instead of '{}'.\n"
142 "Exception:\n{}\n"
143 "Output:\n{}"
144 )
145 exception = (
146 "None"
147 if result.exc_info is None
148 else "".join(traceback.format_exception(*result.exc_info))
149 )
150 m = m.format(result.exit_code, exit_code, exception, result.output)
151 assert result.exit_code == exit_code, m
152 if exit_code == 0:
153 assert not result.exception, m
154 if exception_type is not None:
155 assert isinstance(result.exception, exception_type), m