tests.test_generate_files   A
last analyzed

Complexity

Total Complexity 38

Size/Duplication

Total Lines 440
Duplicated Lines 40 %

Importance

Changes 0
Metric Value
wmc 38
eloc 278
dl 176
loc 440
rs 9.36
c 0
b 0
f 0

23 Functions

Rating   Name   Duplication   Size   Complexity  
A test_raise_undefined_variable_project_dir() 0 14 2
A test_generate_files_with_linux_newline() 16 16 2
A test_generate_files_output_dir() 0 14 1
A test_ensure_dir_is_templated_raises() 0 5 2
A test_generate_files_with_jinja2_environment() 0 19 1
A test_generate_files() 0 14 1
A test_generate_files_with_windows_newline() 16 16 2
A test_generate_files_binaries() 0 19 1
A test_generate_files_nontemplated_exception() 0 11 2
A test_generate_files_absolute_path() 0 8 1
A test_generate_files_with_trailing_newline_forced_to_linux_by_context() 17 17 2
A test_generate_files_with_windows_newline_forced_to_linux_by_context() 17 17 2
A test_generate_files_with_overwrite_if_exists_with_skip_if_file_exists() 24 24 2
A test_generate_files_with_overwrite_if_exists() 22 22 1
A test_raise_undefined_variable_file_name() 0 13 2
A test_generate_files_permissions() 0 42 1
A test_raise_undefined_variable_file_name_existing_project() 19 19 2
A test_raise_undefined_variable_dir_name_existing_project() 23 23 2
A undefined_context() 0 5 1
A test_raise_undefined_variable_file_content() 0 13 2
A test_generate_files_with_skip_if_file_exists() 22 22 2
A test_raise_undefined_variable_dir_name() 0 17 2
A test_keep_project_dir_on_failure() 0 10 2

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

1
"""Tests for `generate_files` function and related errors raising.
2
3
Use the global clean_system fixture and run additional teardown code to remove
4
some special folders.
5
"""
6
from pathlib import Path
7
8
import pytest
9
from binaryornot.check import is_binary
10
11
from cookiecutter import exceptions, generate
12
13
14
@pytest.mark.parametrize('invalid_dirname', ['', '{foo}', '{{foo', 'bar}}'])
15
def test_ensure_dir_is_templated_raises(invalid_dirname):
16
    """Verify `ensure_dir_is_templated` raises on wrong directories names input."""
17
    with pytest.raises(exceptions.NonTemplatedInputDirException):
18
        generate.ensure_dir_is_templated(invalid_dirname)
19
20
21
def test_generate_files_nontemplated_exception(tmp_path):
22
    """
23
    Verify `generate_files` raises when no directories to render exist.
24
25
    Note: Check `tests/test-generate-files-nontemplated` location to understand.
26
    """
27
    with pytest.raises(exceptions.NonTemplatedInputDirException):
28
        generate.generate_files(
29
            context={'cookiecutter': {'food': 'pizza'}},
30
            repo_dir='tests/test-generate-files-nontemplated',
31
            output_dir=tmp_path,
32
        )
33
34
35
def test_generate_files(tmp_path):
36
    """Verify directory name correctly rendered with unicode containing context."""
37
    generate.generate_files(
38
        context={'cookiecutter': {'food': 'pizzä'}},
39
        repo_dir='tests/test-generate-files',
40
        output_dir=tmp_path,
41
    )
42
43
    simple_file = Path(tmp_path, 'inputpizzä/simple.txt')
44
    assert simple_file.exists()
45
    assert simple_file.is_file()
46
47
    simple_text = Path(simple_file).read_text(encoding='utf-8')
48
    assert simple_text == 'I eat pizzä'
49
50
51 View Code Duplication
def test_generate_files_with_linux_newline(tmp_path):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
52
    """Verify new line not removed by templating engine after folder generation."""
53
    generate.generate_files(
54
        context={'cookiecutter': {'food': 'pizzä'}},
55
        repo_dir='tests/test-generate-files',
56
        output_dir=tmp_path,
57
    )
