Skip to content

Commit

Permalink
Seperated nox sessions for templates and tests and, new testing infra…
Browse files Browse the repository at this point in the history
… for generated project
  • Loading branch information
santacodes committed Jul 22, 2024
1 parent b93d726 commit 7ad77d5
Show file tree
Hide file tree
Showing 11 changed files with 249 additions and 30 deletions.
46 changes: 41 additions & 5 deletions .github/workflows/test_on_push.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: Test template generation
name: Test template and generated project

on:
workflow_dispatch:
Expand All @@ -7,7 +7,6 @@ on:
branches:
- main


jobs:
style:
runs-on: ubuntu-latest
Expand All @@ -32,7 +31,7 @@ jobs:
os: [ubuntu-latest, macos-13, macos-14, windows-latest]
python-version: ["3.9", "3.10", "3.11", "3.12"]
name:
Template Tests (${{ matrix.os }} / Python ${{ matrix.python-version }})
Template Generation/Project Tests (${{ matrix.os }} / Python ${{ matrix.python-version }})
steps:
- name: Checkout pybamm-cookiecutter
uses: actions/checkout@v4
Expand All @@ -51,9 +50,13 @@ jobs:
- name: Install nox
run: uv pip install nox[uv]

- name: Test Template Generation
- name: Test template generation
run: |
nox -s template-tests
- name: Test project units
run: |
nox -s test-generation
nox -s project-tests
- name: Run coverage tests
if: matrix.os == 'ubuntu-latest' && matrix.python-version == '3.12'
Expand Down Expand Up @@ -87,3 +90,36 @@ jobs:

- name: Check if the documentation can be built
run: python -m nox -s docs

generated_project_tests:
needs: [style, template_test]
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-13, macos-14, windows-latest]
python-version: ["3.9", "3.10", "3.11", "3.12"]
name:
Generated Project Tests (${{ matrix.os }} / Python ${{ matrix.python-version }})
steps:
- name: Checkout pybamm-cookiecutter
uses: actions/checkout@v4

- name: Set up Python ${{ matrix.python-version }}
id: setup-python
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}

- name: Install cookiecutter and pipx
run: python -m pip install cookiecutter pipx

- name: Generate a project using cookiecutter
run: |
cookiecutter . --no-input
- name: Install nox and test generated project
working-directory: ./pybamm_example_project
run: |
pipx install nox
pipx run nox -s generated-project-tests
5 changes: 3 additions & 2 deletions cookiecutter.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"project_name": "pybamm-example-project",
"project_name": "pybamm_example_project",
"platform": [
"github",
"gitlab"
Expand All @@ -20,6 +20,7 @@
"mypy": false,
"__year": "{% now 'utc', '%Y' %}",
"__project_slug": "{{ cookiecutter.project_name | lower | replace('-', '_') | replace('.', '_') }}",
"_copy_without_render": ["*.yml"],
"__type": "{{ 'pure' }}",
"__answers": "",
"__ci": "{{ cookiecutter.platform }}",
Expand All @@ -31,7 +32,7 @@
"gitlab": "GitLab"
},
"org": "The name of your organisation (or username, if you are not part of an organisation)",
"url": "The URL to your repository",
"url": "The URL to your repository",
"full_name": "Your name",
"email": "Your email",
"project_short_description": "A short description of your project",
Expand Down
11 changes: 9 additions & 2 deletions noxfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,19 @@ def build_docs(session: nox.Session) -> None:
"build/html/",
)

@nox.session(name="test-generation")
@nox.session(name="template-tests")
def run_template_generation(session):
"""Run the tests for testing template generation"""
session.install("setuptools", silent=False)
session.install("-e", ".[dev]", silent=False)
session.run("pytest", "tests")
session.run("pytest", "tests/template_tests")

