Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 9 additions & 27 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,34 +6,16 @@

import pytest


def _generate_package(
config: dict[str, str], path: pathlib.Path
) -> subprocess.CompletedProcess[str]:
"""
Generate a project from the cookiecutter template.
Arguments:
---------
config: dict
A dictionary with values for the cookiecutter template,
as defined in the cookiecutter.json
path: Path
Directory to create package in.
"""
args = [f"{key}={val}" for key, val in config.items()]
cmd = ["cookiecutter", ".", "--no-input", "--output-dir", f"{path}"]
return subprocess.run( # noqa: S603
cmd + args,
check=False,
shell=False,
capture_output=True,
text=True,
)
from .helpers import DEFAULT_CONFIG, _generate_package # type: ignore[import-not-found]


@pytest.fixture
def generate_package() -> typing.Callable:
def generate_package(tmp_path: pathlib.Path) -> typing.Callable:
"""Generate project from cookiecutter template."""
return _generate_package

def wrapped_with_tmp_path(
config: dict[str, str] = DEFAULT_CONFIG,
) -> tuple[subprocess.CompletedProcess, pathlib.Path]:
return _generate_package(config, tmp_path)

return wrapped_with_tmp_path
67 changes: 67 additions & 0 deletions tests/helpers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
"""Helper functions for the cookiecutter template tests."""

import os
import pathlib
import subprocess

DEFAULT_CONFIG = {
"github_owner": "test-user",
"project_short_description": "description",
"project_name": "Cookiecutter Test",
"project_slug": "cookiecutter-test",
}


def _generate_package(
config: dict[str, str], path: pathlib.Path
) -> tuple[subprocess.CompletedProcess[str], pathlib.Path]:
"""
Generate a project from the cookiecutter template.
Arguments:
---------
config: dict
A dictionary with values for the cookiecutter template,
as defined in the cookiecutter.json
path: Path
Directory to create package in.
Returns:
-------
subprocess.CompletedProcess, pathlib.Path
The result of the cookiecutter command and the path to the generated package.
"""
args = [f"{key}={val}" for key, val in config.items()]
cmd = ["cookiecutter", ".", "--no-input", "--output-dir", f"{path}"]
return subprocess.run( # noqa: S603
cmd + args,
check=False,
shell=False,
capture_output=True,
text=True,
), path / config["project_slug"]


def get_all_files_folders(root_path: pathlib.Path) -> set[pathlib.Path]:
"""
Get all files and folders under a directory.
The paths are returned relative to the root path given.
__pycache__ directories and .DS_Store files are ignored.
"""
file_set: set[pathlib.Path] = set()
for dirpath, _, filenames in os.walk(root_path):
dirpath_path = pathlib.Path(dirpath).relative_to(root_path)
if dirpath_path.name in ["__pycache__"]:
continue

# Add this directory
file_set.update((dirpath_path,))
# Add any files in it
for filename in filenames:
if filename in [".DS_Store"]:
continue
file_set.update((dirpath_path / filename,))

return file_set
16 changes: 5 additions & 11 deletions tests/test_git_init.py
Original file line number Diff line number Diff line change
@@ -1,29 +1,23 @@
"""Checks that the git repo initialisation works."""

import pathlib
import subprocess
import typing

import pytest

from .helpers import DEFAULT_CONFIG # type: ignore[import-not-found]


@pytest.mark.parametrize("initialise_git_repository", [True, False])
def test_initialisation_of_git_repo(
initialise_git_repository: bool, # noqa: FBT001
generate_package: typing.Callable,
tmp_path: pathlib.Path,
) -> None:
"""Checks to see if git was correctly initialised if desired."""
test_config = {
"github_owner": "test-user",
"project_short_description": "description",
"project_name": "Cookiecutter Test",
"initialise_git_repository": initialise_git_repository,
}
test_config = DEFAULT_CONFIG.copy()
test_config["initialise_git_repository"] = str(initialise_git_repository)
# Run cookiecutter with initialise_git_repository
result = generate_package(config=test_config, path=tmp_path)

test_project_dir = tmp_path / "cookiecutter-test"
result, test_project_dir = generate_package(config=test_config)