58
59
    newline_file = Path(tmp_path, 'inputpizzä/simple-with-newline.txt')
60
    assert newline_file.is_file()
61
    assert newline_file.exists()
62
63
    with Path(newline_file).open(encoding='utf-8', newline='') as f:
64
        simple_text = f.readline()
65
    assert simple_text == 'newline is LF\n'
66
    assert f.newlines == '\n'
67
68
69
def test_generate_files_with_jinja2_environment(tmp_path):
70
    """Extend StrictEnvironment with _jinja2_env_vars cookiecutter template option."""
71
    generate.generate_files(
72
        context={
73
            'cookiecutter': {
74
                'food': 'pizzä',
75
                '_jinja2_env_vars': {'lstrip_blocks': True, 'trim_blocks': True},
76
            }
77
        },
78
        repo_dir='tests/test-generate-files',
79
        output_dir=tmp_path,
80
    )
81
82
    conditions_file = tmp_path.joinpath('inputpizzä/simple-with-conditions.txt')
83
    assert conditions_file.is_file()
84
    assert conditions_file.exists()
85
86
    simple_text = conditions_file.read_text(encoding='utf-8')
87
    assert simple_text == 'I eat pizzä\n'
88
89
90 View Code Duplication
def test_generate_files_with_trailing_newline_forced_to_linux_by_context(tmp_path):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
91
    """Verify new line not removed by templating engine after folder generation."""
92
    generate.generate_files(
93
        context={'cookiecutter': {'food': 'pizzä', '_new_lines': '\r\n'}},
94
        repo_dir='tests/test-generate-files',
95
        output_dir=tmp_path,
96
    )
97
98
    # assert 'Overwritting endline character with %s' in caplog.messages
99
    newline_file = Path(tmp_path, 'inputpizzä/simple-with-newline.txt')
100
    assert newline_file.is_file()
101
    assert newline_file.exists()
102
103
    with Path(newline_file).open(encoding='utf-8', newline='') as f:
104
        simple_text = f.readline()
105
    assert simple_text == 'newline is LF\r\n'
106
    assert f.newlines == '\r\n'
107
108
109 View Code Duplication
def test_generate_files_with_windows_newline(tmp_path):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
110
    """Verify windows source line end not changed during files generation."""
111
    generate.generate_files(
112
        context={'cookiecutter': {'food': 'pizzä'}},
113
        repo_dir='tests/test-generate-files',
114
        output_dir=tmp_path,
115
    )
116
117
    newline_file = Path(tmp_path, 'inputpizzä/simple-with-newline-crlf.txt')
118
    assert newline_file.is_file()
119
    assert newline_file.exists()
120
121
    with Path(newline_file).open(encoding='utf-8', newline='') as f:
122
        simple_text = f.readline()
123
    assert simple_text == 'newline is CRLF\r\n'
124
    assert f.newlines == '\r\n'
125
126
127 View Code Duplication
def test_generate_files_with_windows_newline_forced_to_linux_by_context(tmp_path):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
128
    """Verify windows line end changed to linux during files generation."""
129
    generate.generate_files(
130
        context={'cookiecutter': {'food': 'pizzä', '_new_lines': '\n'}},
131
        repo_dir='tests/test-generate-files',
132
        output_dir=tmp_path,
133
    )
134
135
    newline_file = Path(tmp_path, 'inputpizzä/simple-with-newline-crlf.txt')
136
    assert newline_file.is_file()
137
    assert newline_file.exists()
138
139
    with Path(newline_file).open(encoding='utf-8', newline='') as f:
140
        simple_text = f.readline()
141
142
    assert simple_text == 'newline is CRLF\n'
143
    assert f.newlines == '\n'
144
145
146
def test_generate_files_binaries(tmp_path):
147
    """Verify binary files created during directory generation."""
148
    generate.generate_files(
149
        context={'cookiecutter': {'binary_test': 'binary_files'}},
150
        repo_dir='tests/test-generate-binaries',
151
        output_dir=tmp_path,
152
    )
153
154
    dst_dir = Path(tmp_path, 'inputbinary_files')
