-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathtests.py
243 lines (197 loc) · 7.14 KB
/
tests.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
"""
tests
~~~~~
Tests for the :mod:`~scratchdir` module.
"""
import io
import os
import pytest
import shutil
try:
import pathlib
except ImportError:
import pathlib2 as pathlib
import scratchdir
def is_file_like_obj(obj):
"""
Helper function to check that the given object implements all public methods of the
:class:`~io.IOBase` abstract class.
"""
return all((hasattr(obj, name) for name in dir(io.IOBase) if not name.startswith('_')))
def is_pardir(pardir, subdir):
"""
Helper function to check if the given path is a parent of another.
"""
return pathlib.Path(pardir) in pathlib.Path(subdir).parents
@pytest.fixture(scope='function')
def scratch_dir(tmpdir):
"""
Fixture that yields a :class:`~scratchdir.ScratchDir` instance with a root directory
that is unique to each test invocation.
"""
return scratchdir.ScratchDir(root=tmpdir.strpath)
@pytest.fixture(scope='function')
def active_scratch_dir(scratch_dir):
"""
Fixture that yields a :class:`~scratchdir.ScratchDir` instance that has already performed
the setup process and is active.
"""
with scratch_dir:
yield scratch_dir
def test_scratch_enter_calls_setup(scratch_dir, mocker):
"""
Assert that :meth:`~scratchdir.ScratchDir.__enter__` calls :meth:`~scratchdir.ScratchDir.setup`.
"""
mocker.patch.object(scratch_dir, 'setup', wraps=scratch_dir.setup)
with scratch_dir:
assert scratch_dir.setup.called
def test_scratch_exit_calls_teardown(scratch_dir, mocker):
"""
Assert that :meth:`~scratchdir.ScratchDir.__exit__` calls :meth:`~scratchdir.ScratchDir.teardown`.
"""
mocker.patch.object(scratch_dir, 'teardown', wraps=scratch_dir.teardown)
with scratch_dir:
pass
assert scratch_dir.teardown.called
def test_scratch_is_not_active_when_wd_not_set(scratch_dir):
"""
Assert that :prop:`~scratchdir.ScratchDir.active` is `False` when the
working directory is not set.
"""
scratch_dir.wd = None
assert not scratch_dir.is_active
def test_scratch_is_not_active_when_wd_does_not_exist(active_scratch_dir, mocker):
"""
Assert that an active :prop:`~scratchdir.ScratchDir.active` is `False` when the
working directory does not exist.
"""
assert active_scratch_dir.is_active
mocker.patch('os.path.exists', return_value=False)
assert not active_scratch_dir.is_active
def test_scratch_is_not_active_when_setup_not_called(scratch_dir):
"""
Assert that a :prop:`~scratchdir.ScratchDir.is_active` is `False` when
:meth:`~scratchdir.ScratchDir.setup` has not been called.
"""
assert not scratch_dir.is_active
def test_scratch_is_active_when_inside_context_manager(scratch_dir):
"""
Assert that a :prop:`~scratchdir.ScratchDir.is_active` is `True` when
the :meth:`~scratchdir.ScratchDir.__enter__` is called.
"""
assert not scratch_dir.is_active
with scratch_dir:
assert scratch_dir.is_active
def test_scratch_is_not_active_after_context_manager(scratch_dir):
"""
Assert that a :prop:`~scratchdir.ScratchDir.is_active` is `False` after
the :meth:`~scratchdir.ScratchDir.__exit__` is called.
"""
with scratch_dir:
pass
assert not scratch_dir.is_active
def test_scratch_setup_assigns_wd(scratch_dir):
"""
Assert that :attr:`~scratchdir.ScratchDir.wd` is set after :meth:`~scratchdir.ScratchDir.setup` is called.
"""
with scratch_dir:
assert scratch_dir.wd != scratchdir.DEFAULT_WD
def test_scratch_teardown_unassigns_wd(scratch_dir):
"""
Assert that :attr:`~scratchdir.ScratchDir.wd` is not set after :meth:`~scratchdir.ScratchDir.teardown` is called.
"""
with scratch_dir:
pass
assert scratch_dir.wd == scratchdir.DEFAULT_WD
def test_scratch_teardown_removes_files(scratch_dir, mocker):
"""
Assert that :func:`~shutil.rmtree` is called when :func:`~scratchdir.ScratchDir.teardown` is called.
"""
mock = mocker.patch('shutil.rmtree')
with scratch_dir:
pass
assert mock.called
@pytest.mark.parametrize('method_name', [
'teardown',
'child',
'file',
'named',
'spooled',
'secure',
'dir',
'directory',
'filename',
'join',
'TemporaryFile',
'NamedTemporaryFile',
'SpooledTemporaryFile',
'mkstemp',
'mkdtemp'
])
def test_scratch_methods_raise_when_not_active(scratch_dir, method_name):
"""
Assert that expected methods on the :class:`~scratchdir.ScratchDir` class raise a
:class:`~scratchdir.ScratchDirInactiveError` exception when called while the instance is not active.
"""
method = getattr(scratch_dir, method_name)
with pytest.raises(scratchdir.ScratchDirInactiveError):
assert method()
@pytest.mark.parametrize('method_name', [
'file',
'named',
'secure',
'TemporaryFile',
'NamedTemporaryFile',
'mkstemp'
])
def test_scratch_methods_given_unknown_subdir_raise(active_scratch_dir, method_name):
"""
Assert that methods on :class:`~scratchdir.ScratchDir` that support a `dir` parameter will raise
a :class:`~FileNotFoundError` when the dir does not exist.
"""
method = getattr(active_scratch_dir, method_name)
with pytest.raises(FileNotFoundError):
assert method(dir='foo')
def test_scratch_child_returns_scratch_dir_instance(active_scratch_dir):
"""
Assert that :meth:`~scratchdir.ScratchDir.child` returns a :class:`~scratchdir.ScratchDir` instance.
"""
assert isinstance(active_scratch_dir.child(), scratchdir.ScratchDir)
def test_scratch_child_wd_is_within_parent_wd(active_scratch_dir):
"""
Assert that :meth:`~scratchdir.ScratchDir.child` returns a :class:`~scratchdir.ScratchDir` instance
whose working directory is a subdirectory of the working directory of the parent instance.
"""
with active_scratch_dir.child() as child:
assert is_pardir(active_scratch_dir.wd, child.wd)
@pytest.mark.parametrize('method_name', [
'file',
'named',
'TemporaryFile',
'NamedTemporaryFile'
])
def test_scratch_file_supports_file_obj_interface(active_scratch_dir, method_name):
"""
Assert that methods of :class:`~scratchdir.ScratchDir` that are expected to return file-like objects
do so and these objects implement, atleast, the :class:`~io.IOBase` interface.
"""
method = getattr(active_scratch_dir, method_name)
assert is_file_like_obj(method())
def test_scratch_secure_returns_fd_and_name_by_default(active_scratch_dir):
"""
Assert that :meth:`~scratchdir.ScratchDir` returns a two item tuple containing the file descriptor
and filename of the newly created temporary file.
"""
result = active_scratch_dir.secure()
assert isinstance(result, tuple)
assert isinstance(result[0], int)
assert isinstance(result[1], str)
assert os.path.exists(result[1])
def test_scratch_secure_returns_only_name_on_toggle(active_scratch_dir):
"""
Assert that :meth:`~scratchdir.ScratchDir` returns a :class:`str` containing the filename when
configured to do so.
"""
result = active_scratch_dir.secure(return_fd=False)
assert isinstance(result, str)
assert os.path.exists(result)