@nox.session(name="project-tests")
def run_project_tests(session):
"""Run the tests for testing template generation"""
session.install("setuptools", silent=False)
session.install("-e", ".[dev]", silent=False)
session.run("pytest", "tests/project_tests")

@nox.session(name="coverage")
def run_coverage(session):
Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ def test_bake_project(cookies: Cookies):
result = cookies.bake()
assert result.exit_code == 0, f"Exited with code {result.exit_code}, expected 0"
assert result.exception is None, result.exception
assert result.project_path.name == "pybamm-example-project"
assert result.project_path.name == "pybamm_example_project"
assert result.project_path.is_dir(), f"Project directory {result.project_path} not found"


Expand Down
92 changes: 92 additions & 0 deletions {{cookiecutter.project_name}}/.github/workflows/test_on_push.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
name: Project Tests

on:
workflow_dispatch:
pull_request:
push:
branches:
- main

jobs:
style:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: 3.12

- name: Check style
run: |
python -m pip install pre-commit
pre-commit run -a
test_project:
needs: style
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-13, macos-14, windows-latest]
python-version: ["3.9", "3.10", "3.11", "3.12"]
name:
Template Generation/Project Tests (${{ matrix.os }} / Python ${{ matrix.python-version }})
steps:
- name: Checkout pybamm-cookiecutter
uses: actions/checkout@v4

- name: Set up Python ${{ matrix.python-version }}
id: setup-python
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}

- name: Set up uv
uses: yezz123/setup-uv@v4
with:
uv-venv: ".venv"

- name: Install nox
run: uv pip install nox[uv]

- name: Test project units
run: |
nox -s generated-project-tests
- name: Test user tests
run: |
nox -s user-tests
- name: Run coverage tests
if: matrix.os == 'ubuntu-latest' && matrix.python-version == '3.12'
run: python -m nox -s coverage

- name: Upload coverage report
if: matrix.os == 'ubuntu-latest' && matrix.python-version == '3.12'
uses: codecov/codecov-action@v4.5.0
with:
token: ${{ secrets.CODECOV_TOKEN }}

run_doctests:
needs: style
runs-on: ubuntu-latest
name: Doctests (ubuntu-latest / Python 3.12)

steps:
- name: Check out pybamm-cookiecutter repository
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: 3.12
cache: 'pip'

- name: Install nox
run: python -m pip install nox

- name: Check if the documentation can be built
run: python -m nox -s docs
69 changes: 58 additions & 11 deletions {{cookiecutter.project_name}}/noxfile.py
Original file line number Diff line number Diff line change
@@ -1,20 +1,67 @@
import nox
from pathlib import Path
import os

# Options to modify nox behaviour
nox.options.default_venv_backend = "uv|virtualenv"
nox.options.reuse_existing_virtualenvs = True

VENV_DIR = Path("./venv").resolve()

@nox.session(name="docs")
def build_docs(session):
def build_docs(session: nox.Session) -> None:
"""Build the documentation and load it in a browser tab, rebuilding on changes."""
envbindir = session.bin
session.install("-e", ".[docs]")
with session.chdir("docs/"):
session.run(
"sphinx-autobuild",
"-j",
"auto",
"--open-browser",
"-qT",
".",
f"{envbindir}/../tmp/html",
)
# For local development
if session.interactive:
session.run(
"sphinx-autobuild",
"-j",
"auto",
"--open-browser",
"-qT",
".",
"build/html/",
)
# For CI testing if documentation builds
else:
session.run(
"sphinx-build",
"-b",
"html",
"-W",
"--keep-going",
".",
"build/html/",
)

@nox.session(name="generated-project-tests")
def run_generated_project_tests(session):
"""Run the tests for testing units inside generated project"""
session.install("setuptools", silent=False)
session.install("-e", ".[dev]", silent=False)
session.run("pytest", "tests/generated_project_tests")

