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

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 

6 

7"""Re-usable decorators and utilities for bob test code.""" 

8 

9import functools 

10import os 

11import traceback 

12import unittest 

13 

14from typing import Optional 

15 

16import click.testing 

17 

18 

19def datafile(f, module=None, path="data"): 

20 """datafile(f, [module], [data]) -> filename. 

21 

22 Returns the test file on the "data" subdirectory of the current module. 

23 

24 **Parameters:** 

25 

26 ``f`` : str 

27 This is the filename of the file you want to retrieve. Something like ``'movie.avi'``. 

28 

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. 

34 

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). 

38 

39 **Returns:** 

40 

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 

47 

48 return pkg_resources.resource_filename(resource, final_path) 

49 

50 

51def temporary_filename(prefix="bobtest_", suffix=".hdf5"): 

52 """temporary_filename([prefix], [suffix]) -> filename. 

53 

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: 

57 

58 .. code-block:: py 

59 

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) 

67 

68 **Parameters:** 

69 

70 ``prefix`` : str 

71 [Default: ``'bobtest_'``] The file name prefix to be added in front of the random file name 

72 

73 ``suffix`` : str 

74 [Default: ``'.hdf5'``] The file name extension of the temporary file name 

75 

76 **Returns:** 

77 

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 

83 

84 fd, name = tempfile.mkstemp(suffix, prefix) 

85 os.close(fd) 

86 os.unlink(name) 

87 return name 

88 

89 

90def extension_available(extension): 

91 """Decorator to check if a extension is available before enabling a test. 

92 

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: 

95 

96 .. code-block:: py 

97 

98 import bob.io.base.testing_utils 

99 

100 @bob.io.base.testing_utils.extension_available('.ext') 

101 def my_test(): 

102 ... 

103 """ 

104 

105 def test_wrapper(test): 

106 @functools.wraps(test) 

107 def wrapper(*args, **kwargs): 

108 from . import extensions 

109 

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 ) 

117 

118 return wrapper 

119 

120 return test_wrapper 

121 

122 

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. 

129 

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 """ 

139 

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