155
156
    assert is_binary(str(Path(dst_dir, 'logo.png')))
157
    assert is_binary(str(Path(dst_dir, '.DS_Store')))
158
    assert not is_binary(str(Path(dst_dir, 'readme.txt')))
159
    assert is_binary(str(Path(dst_dir, 'some_font.otf')))
160
    assert is_binary(str(Path(dst_dir, 'binary_files/logo.png')))
161
    assert is_binary(str(Path(dst_dir, 'binary_files/.DS_Store')))
162
    assert not is_binary(str(Path(dst_dir, 'binary_files/readme.txt')))
163
    assert is_binary(str(Path(dst_dir, 'binary_files/some_font.otf')))
164
    assert is_binary(str(Path(dst_dir, 'binary_files/binary_files/logo.png')))
165
166
167
def test_generate_files_absolute_path(tmp_path):
168
    """Verify usage of absolute path does not change files generation behaviour."""
169
    generate.generate_files(
170
        context={'cookiecutter': {'food': 'pizzä'}},
171
        repo_dir=Path('tests/test-generate-files').absolute(),
172
        output_dir=tmp_path,
173
    )
174
    assert Path(tmp_path, 'inputpizzä/simple.txt').is_file()
175
176
177
def test_generate_files_output_dir(tmp_path):
178
    """Verify `output_dir` option for `generate_files` changing location correctly."""
179
    output_dir = Path(tmp_path, 'custom_output_dir')
180
    output_dir.mkdir()
181
182
    project_dir = generate.generate_files(
183
        context={'cookiecutter': {'food': 'pizzä'}},
184
        repo_dir=Path('tests/test-generate-files').absolute(),
185
        output_dir=output_dir,
186
    )
187
188
    assert Path(output_dir, 'inputpizzä/simple.txt').exists()
189
    assert Path(output_dir, 'inputpizzä/simple.txt').is_file()
190
    assert Path(project_dir) == Path(tmp_path, 'custom_output_dir/inputpizzä')
191
192
193
def test_generate_files_permissions(tmp_path):
194
    """Verify generates files respect source files permissions.
195
196
    simple.txt and script.sh should retain their respective 0o644 and 0o755
197
    permissions.
198
    """
199
    generate.generate_files(
200
        context={'cookiecutter': {'permissions': 'permissions'}},
201
        repo_dir='tests/test-generate-files-permissions',
202
        output_dir=tmp_path,
203
    )
204
205
    assert Path(tmp_path, 'inputpermissions/simple.txt').is_file()
206
207
    # Verify source simple.txt should still be 0o644
208
    tests_simple_file = Path(
209
        'tests',
210
        'test-generate-files-permissions',
211
        'input{{cookiecutter.permissions}}',
212
        'simple.txt',
213
    )
214
    tests_simple_file_mode = tests_simple_file.stat().st_mode
215
216
    input_simple_file = Path(tmp_path, 'inputpermissions', 'simple.txt')
217
    input_simple_file_mode = input_simple_file.stat().st_mode
218
    assert tests_simple_file_mode == input_simple_file_mode
219
220
    assert Path(tmp_path, 'inputpermissions/script.sh').exists()
221
    assert Path(tmp_path, 'inputpermissions/script.sh').is_file()
222
223
    # Verify source script.sh should still be 0o755
224
    tests_script_file = Path(
225
        'tests',
226
        'test-generate-files-permissions',
227
        'input{{cookiecutter.permissions}}',
228
        'script.sh',
229
    )
230
    tests_script_file_mode = tests_script_file.stat().st_mode
231
232
    input_script_file = Path(tmp_path, 'inputpermissions', 'script.sh')
233
    input_script_file_mode = input_script_file.stat().st_mode
234
    assert tests_script_file_mode == input_script_file_mode
235
236
237 View Code Duplication
def test_generate_files_with_overwrite_if_exists_with_skip_if_file_exists(tmp_path):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
238
    """Verify `skip_if_file_exist` has priority over `overwrite_if_exists`."""
239
    simple_file = Path(tmp_path, 'inputpizzä/simple.txt')