# check if git is initialised
git_status = subprocess.run( # noqa: S603
Expand Down
87 changes: 18 additions & 69 deletions tests/test_package_generation.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
"""Checks that the cookiecutter works."""

import difflib
import os
import pathlib
import shutil
import subprocess
Expand All @@ -10,52 +9,24 @@
import pytest
import pytest_venv # type: ignore[import-not-found]

from .helpers import ( # type: ignore[import-not-found]
DEFAULT_CONFIG,
get_all_files_folders,
)

def get_all_files_folders(root_path: pathlib.Path) -> set[pathlib.Path]:
"""
Get all files and folders under a directory.

The paths are returned relative to the root path given.
__pycache__ directories and .DS_Store files are ignored.
"""
file_set: set[pathlib.Path] = set()
for dirpath, _, filenames in os.walk(root_path):
dirpath_path = pathlib.Path(dirpath).relative_to(root_path)
if dirpath_path.name in ["__pycache__"]:
continue

# Add this directory
file_set.update((dirpath_path,))
# Add any files in it
for filename in filenames:
if filename in [".DS_Store"]:
continue
file_set.update((dirpath_path / filename,))

return file_set


def test_package_generation(
tmp_path: pathlib.Path,
generate_package: typing.Callable,
) -> None:
def test_package_generation(generate_package: typing.Callable) -> None:
"""Test package generation."""
test_config = {
"github_owner": "test-user",
"project_short_description": "description",
"project_name": "Cookiecutter Test",
# Not having a git repo makes it easier to check in/out reference
# data files to the main python-tooling git repository
"initialise_git_repository": False,
}
generate_package(config=test_config, path=tmp_path)
test_config = DEFAULT_CONFIG.copy()
# Not having a git repo makes it easier to check in/out reference
# data files to the main python-tooling git repository
test_config["initialise_git_repository"] = "False"
_, test_project_dir = generate_package(config=test_config)

expected_package_dir = (
pathlib.Path(__file__).parent / "data" / "test_package_generation"
)
# Check project directory exists
test_project_dir = tmp_path / "cookiecutter-test"
assert test_project_dir.exists()
assert test_project_dir.exists(), "Project directory does not exist."

actual_files = get_all_files_folders(test_project_dir)
expected_files = get_all_files_folders(expected_package_dir)
Expand Down Expand Up @@ -94,18 +65,11 @@ def test_package_generation(


def test_pip_installable(
tmp_path: pathlib.Path,
venv: pytest_venv.VirtualEnvironment,
generate_package: typing.Callable,
) -> None:
"""Test generated package is pip installable."""
test_config = {
"github_owner": "test-user",
"project_short_description": "description",
"project_name": "Cookiecutter Test",
}
generate_package(config=test_config, path=tmp_path)
test_project_dir = tmp_path / "cookiecutter-test"
_, test_project_dir = generate_package()
# Try to install package in virtual environment with pip
pipinstall = subprocess.run( # noqa: S603
[
Expand All @@ -124,21 +88,13 @@ def test_pip_installable(
)


@pytest.mark.parametrize("funder", ["", "STFC"])
def test_optional_funder(
tmp_path: pathlib.Path, generate_package: typing.Callable, funder: str
) -> None:
@pytest.mark.parametrize("funder", ["", "STFC", "UKRI", "Wellcome Trust"])
def test_optional_funder(generate_package: typing.Callable, funder: str) -> None:
"""Test specifying funder or not in package generation."""
config = {
"github_owner": "test-user",
"project_short_description": "description",
"project_name": "Cookiecutter Test",
"funder": funder,
}

generate_package(config, tmp_path)
config = DEFAULT_CONFIG.copy()
config["funder"] = funder
_, test_project_dir = generate_package(config)

test_project_dir = tmp_path / "cookiecutter-test"
with (test_project_dir / "README.md").open() as f:
readme_text = "".join(f.readlines())

Expand All @@ -152,18 +108,11 @@ def test_optional_funder(


def test_docs_build(
tmp_path: pathlib.Path,
venv: pytest_venv.VirtualEnvironment,
generate_package: typing.Callable,
) -> None:
"""Test documentation build from package created from template."""
config = {
"github_owner": "test-user",
"project_short_description": "description",
"project_name": "Cookiecutter Test",
}
generate_package(config, tmp_path)
test_project_dir = tmp_path / "cookiecutter-test"
_, test_project_dir = generate_package()
venv.install("tox")
tox_docs_process = subprocess.run( # noqa: S603
[
Expand Down
Loading