@nox.session(name="user-tests")
def run_user_tests(session):
"""Run the tests for testing user written tests"""
session.install("setuptools", silent=False)
session.install("-e", ".[dev]", silent=False)
session.run("pytest", "tests/user_tests")

@nox.session(name="coverage")
def run_coverage(session):
"""Run the coverage tests and generate an XML report."""
session.install("setuptools", silent=False)
session.install("coverage", silent=False)
session.install("-e", ".[all,dev,jax]", silent=False)
session.run("pytest", "--cov=src/pybamm_cookiecutter", "--cov-report=xml", "tests/")

@nox.session(name="dev")
def set_dev(session):
"""Install pybamm-cookiecutter in editable mode"""
session.install("virtualenv")
session.run("virtualenv", os.fsdecode(VENV_DIR), silent=True)
python = os.fsdecode(VENV_DIR.joinpath("bin/python"))
session.run(python, "-m", "pip", "install", "-e", ".[dev]")
3 changes: 1 addition & 2 deletions {{cookiecutter.project_name}}/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -47,15 +47,14 @@ classifiers = [
{%- if cookiecutter.backend == "hatch" %}
dynamic = ["version"]
{%- endif %}
dependencies = ["pybamm", "cookiecutter"]
dependencies = ["pybamm",]

[project.optional-dependencies]
dev = [
"pytest >=6",
"pytest-cov >=3",
"nox[uv]",
"pre-commit",
"pytest-cookies",
]
docs = [
"sphinx",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 +13,12 @@
{# keep this line here for newline #}
{%- if cookiecutter.mypy %}
__all__: list[str] = [
"__version__",
"pybamm",
"parameter_sets",
"Model",
"models",
]
{%- else %}
__all__ = [
{%- endif %}
"__version__",
"pybamm",
"parameter_sets",
"Model",
"models",
]
{%- endif %}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import pytest
import {{ cookiecutter.project_name }}
import importlib.util
import sys
from pathlib import Path

def test_parameter_sets_entry_points():
"""Test if the parameter_sets via entry points are loaded correctly."""

entry_points = list({{ cookiecutter.project_name }}.parameter_sets)
parameter_sets = Path("src/{{ cookiecutter.project_name }}/parameters/input/").glob("*.py")
# Making a list of parameter sets in the parameters/input directory
parameter_sets = [x.stem for x in parameter_sets]

assert parameter_sets == entry_points, "Entry points missing either in pyproject.toml or in the input directory"

def test_parameter_sets_entry_point_load():
"""Testing if the values get loaded via parameter entry points and are equal when loaded through entry points"""
# Loading parameter_sets through entry points
parameters = {{ cookiecutter.project_name }}.parameter_sets['Chen2020']
# Loading parameter sets through the source file by dynamically loading Chen2020.py as a module
spec = importlib.util.spec_from_file_location("Chen2020mod", "src/{{ cookiecutter.project_name }}/parameters/input/Chen2020.py")
chen_module = importlib.util.module_from_spec(spec)
sys.modules["Chen2020mod"] = chen_module
spec.loader.exec_module(chen_module)
parameters_from_file = chen_module.get_parameter_values()
assert parameters.keys() == parameters_from_file.keys(), f"The keys in the module and local input file are not the same, expected {parameters.keys} got {parameters_from_file.keys()}"

def test_model_entry_points():
"""Test if the models via entry points are loaded correctly."""

entry_points = list({{ cookiecutter.project_name }}.models)
models = Path("src/{{ cookiecutter.project_name }}/models/input/").glob("*.py")
# Making a list Parameter sets in the parameters/input directory
models = [x.stem for x in models]

assert models == entry_points, "Entry points missing either in pyproject.toml or in the input directory"

def test_model_entry_point_load():
"""Testing if the model gets initialised and returned."""
# Loading parameter_sets through entry points
model_instance = {{ cookiecutter.project_name }}.Model("SPM")
assert model_instance is not None

0 comments on commit 7ad77d5

Please sign in to comment.