240
    simple_with_new_line_file = Path(tmp_path, 'inputpizzä/simple-with-newline.txt')
241
242
    Path(tmp_path, 'inputpizzä').mkdir(parents=True)
243
    with Path(simple_file).open('w') as f:
244
        f.write('temp')
245
246
    generate.generate_files(
247
        context={'cookiecutter': {'food': 'pizzä'}},
248
        repo_dir='tests/test-generate-files',
249
        overwrite_if_exists=True,
250
        skip_if_file_exists=True,
251
        output_dir=tmp_path,
252
    )
253
254
    assert Path(simple_file).is_file()
255
    assert Path(simple_file).exists()
256
    assert Path(simple_with_new_line_file).is_file()
257
    assert Path(simple_with_new_line_file).exists()
258
259
    simple_text = Path(simple_file).read_text(encoding='utf-8')
260
    assert simple_text == 'temp'
261
262
263 View Code Duplication
def test_generate_files_with_skip_if_file_exists(tmp_path):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
264
    """Verify existed files not removed if error raised with `skip_if_file_exists`."""
265
    simple_file = Path(tmp_path, 'inputpizzä/simple.txt')
266
    simple_with_new_line_file = Path(tmp_path, 'inputpizzä/simple-with-newline.txt')
267
268
    Path(tmp_path, 'inputpizzä').mkdir(parents=True)
269
    Path(simple_file).write_text('temp')
270
271
    with pytest.raises(exceptions.OutputDirExistsException):
272
        generate.generate_files(
273
            context={'cookiecutter': {'food': 'pizzä'}},
274
            repo_dir='tests/test-generate-files',
275
            skip_if_file_exists=True,
276
            output_dir=tmp_path,
277
        )
278
279
    assert Path(simple_file).is_file()
280
    assert not Path(simple_with_new_line_file).is_file()
281
    assert not Path(simple_with_new_line_file).exists()
282
283
    simple_text = Path(simple_file).read_text(encoding='utf-8')
284
    assert simple_text == 'temp'
285
286
287 View Code Duplication
def test_generate_files_with_overwrite_if_exists(tmp_path):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
288
    """Verify overwrite_if_exists overwrites old files."""
289
    simple_file = Path(tmp_path, 'inputpizzä/simple.txt')
290
    simple_with_new_line_file = Path(tmp_path, 'inputpizzä/simple-with-newline.txt')
291
292
    Path(tmp_path, 'inputpizzä').mkdir(parents=True)
293
    Path(simple_file).write_text('temp')
294
295
    generate.generate_files(
296
        context={'cookiecutter': {'food': 'pizzä'}},
297
        repo_dir='tests/test-generate-files',
298
        overwrite_if_exists=True,
299
        output_dir=tmp_path,
300
    )
301
302
    assert Path(simple_file).is_file()
303
    assert Path(simple_file).exists()
304
    assert Path(simple_with_new_line_file).is_file()
305
    assert Path(simple_with_new_line_file).exists()
306
307
    simple_text = Path(simple_file).read_text(encoding='utf-8')
308
    assert simple_text == 'I eat pizzä'
309
310
311
@pytest.fixture
312
def undefined_context():
313
    """Fixture. Populate context variable for future tests."""
314
    return {
315
        'cookiecutter': {'project_slug': 'testproject', 'github_username': 'hackebrot'}
316
    }
317
318
319
def test_raise_undefined_variable_file_name(output_dir, undefined_context):
320
    """Verify correct error raised when file name cannot be rendered."""
321
    with pytest.raises(exceptions.UndefinedVariableInTemplate) as err:
322
        generate.generate_files(
323
            repo_dir='tests/undefined-variable/file-name/',
324
            output_dir=output_dir,
325
            context=undefined_context,
326
        )
327
    error = err.value
328
    assert "Unable to create file '{{cookiecutter.foobar}}'" == error.message
329
    assert error.context == undefined_context
330
331
    assert not Path(output_dir).joinpath('testproject').exists()
