Passed
Push — master ( 90434f...947a7f )
by Andrey
01:04
created

test_ignore_shell_hooks()   A

Complexity

Conditions 1

Size

Total Lines 15
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 12
dl 0
loc 15
rs 9.8
c 0
b 0
f 0
cc 1
nop 1
1
"""Test work of python and shell hooks for generated projects."""
2
import errno
3
import os
4
import sys
5
6
import pytest
7
8
from cookiecutter import generate, utils
9
from cookiecutter.exceptions import FailedHookException
10
11
WINDOWS = sys.platform.startswith('win')
12
13
14
@pytest.fixture(scope='function')
15
def remove_additional_folders(tmpdir):
16
    """Remove some special folders which are created by the tests."""
17
    yield
18
    directories_to_delete = [
19
        'tests/test-pyhooks/inputpyhooks',
20
        'inputpyhooks',
21
        'inputhooks',
22
        os.path.join(str(tmpdir), 'test-shellhooks'),
23
        'tests/test-hooks',
24
    ]
25
    for directory in directories_to_delete:
26
        if os.path.exists(directory):
27
            utils.rmtree(directory)
28
29
30
@pytest.mark.usefixtures('clean_system', 'remove_additional_folders')
31
def test_ignore_hooks_dirs():
32
    """Verify hooks directory not created in target location on files generation."""
33
    generate.generate_files(
34
        context={'cookiecutter': {'pyhooks': 'pyhooks'}},
35
        repo_dir='tests/test-pyhooks/',
36
        output_dir='tests/test-pyhooks/',
37
    )
38
    assert not os.path.exists('tests/test-pyhooks/inputpyhooks/hooks')
39
40
41
@pytest.mark.usefixtures('clean_system', 'remove_additional_folders')
42
def test_run_python_hooks():
43
    """Verify pre and post generation python hooks executed and result in output_dir.
44
45
    Each hook should create in target directory. Test verifies that these files
46
    created.
47
    """
48
    generate.generate_files(
49
        context={'cookiecutter': {'pyhooks': 'pyhooks'}},
50
        repo_dir='tests/test-pyhooks/',
51
        output_dir='tests/test-pyhooks/',
52
    )
53
    assert os.path.exists('tests/test-pyhooks/inputpyhooks/python_pre.txt')
54
    assert os.path.exists('tests/test-pyhooks/inputpyhooks/python_post.txt')
55
56
57
@pytest.mark.usefixtures('clean_system', 'remove_additional_folders')
58
def test_run_python_hooks_cwd():
59
    """Verify pre and post generation python hooks executed and result in current dir.
60
61
    Each hook should create in target directory. Test verifies that these files
62
    created.
63
    """
64
    generate.generate_files(
65
        context={'cookiecutter': {'pyhooks': 'pyhooks'}}, repo_dir='tests/test-pyhooks/'
66
    )
67
    assert os.path.exists('inputpyhooks/python_pre.txt')
68
    assert os.path.exists('inputpyhooks/python_post.txt')
69
70
71
@pytest.mark.skipif(WINDOWS, reason='OSError.errno=8 is not thrown on Windows')
72
@pytest.mark.usefixtures('clean_system', 'remove_additional_folders')
73
def test_empty_hooks():
74
    """Verify error is raised on empty hook script. Ignored on windows.
75
76
    OSError.errno=8 is not thrown on Windows when the script is empty
77
    because it always runs through shell instead of needing a shebang.
78
    """
79
    with pytest.raises(FailedHookException) as excinfo:
80
        generate.generate_files(
81
            context={'cookiecutter': {'shellhooks': 'shellhooks'}},
82
            repo_dir='tests/test-shellhooks-empty/',
83
            overwrite_if_exists=True,
84
        )
85
    assert 'shebang' in str(excinfo.value)
86
87
88
@pytest.mark.usefixtures('clean_system', 'remove_additional_folders')
89
def test_oserror_hooks(mocker):
90
    """Verify script error passed correctly to cookiecutter error.
91
92
    Here subprocess.Popen function mocked, ie we do not call hook script,
93
    just produce expected error.
94
    """
95
    message = 'Out of memory'
96
97
    err = OSError(message)
98
    err.errno = errno.ENOMEM
99
100
    prompt = mocker.patch('subprocess.Popen')
101
    prompt.side_effect = err
102
103
    with pytest.raises(FailedHookException) as excinfo:
104
        generate.generate_files(
105
            context={'cookiecutter': {'shellhooks': 'shellhooks'}},
106
            repo_dir='tests/test-shellhooks-empty/',
107
            overwrite_if_exists=True,
108
        )
109
    assert message in str(excinfo.value)
110
111
112 View Code Duplication
@pytest.mark.usefixtures('clean_system', 'remove_additional_folders')
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
113
def test_run_failing_hook_removes_output_directory():
114
    """Verify project directory not created or removed if hook failed."""
115
    repo_path = os.path.abspath('tests/test-hooks/')
116
    hooks_path = os.path.abspath('tests/test-hooks/hooks')
117
118
    hook_dir = os.path.join(repo_path, 'hooks')
119
    template = os.path.join(repo_path, 'input{{cookiecutter.hooks}}')
