diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md
new file mode 100644
index 0000000..0bc53ef
--- /dev/null
+++ b/.github/PULL_REQUEST_TEMPLATE.md
@@ -0,0 +1,20 @@
+## Summary
+
+
+
+## Changes
+
+
+
+-
+
+## Testing
+
+
+
+- [ ] Tests pass locally (`python -m pytest tests/ -v`)
+- [ ] Pre-commit hooks pass (`pre-commit run --all-files`)
+
+## Related Issues
+
+
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
new file mode 100644
index 0000000..056f1bb
--- /dev/null
+++ b/.github/dependabot.yml
@@ -0,0 +1,27 @@
+version: 2
+
+updates:
+ # Python (pip) dependencies
+ - package-ecosystem: "pip"
+ directory: "/"
+ schedule:
+ interval: "weekly"
+ day: "monday"
+ open-pull-requests-limit: 10
+ labels:
+ - "dependencies"
+ commit-message:
+ prefix: "chore(deps)"
+
+ # GitHub Actions
+ - package-ecosystem: "github-actions"
+ directory: "/"
+ schedule:
+ interval: "weekly"
+ day: "monday"
+ open-pull-requests-limit: 5
+ labels:
+ - "dependencies"
+ - "ci"
+ commit-message:
+ prefix: "ci(deps)"
diff --git a/.github/workflows/auto-populate-pr.yml b/.github/workflows/auto-populate-pr.yml
new file mode 100644
index 0000000..b4c2996
--- /dev/null
+++ b/.github/workflows/auto-populate-pr.yml
@@ -0,0 +1,109 @@
+name: Auto-populate PR Body
+
+on:
+ pull_request:
+ types: [opened]
+
+permissions:
+ pull-requests: write
+
+jobs:
+ populate-body:
+ name: Generate PR Body
+ runs-on: ubuntu-22.04
+ steps:
+ - uses: actions/checkout@v4
+ with:
+ fetch-depth: 0
+
+ - name: Fetch base branch
+ run: git fetch origin ${{ github.event.pull_request.base.ref }} --depth=1
+
+ - name: Generate and update PR body
+ env:
+ GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ PR_NUMBER: ${{ github.event.pull_request.number }}
+ BASE_REF: ${{ github.event.pull_request.base.ref }}
+ run: |
+ # Fetch the current PR body
+ CURRENT_BODY=$(gh pr view "$PR_NUMBER" --json body -q '.body')
+
+ # Strip HTML comments, headers, whitespace, checklist items
+ STRIPPED=$(echo "$CURRENT_BODY" \
+ | sed 's///g' \
+ | sed '/^## /d' \
+ | sed '/^- \[.\]/d' \
+ | sed '/^-$/d' \
+ | sed 's/^[[:space:]]*//; s/[[:space:]]*$//' \
+ | sed '/^$/d')
+
+ if [[ -n "$STRIPPED" ]]; then
+ echo "PR body already has custom content. Skipping auto-populate."
+ exit 0
+ fi
+
+ echo "PR body is empty or template-only. Generating content..."
+
+ MERGE_BASE=$(git merge-base origin/"$BASE_REF" HEAD)
+
+ # --- Collect commit messages ---
+ COMMITS=$(git log --pretty=format:"- %s" "$MERGE_BASE"..HEAD)
+
+ # --- Collect changed files with stats ---
+ DIFF_STAT=$(git diff --stat "$MERGE_BASE"..HEAD)
+ FILE_LIST=$(git diff --name-only "$MERGE_BASE"..HEAD)
+
+ # --- Categorize changes ---
+ TOTAL=$(echo "$FILE_LIST" | grep -c '.' || true)
+ SRC_CHANGES=$(echo "$FILE_LIST" | grep -c '^src/' || true)
+ TEST_CHANGES=$(echo "$FILE_LIST" | grep -c '^tests/' || true)
+ DOC_CHANGES=$(echo "$FILE_LIST" | grep -cE '^(.github/.*\.md|.*README)' || true)
+ CI_CHANGES=$(echo "$FILE_LIST" | grep -cE '^\.github/(workflows|dependabot)' || true)
+
+ # --- Build summary line ---
+ SUMMARY_PARTS=()
+ [[ "$SRC_CHANGES" -gt 0 ]] && SUMMARY_PARTS+=("$SRC_CHANGES source file(s)")
+ [[ "$TEST_CHANGES" -gt 0 ]] && SUMMARY_PARTS+=("$TEST_CHANGES test file(s)")
+ [[ "$DOC_CHANGES" -gt 0 ]] && SUMMARY_PARTS+=("$DOC_CHANGES doc file(s)")
+ [[ "$CI_CHANGES" -gt 0 ]] && SUMMARY_PARTS+=("$CI_CHANGES CI file(s)")
+
+ if [[ ${#SUMMARY_PARTS[@]} -gt 0 ]]; then
+ SUMMARY_LINE="This PR touches $(IFS=', '; echo "${SUMMARY_PARTS[*]}") across $TOTAL file(s) total."
+ else
+ SUMMARY_LINE="This PR modifies $TOTAL file(s)."
+ fi
+
+ # --- Write PR body to a temp file ---
+ BODY_FILE=$(mktemp)
+ {
+ echo "## Summary"
+ echo ""
+ echo "$SUMMARY_LINE"
+ echo ""
+ echo "## Changes"
+ echo ""
+ echo "$COMMITS"
+ echo ""
+ echo ""
+ echo "Diff stats
"
+ echo ""
+ echo '```'
+ echo "$DIFF_STAT"
+ echo '```'
+ echo ""
+ echo " "
+ echo ""
+ echo "## Testing"
+ echo ""
+ echo '- [ ] Tests pass locally (`python -m pytest tests/ -v`)'
+ echo '- [ ] Pre-commit hooks pass (`pre-commit run --all-files`)'
+ echo ""
+ echo "## Related Issues"
+ echo ""
+ echo ""
+ } > "$BODY_FILE"
+
+ # Update the PR body from file
+ gh pr edit "$PR_NUMBER" --body-file "$BODY_FILE"
+ rm -f "$BODY_FILE"
+ echo "PR body has been auto-populated."
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
new file mode 100644
index 0000000..4c164fd
--- /dev/null
+++ b/.github/workflows/ci.yml
@@ -0,0 +1,80 @@
+name: CI
+
+on:
+ push:
+ branches: [main]
+ pull_request:
+ branches: [main]
+
+concurrency:
+ group: ${{ github.workflow }}-${{ github.ref }}
+ cancel-in-progress: true
+
+jobs:
+ lint:
+ name: Lint & Format
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+
+ - uses: actions/setup-python@v5
+ with:
+ python-version: "3.11"
+
+ - name: Install dependencies
+ run: |
+ pip install --upgrade pip
+ pip install pre-commit mypy bandit ruff
+
+ - name: Cache pre-commit hooks
+ uses: actions/cache@v4
+ with:
+ path: ~/.cache/pre-commit
+ key: pre-commit-${{ hashFiles('.pre-commit-config.yaml') }}
+ restore-keys: pre-commit-
+
+ - name: Run pre-commit
+ run: pre-commit run --all-files --show-diff-on-failure
+
+ - name: Lint check with ruff
+ run: ruff check src/ tests/ apps/
+
+ - name: Type check with mypy
+ run: mypy src/ apps/
+
+ - name: Security check with bandit
+ run: bandit -c pyproject.toml -r src/ apps/
+
+ test:
+ name: Test (Python ${{ matrix.python-version }}, ${{ matrix.os }})
+ runs-on: ${{ matrix.os }}
+ needs: lint
+ strategy:
+ fail-fast: false
+ matrix:
+ os: [ubuntu-latest, macos-latest]
+ python-version: ["3.9", "3.10", "3.11", "3.12"]
+ steps:
+ - uses: actions/checkout@v4
+
+ - uses: actions/setup-python@v5
+ with:
+ python-version: ${{ matrix.python-version }}
+
+ - name: Install dependencies
+ run: |
+ pip install --upgrade pip
+ pip install -r requirements.txt
+ pip install -e .
+
+ - name: Run tests
+ run: python -m pytest tests/ -v
+
+ - name: Run tests with coverage
+ run: |
+ python -m pytest tests/ \
+ -v \
+ --cov=template_project \
+ --cov-fail-under=90 \
+ --cov-report=term-missing \
+ --cov-report=xml
diff --git a/.github/workflows/dependency-review.yml b/.github/workflows/dependency-review.yml
new file mode 100644
index 0000000..c8b5542
--- /dev/null
+++ b/.github/workflows/dependency-review.yml
@@ -0,0 +1,24 @@
+name: Dependency Review
+
+on:
+ pull_request:
+ paths:
+ - "requirements*.txt"
+ - "setup.py"
+ - "pyproject.toml"
+
+permissions:
+ contents: read
+
+jobs:
+ dependency-review:
+ name: Review Dependencies
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+
+ - name: Dependency Review
+ uses: actions/dependency-review-action@v4
+ with:
+ fail-on-severity: high
+ comment-summary-in-pr: always
diff --git a/.github/workflows/pr-body.yml b/.github/workflows/pr-body.yml
new file mode 100644
index 0000000..17c391e
--- /dev/null
+++ b/.github/workflows/pr-body.yml
@@ -0,0 +1,54 @@
+name: PR Body Validation
+
+on:
+ pull_request:
+ # Runs on 'edited' and 'reopened' only — the 'opened' event is handled by
+ # the auto-populate workflow, which edits the body and triggers 'edited'.
+ types: [edited, reopened]
+
+jobs:
+ validate-body:
+ name: Validate PR Body
+ runs-on: ubuntu-22.04
+ steps:
+ - name: Check PR body is not empty
+ run: |
+ BODY=$(cat <<'BODY_EOF'
+ ${{ github.event.pull_request.body }}
+ BODY_EOF
+ )
+
+ # Strip HTML comments, whitespace, and section headers
+ CLEANED=$(echo "$BODY" | sed 's///g; /^## /d; /^- \[ \]/d; s/^[[:space:]]*//; s/[[:space:]]*$//; /^$/d; /^-$/d')
+
+ if [[ -z "$CLEANED" ]]; then
+ echo "::error::PR body is empty. Please provide a description of your changes."
+ echo ""
+ echo "A good PR description should include:"
+ echo " - What: A summary of the changes made"
+ echo " - Why: The motivation or issue being addressed"
+ echo " - How: Key implementation details (if non-obvious)"
+ echo " - Testing: How the changes were verified"
+ exit 1
+ fi
+
+ # Check minimum length (at least 20 characters of meaningful content)
+ CHAR_COUNT=${#CLEANED}
+ if [[ "$CHAR_COUNT" -lt 20 ]]; then
+ echo "::error::PR body is too short ($CHAR_COUNT chars). Please provide a meaningful description."
+ exit 1
+ fi
+
+ echo "PR body is present ($CHAR_COUNT chars)."
+
+ - name: Check for placeholder text
+ run: |
+ BODY=$(cat <<'BODY_EOF'
+ ${{ github.event.pull_request.body }}
+ BODY_EOF
+ )
+
+ # Warn if common placeholder patterns are detected
+ if echo "$BODY" | grep -qiE '(TODO|FIXME|PLACEHOLDER|fill in|describe here|add description)'; then
+ echo "::warning::PR body may contain placeholder text. Please ensure all sections are filled in."
+ fi
diff --git a/.github/workflows/pr-policy.yml b/.github/workflows/pr-policy.yml
new file mode 100644
index 0000000..5f20b81
--- /dev/null
+++ b/.github/workflows/pr-policy.yml
@@ -0,0 +1,63 @@
+name: PR Policy
+
+on:
+ pull_request:
+ types: [opened, edited, synchronize, labeled, unlabeled, reopened]
+
+jobs:
+ title-convention:
+ name: Validate PR Title
+ runs-on: ubuntu-latest
+ steps:
+ - name: Check conventional commit format
+ run: |
+ TITLE="${{ github.event.pull_request.title }}"
+ PATTERN="^(feat|fix|docs|doc|style|refactor|perf|test|build|ci|chore|revert)(\(.+\))?!?: .+"
+ if [[ ! "$TITLE" =~ $PATTERN ]]; then
+ echo "::error::PR title does not follow Conventional Commits format."
+ echo ""
+ echo "Expected format: (): "
+ echo " Types: feat, fix, docs, doc, style, refactor, perf, test, build, ci, chore, revert"
+ echo ""
+ echo "Examples:"
+ echo " feat: add decrement CLI command"
+ echo " fix(core): handle empty config file"
+ echo " docs: update installation instructions"
+ echo ""
+ echo "Got: '$TITLE'"
+ exit 1
+ fi
+ echo "PR title follows Conventional Commits format."
+
+ label-check:
+ name: Require Label
+ runs-on: ubuntu-latest
+ steps:
+ - name: Check for at least one label
+ run: |
+ LABEL_COUNT=$(echo '${{ toJson(github.event.pull_request.labels) }}' | jq 'length')
+ if [[ "$LABEL_COUNT" -eq 0 ]]; then
+ echo "::error::PR must have at least one label before merging."
+ echo "Consider adding a label such as: bug, enhancement, documentation, maintenance, etc."
+ exit 1
+ fi
+ echo "PR has $LABEL_COUNT label(s)."
+
+ branch-naming:
+ name: Validate Branch Name
+ runs-on: ubuntu-latest
+ steps:
+ - name: Check branch naming convention
+ run: |
+ BRANCH="${{ github.head_ref }}"
+ PATTERN="^(feature|fix|bugfix|hotfix|docs|chore|refactor|test|ci|release|claude)/"
+ if [[ ! "$BRANCH" =~ $PATTERN ]]; then
+ echo "::warning::Branch name '$BRANCH' does not follow the recommended naming convention."
+ echo ""
+ echo "Recommended format: /"
+ echo " Types: feature, fix, bugfix, hotfix, docs, chore, refactor, test, ci, release"
+ echo ""
+ echo "Examples:"
+ echo " feature/add-decrement-cli"
+ echo " fix/empty-config-handling"
+ fi
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index 8b071b9..4a0792c 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -4,7 +4,6 @@
# - Python linting + formatting (Ruff)
# - Typing checks (Mypy)
# - Security checks (Bandit)
-# - Docstring auto-formatting (Docformatter)
# - Docs build smoke test
# - Commit message enforcement
# - Shell script linting (shfmt + shellcheck)
@@ -44,14 +43,6 @@ repos:
- id: ruff-format
types_or: [python, pyi]
- # ---------- DOCSTRING AUTO-FIX (Docformatter) ----------
- - repo: https://github.com/PyCQA/docformatter
- rev: v1.7.7
- hooks:
- - id: docformatter
- args: [--in-place, --recursive, --wrap-summaries=88]
- types_or: [python]
-
# ---------- TYPES (MYPY) ----------
- repo: https://github.com/pre-commit/mirrors-mypy
rev: v1.19.1
@@ -125,11 +116,7 @@ repos:
rev: v1.38.0
hooks:
- id: yamllint
- args:
- [
- -d,
- "{extends: default, rules: {line-length: {max: 120}, document-start: disable}}",
- ]
+ args: [--config-file=.yamllint]
# ---------- CI / PRE-COMMIT.CI CONFIG ----------
ci:
diff --git a/.yamllint b/.yamllint
new file mode 100644
index 0000000..efa8b92
--- /dev/null
+++ b/.yamllint
@@ -0,0 +1,34 @@
+# .yamllint
+extends: default
+
+rules:
+ # GitHub Actions REQUIRE unquoted true/false for certain keys
+ truthy:
+ allowed-values: ["true", "false", "on", "off", "yes", "no"]
+ check-keys: false # Critical: don't validate GitHub Actions boolean keys
+
+ # Realistic line lengths for CI workflows (URLs, commands)
+ line-length:
+ max: 160
+ allow-non-breakable-words: true
+ allow-non-breakable-inline-mappings: true
+
+ # Enforce newline at EOF (pre-commit already does this)
+ new-lines:
+ type: unix
+
+ # Ignore GitHub Actions schema-specific constructs
+ comments-indentation: disable
+ indentation:
+ indent-sequences: consistent
+
+# Apply stricter rules to project YAML (configs), relaxed for workflows
+yaml-files:
+ - '*.yaml'
+ - '*.yml'
+
+ignore: |
+ .git/
+ __pycache__/
+ .venv/
+ venv/
diff --git a/apps/decrement_hydra.py b/apps/decrement_hydra.py
index 3178380..fe7130e 100644
--- a/apps/decrement_hydra.py
+++ b/apps/decrement_hydra.py
@@ -1,26 +1,36 @@
"""Sample app decrementing a given number using Hydra to handle CLI."""
import hydra
+from omegaconf import DictConfig
-from PROJECT_NAME.add import add
+from template_project.add import add
def decrement(x: int) -> int:
- """Return the decrement of a given value.
+ """
+ Return the decrement of a given value.
Args:
x (int): value to be decremented
Returns:
int: The decremented value 'x-1'
+
"""
return add(x, -1)
@hydra.main(version_base=None, config_path="configs", config_name="decrement")
-def main(config):
+def main(config: DictConfig) -> None:
+ """
+ Decrement the given value from config and print the result.
+
+ Args:
+ config: Hydra config object with 'value' attribute
+
+ """
result = decrement(config.value)
- print(result)
+ print(result) # noqa: T201
if __name__ == "__main__":
diff --git a/apps/increment_fire.py b/apps/increment_fire.py
index 832e28d..9c52e16 100644
--- a/apps/increment_fire.py
+++ b/apps/increment_fire.py
@@ -2,17 +2,19 @@
import fire
-from PROJECT_NAME.add import add
+from template_project.add import add
def increment(x: int) -> int:
- """Return the increment of a given value.
+ """
+ Return the increment of a given value.
Args:
x (int): value to be incremented
Returns:
int: The incremented value 'x+1'
+
"""
return add(x, 1)
diff --git a/docker/Dockerfile b/docker/Dockerfile
index 89506ea..5af147d 100644
--- a/docker/Dockerfile
+++ b/docker/Dockerfile
@@ -15,4 +15,4 @@ RUN apt update && \
echo "$USERNAME ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers
USER $USERNAME
-WORKDIR /workspace/PROJECT_NAME
+WORKDIR /workspace/template_project
diff --git a/docker/compose.yaml b/docker/compose.yaml
index 7042e1c..0450e94 100644
--- a/docker/compose.yaml
+++ b/docker/compose.yaml
@@ -1,7 +1,7 @@
services:
- project_name:
- image: project_name
- container_name: project_name_container
+ template_project:
+ image: template_project
+ container_name: template_project_container
build:
context: .
args:
@@ -17,6 +17,6 @@ services:
capabilities: [gpu]
command: sleep infinity
volumes:
- - ..:/workspace/PROJECT_NAME
+ - ..:/workspace/template_project
- ${HOST_SSH_FOLDER}:/home/${HOST_USERNAME}/.ssh:ro
- ${HOST_GITCONFIG_FILE}:/home/${HOST_USERNAME}/.gitconfig:ro
diff --git a/docker/create.sh b/docker/create.sh
index 0a623b6..d8f50b8 100755
--- a/docker/create.sh
+++ b/docker/create.sh
@@ -12,4 +12,4 @@ source set_env_variables.sh
docker compose up -d
# Get an interactive bash session in the container
-docker compose exec project_name bash
+docker compose exec template_project bash
diff --git a/docker/exec.sh b/docker/exec.sh
index 2026e39..bda1519 100755
--- a/docker/exec.sh
+++ b/docker/exec.sh
@@ -9,4 +9,4 @@ cd "$(dirname "$0")" || exit
source set_env_variables.sh
# Get an interactive bash session
-docker compose exec project_name bash
+docker compose exec template_project bash
diff --git a/pyproject.toml b/pyproject.toml
index 8f6e425..572d89c 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,21 +1,30 @@
[tool.ruff]
-# Core linting + formatting
line-length = 88
-target-version = ["py39", "py310", "py311", "py312"]
-fix = true
-select = ["ALL"]
+target-version = "py39"
+src = ["src", "apps", "tests"]
+
+[tool.ruff.lint]
+select = ["E", "F", "W", "B", "S", "D", "PLR"]
extend-ignore = [
- "E203", # Conflicts with line break before ':' in slices (Black style)
- "W503" # Line break before binary operator (Black style)
+ "E203", # Black-compatible slice formatting
+ "D203", # Google style: no blank line before class (keep D211)
+ "D212", # Google style: multi-line summary on second line (keep D213)
]
-src = ["src", "apps", "tests"]
-[tool.docformatter]
-# Auto-format docstrings
-wrap-summaries = 88
-pre-summary-newline = true
-make-summary-multi-line = true
-recursive = true
+[tool.ruff.lint.per-file-ignores]
+"tests/**/*.py" = [
+ "D100", "D101", "D102", # No docstring requirements in tests
+ "S101", # allow assert
+ "S602", # shell=True in subprocess (tests only)
+ "PLR2004", # Magic values in assertions are normal
+]
+
+[tool.ruff.format]
+quote-style = "double"
+indent-style = "space"
+skip-magic-trailing-comma = false
+line-ending = "auto"
+
[tool.mypy]
# Type checking
diff --git a/requirements.txt b/requirements.txt
index 4f9c3aa..2292cab 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,4 +1,10 @@
+bandit
fire
hydra-core
+mypy
pre-commit<4
pytest
+pytest-cov
+pytest-mock
+ruff
+types-PyYAML
diff --git a/setup.py b/setup.py
index 6c701d8..49e5985 100644
--- a/setup.py
+++ b/setup.py
@@ -1,7 +1,9 @@
+"""Docstring for setup."""
+
from setuptools import find_packages, setup
setup(
- name="PROJECT_NAME",
+ name="template_project",
version="0.0.0",
description="",
author="",
diff --git a/src/PROJECT_NAME/__init__.py b/src/PROJECT_NAME/__init__.py
deleted file mode 100644
index e69de29..0000000
diff --git a/src/template_project/__init__.py b/src/template_project/__init__.py
new file mode 100644
index 0000000..c10b7ed
--- /dev/null
+++ b/src/template_project/__init__.py
@@ -0,0 +1 @@
+"""Docstring for template_project."""
diff --git a/src/PROJECT_NAME/add.py b/src/template_project/add.py
similarity index 87%
rename from src/PROJECT_NAME/add.py
rename to src/template_project/add.py
index aa39836..6124e82 100644
--- a/src/PROJECT_NAME/add.py
+++ b/src/template_project/add.py
@@ -2,7 +2,8 @@
def add(a: int, b: int) -> int:
- """Return the sum of two numbers.
+ """
+ Return the sum of two numbers.
Adds two numbers using internally the '+' operator.
@@ -12,6 +13,6 @@ def add(a: int, b: int) -> int:
Returns:
int: The value 'a+b'
- """
+ """
return a + b
diff --git a/tests/__init__.py b/tests/__init__.py
index e69de29..40c103b 100644
--- a/tests/__init__.py
+++ b/tests/__init__.py
@@ -0,0 +1 @@
+"""Docstring for apps/__init__.py."""
diff --git a/tests/apps/__init__.py b/tests/apps/__init__.py
new file mode 100644
index 0000000..56fced9
--- /dev/null
+++ b/tests/apps/__init__.py
@@ -0,0 +1 @@
+"""Docstring for tests.apps."""
diff --git a/tests/apps/test_decrement_hydra.py b/tests/apps/test_decrement_hydra.py
index 93720bb..1ffac58 100644
--- a/tests/apps/test_decrement_hydra.py
+++ b/tests/apps/test_decrement_hydra.py
@@ -1,3 +1,5 @@
+"""Tests for the decrement function."""
+
import subprocess
import tempfile
from pathlib import Path
@@ -5,9 +7,8 @@
apps_directory_path = Path(__file__).parents[2] / "apps"
-def test_increment_fire():
+def test_increment_fire() -> None:
"""Test the decrement_hydra.py script."""
-
with tempfile.TemporaryDirectory() as tmp_dir:
command = (
f"python {apps_directory_path / 'decrement_hydra.py'} "
diff --git a/tests/apps/test_increment_fire.py b/tests/apps/test_increment_fire.py
index 48081b1..6555aa2 100644
--- a/tests/apps/test_increment_fire.py
+++ b/tests/apps/test_increment_fire.py
@@ -1,12 +1,13 @@
+"""Tests for the increment function."""
+
import subprocess
from pathlib import Path
apps_directory_path = Path(__file__).parents[2] / "apps"
-def test_increment_fire():
+def test_increment_fire() -> None:
"""Test the increment_fire.py script."""
-
command = f"python {apps_directory_path / 'increment_fire.py'} --x 2"
res = int(subprocess.check_output(command, shell=True))
assert res == 3
diff --git a/tests/test_add.py b/tests/test_add.py
index 6bb8101..93be505 100644
--- a/tests/test_add.py
+++ b/tests/test_add.py
@@ -1,7 +1,8 @@
-from PROJECT_NAME.add import add
+"""Tests for the add function."""
+from template_project.add import add
-def test_add():
- """Test of the add module."""
+def test_add() -> None:
+ """Test of the add module."""
assert add(0, 1) == 1