332
333
334 View Code Duplication
def test_raise_undefined_variable_file_name_existing_project(
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
335
    output_dir, undefined_context
336
):
337
    """Verify correct error raised when file name cannot be rendered."""
338
    testproj_path = Path(output_dir, 'testproject')
339
    testproj_path.mkdir()
340
341
    with pytest.raises(exceptions.UndefinedVariableInTemplate) as err:
342
        generate.generate_files(
343
            repo_dir='tests/undefined-variable/file-name/',
344
            output_dir=output_dir,
345
            context=undefined_context,
346
            overwrite_if_exists=True,
347
        )
348
    error = err.value
349
    assert "Unable to create file '{{cookiecutter.foobar}}'" == error.message
350
    assert error.context == undefined_context
351
352
    assert testproj_path.exists()
353
354
355
def test_raise_undefined_variable_file_content(output_dir, undefined_context):
356
    """Verify correct error raised when file content cannot be rendered."""
357
    with pytest.raises(exceptions.UndefinedVariableInTemplate) as err:
358
        generate.generate_files(
359
            repo_dir='tests/undefined-variable/file-content/',
360
            output_dir=output_dir,
361
            context=undefined_context,
362
        )
363
    error = err.value
364
    assert "Unable to create file 'README.rst'" == error.message
365
    assert error.context == undefined_context
366
367
    assert not Path(output_dir).joinpath('testproject').exists()
368
369
370
def test_raise_undefined_variable_dir_name(output_dir, undefined_context):
371
    """Verify correct error raised when directory name cannot be rendered."""
372
    with pytest.raises(exceptions.UndefinedVariableInTemplate) as err:
373
        generate.generate_files(
374
            repo_dir='tests/undefined-variable/dir-name/',
375
            output_dir=output_dir,
376
            context=undefined_context,
377
        )
378
    error = err.value
379
380
    directory = Path('testproject', '{{cookiecutter.foobar}}')
381
    msg = f"Unable to create directory '{directory}'"
382
    assert msg == error.message
383
384
    assert error.context == undefined_context
385
386
    assert not Path(output_dir).joinpath('testproject').exists()
387
388
389
def test_keep_project_dir_on_failure(output_dir, undefined_context):
390
    """Verify correct error raised when directory name cannot be rendered."""
391
    with pytest.raises(exceptions.UndefinedVariableInTemplate):
392
        generate.generate_files(
393
            repo_dir='tests/undefined-variable/dir-name/',
394
            output_dir=output_dir,
395
            context=undefined_context,
396
            keep_project_on_failure=True,
397
        )
398
    assert Path(output_dir).joinpath('testproject').exists()
399
400
401 View Code Duplication
def test_raise_undefined_variable_dir_name_existing_project(
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
402
    output_dir, undefined_context
403
):
404
    """Verify correct error raised when directory name cannot be rendered."""
405
    testproj_path = Path(output_dir, 'testproject')
406
    testproj_path.mkdir()
407
408
    with pytest.raises(exceptions.UndefinedVariableInTemplate) as err:
409
        generate.generate_files(
410
            repo_dir='tests/undefined-variable/dir-name/',
411
            output_dir=output_dir,
412
            context=undefined_context,
413
            overwrite_if_exists=True,
414
        )
415
    error = err.value
416
417
    directory = Path('testproject', '{{cookiecutter.foobar}}')
418
    msg = f"Unable to create directory '{directory}'"
419
    assert msg == error.message
420
421
    assert error.context == undefined_context
422
423
    assert testproj_path.exists()
424
425
426
def test_raise_undefined_variable_project_dir(tmp_path):
427
    """Verify correct error raised when directory name cannot be rendered."""
428
    with pytest.raises(exceptions.UndefinedVariableInTemplate) as err:
429
        generate.generate_files(
430
            repo_dir='tests/undefined-variable/dir-name/',
431
            output_dir=tmp_path,
432
            context={},
433
        )
434
    error = err.value
435
    msg = "Unable to create project directory '{{cookiecutter.project_slug}}'"
436
    assert msg == error.message
437
    assert error.context == {}
438
439
    assert not Path(tmp_path, 'testproject').exists()
440