120
    os.mkdir(repo_path)
121
    os.mkdir(hook_dir)
122
    os.mkdir(template)
123
124
    hook_path = os.path.join(hooks_path, 'pre_gen_project.py')
125
126
    with open(hook_path, 'w') as f:
127
        f.write("#!/usr/bin/env python\n")
128
        f.write("import sys; sys.exit(1)\n")
129
130
    with pytest.raises(FailedHookException) as excinfo:
131
        generate.generate_files(
132
            context={'cookiecutter': {'hooks': 'hooks'}},
133
            repo_dir='tests/test-hooks/',
134
            overwrite_if_exists=True,
135
        )
136
137
    assert 'Hook script failed' in str(excinfo.value)
138
    assert not os.path.exists('inputhooks')
139
140
141 View Code Duplication
@pytest.mark.usefixtures('clean_system', 'remove_additional_folders')
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
142
def test_run_failing_hook_preserves_existing_output_directory():
143
    """Verify project directory not removed if exist before hook failed."""
144
    repo_path = os.path.abspath('tests/test-hooks/')
145
    hooks_path = os.path.abspath('tests/test-hooks/hooks')
146
147
    hook_dir = os.path.join(repo_path, 'hooks')
148
    template = os.path.join(repo_path, 'input{{cookiecutter.hooks}}')
149
    os.mkdir(repo_path)
150
    os.mkdir(hook_dir)
151
    os.mkdir(template)
152
153
    hook_path = os.path.join(hooks_path, 'pre_gen_project.py')
154
155
    with open(hook_path, 'w') as f:
156
        f.write("#!/usr/bin/env python\n")
157
        f.write("import sys; sys.exit(1)\n")
158
159
    os.mkdir('inputhooks')
160
    with pytest.raises(FailedHookException) as excinfo:
161
        generate.generate_files(
162
            context={'cookiecutter': {'hooks': 'hooks'}},
163
            repo_dir='tests/test-hooks/',
164
            overwrite_if_exists=True,
165
        )
166
167
    assert 'Hook script failed' in str(excinfo.value)
168
    assert os.path.exists('inputhooks')
169
170
171 View Code Duplication
@pytest.mark.skipif(sys.platform.startswith('win'), reason="Linux only test")
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
172
@pytest.mark.usefixtures('clean_system', 'remove_additional_folders')
173
def test_run_shell_hooks(tmpdir):
174
    """Verify pre and post generate project shell hooks executed.
175
176
    This test for .sh files.
177
    """
178
    generate.generate_files(
179
        context={'cookiecutter': {'shellhooks': 'shellhooks'}},
180
        repo_dir='tests/test-shellhooks/',
181
        output_dir=os.path.join(str(tmpdir), 'test-shellhooks'),
182
    )
183
    shell_pre_file = os.path.join(
184
        str(tmpdir), 'test-shellhooks', 'inputshellhooks', 'shell_pre.txt'
185
    )
186
    shell_post_file = os.path.join(
187
        str(tmpdir), 'test-shellhooks', 'inputshellhooks', 'shell_post.txt'
188
    )
189
    assert os.path.exists(shell_pre_file)
190
    assert os.path.exists(shell_post_file)
191
192
193 View Code Duplication
@pytest.mark.skipif(not sys.platform.startswith('win'), reason="Win only test")
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
194
@pytest.mark.usefixtures('clean_system', 'remove_additional_folders')
195
def test_run_shell_hooks_win(tmpdir):
196
    """Verify pre and post generate project shell hooks executed.
197
198
    This test for .bat files.
199
    """
200
    generate.generate_files(
201
        context={'cookiecutter': {'shellhooks': 'shellhooks'}},
202
        repo_dir='tests/test-shellhooks-win/',
203
        output_dir=os.path.join(str(tmpdir), 'test-shellhooks-win'),
204
    )
205
    shell_pre_file = os.path.join(
206
        str(tmpdir), 'test-shellhooks-win', 'inputshellhooks', 'shell_pre.txt'
207
    )
208
    shell_post_file = os.path.join(
209
        str(tmpdir), 'test-shellhooks-win', 'inputshellhooks', 'shell_post.txt'
210
    )
211
    assert os.path.exists(shell_pre_file)
212
    assert os.path.exists(shell_post_file)
213
214
215
@pytest.mark.usefixtures("clean_system", "remove_additional_folders")
216
def test_ignore_shell_hooks(tmp_path):
217
    """Verify *.txt files not created, when accept_hooks=False."""
218
    generate.generate_files(
219
        context={"cookiecutter": {"shellhooks": "shellhooks"}},
220
        repo_dir="tests/test-shellhooks/",
221
        output_dir=tmp_path.joinpath('test-shellhooks'),
222
        accept_hooks=False,
223
    )
224
    shell_pre_file = tmp_path.joinpath("test-shellhooks/inputshellhooks/shell_pre.txt")
225
    shell_post_file = tmp_path.joinpath(
226
        "test-shellhooks/inputshellhooks/shell_post.txt"
227
    )
228
    assert not shell_pre_file.exists()
229
    assert not shell_post_file.exists()
230