Files
cookiecutter-data-science/tests/test_creation.py
T
2021-04-07 14:38:42 -07:00

164 lines
4.8 KiB
Python

from pathlib import Path
from subprocess import run, PIPE
import pytest
import chardet
from conftest import bake_project, config_generator
def no_curlies(filepath):
""" Utility to make sure no curly braces appear in a file.
That is, was Jinja able to render everything?
"""
data = filepath.open('r').read()
template_strings = [
'{{',
'}}',
'{%',
'%}'
]
template_strings_in_file = [s in data for s in template_strings]
return not any(template_strings_in_file)
@pytest.mark.parametrize("config", config_generator())
def test_baking_configs(config):
""" For every generated config in the config_generator, run all
of the tests.
"""
print("using config", config)
with bake_project(config) as project_directory:
verify_folders(project_directory, config)
verify_files(project_directory, config)
verify_makefile_commands(project_directory, config)
def verify_folders(root, config):
''' Tests that expected folders and only expected folders exist.
'''
expected_dirs = [
'.',
'data',
'data/external',
'data/interim',
'data/processed',
'data/raw',
'docs',
'models',
'notebooks',
'references',
'reports',
'reports/figures',
config['module_name'],
f"{config['module_name']}/data",
f"{config['module_name']}/features",
f"{config['module_name']}/models",
f"{config['module_name']}/visualization",
]
expected_dirs = [
# (root / d).resolve().relative_to(root) for d in expected_dirs
Path(d) for d in expected_dirs
]
existing_dirs = [
d.resolve().relative_to(root) for d in root.glob('**') if d.is_dir()
]
assert sorted(existing_dirs) == sorted(expected_dirs)
def verify_files(root, config):
''' Test that expected files and only expected files exist.
'''
expected_files = [
'Makefile',
'README.md',
'setup.py',
".env",
".gitignore",
"data/external/.gitkeep",
"data/interim/.gitkeep",
"data/processed/.gitkeep",
"data/raw/.gitkeep",
"docs/Makefile",
"docs/commands.rst",
"docs/conf.py",
"docs/getting-started.rst",
"docs/index.rst",
"docs/make.bat",
"ethics.md",
"notebooks/.gitkeep",
"notebooks/.nbautoexport",
"references/.gitkeep",
"reports/.gitkeep",
"reports/figures/.gitkeep",
"models/.gitkeep",
f"{config['module_name']}/__init__.py",
f"{config['module_name']}/data/__init__.py",
f"{config['module_name']}/data/make_dataset.py",
f"{config['module_name']}/features/__init__.py",
f"{config['module_name']}/features/build_features.py",
f"{config['module_name']}/models/__init__.py",
f"{config['module_name']}/models/train_model.py",
f"{config['module_name']}/models/predict_model.py",
f"{config['module_name']}/visualization/__init__.py",
f"{config['module_name']}/visualization/visualize.py",
]
# conditional files
if not config["open_source_license"].startswith("No license"):
expected_files.append('LICENSE')
expected_files.append(config["dependency_file"])
expected_files = [
Path(f) for f in expected_files
]
existing_files = [
f.relative_to(root) for f in root.glob('**/*') if f.is_file()
]
assert sorted(existing_files) == sorted(expected_files)
for f in existing_files:
assert no_curlies(root / f)
def verify_makefile_commands(root, config):
""" Actually shell out to bash and run the make commands for:
- create_environment
- requirements
Ensure that these use the proper environment.
"""
test_path = Path(__file__).parent
if config["environment_manager"] == 'conda':
harness_path = test_path / "conda_harness.sh"
elif config["environment_manager"] == 'virtualenv':
harness_path = test_path / "virtualenv_harness.sh"
elif config["environment_manager"] == 'pipenv':
harness_path = test_path / "pipenv_harness.sh"
elif config["environment_manager"] == 'none':
return True
else:
raise ValueError(f"Environment manager '{config['environment_manager']}' not found in test harnesses.")
result = run(["bash", str(harness_path), str(root.resolve())], stderr=PIPE, stdout=PIPE)
result_returncode = result.returncode
encoding = chardet.detect(result.stdout)["encoding"]
if encoding is None:
encoding = "utf-8"
# normally hidden by pytest except in failure we want this displayed
print("\n======================= STDOUT ======================")
print("\n======================= STDERR ======================")
assert result_returncode == 0