Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
7869fbf
project generator unit test
chrisdedman Aug 17, 2024
6bae6b9
Add unit test workflow for Grace Framework
chrisdedman Aug 17, 2024
6af6ab7
move workflow
chrisdedman Aug 17, 2024
c5269ad
Refactor workflow file for Grace Framework
chrisdedman Aug 17, 2024
7dffb16
Added to pyproject.toml exclude templates from flake8 linting
chrisdedman Aug 17, 2024
62d79e1
Merge branch 'main' into unit-tests
chrisdedman Aug 17, 2024
040fd04
Add pytest-mock to the dependencies
chrisdedman Aug 17, 2024
a25b150
Refactor project generator tests and add pytest fixtures
chrisdedman Aug 17, 2024
7a07bb2
added regex for name matching validation
chrisdedman Aug 17, 2024
2ca7920
updating regex
chrisdedman Aug 17, 2024
b1395d8
Added generator tests
chrisdedman Aug 17, 2024
1b6c06a
Update pytest command to include verbose output
chrisdedman Aug 17, 2024
df4c5c0
Add tests for config module
chrisdedman Aug 17, 2024
a552086
Add installation of project dependencies in GitHub Actions workflow
chrisdedman Aug 17, 2024
6563a9b
tentative fix github action
chrisdedman Aug 17, 2024
f0e2e58
moving pip install .
chrisdedman Aug 17, 2024
64fe3c0
Update .flake8
chrisdedman Aug 17, 2024
abb5b51
Fix tentative flake8
chrisdedman Aug 17, 2024
f2b3fcf
commented test cases
chrisdedman Aug 18, 2024
817b402
Merge branch 'unit-tests' of https://github.com/Code-Society-Lab/grac…
chrisdedman Aug 18, 2024
7fa49d3
Added ./idea to gitignore
PenguinBoi12 Jan 24, 2025
8ddaea1
Small cleanup and added some documentation
PenguinBoi12 Jan 24, 2025
9b322fd
Added missing packages to pyproject
PenguinBoi12 Jan 24, 2025
e661485
Updated workflow - removed package install that shouldn't be there
PenguinBoi12 Jan 24, 2025
26f28c0
Merge branch 'main' into unit-tests
PenguinBoi12 Jan 24, 2025
5e93896
Fix fixture generator
PenguinBoi12 Jan 24, 2025
273b491
Merge branch 'main' into unit-tests
PenguinBoi12 Jan 24, 2025
d689a67
Fix project generator name validation tests and added some example in…
PenguinBoi12 Jan 24, 2025
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
2 changes: 1 addition & 1 deletion .flake8
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
[flake8]
exclude = grace/generators/templates/*
exclude = grace/generators/templates/
9 changes: 4 additions & 5 deletions .github/workflows/grace_framework.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,13 @@ jobs:
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install flake8 pytest
if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
pip install .
- name: Lint with flake8
run: |
# stop the build if there are Python syntax errors or undefined names
flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
flake8 grace --count --select=E9,F63,F7,F82 --show-source --statistics
# exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide
flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
flake8 grace --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
- name: Test with pytest
run: |
pytest
pytest -v
2 changes: 0 additions & 2 deletions grace/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@
from click import group, argument, option, pass_context
from grace.generator import register_generators

import os
import sys

APP_INFO = """
| Discord.py version: {discord_version}
Expand Down
4 changes: 2 additions & 2 deletions grace/generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from pathlib import Path
from grace.importer import import_package_modules
from cookiecutter.main import cookiecutter
from grace.exceptions import ValidationError
from grace.exceptions import GeneratorError, ValidationError


def register_generators(command_group: Group):
Expand Down Expand Up @@ -33,7 +33,7 @@ class Generator(Command):

def __init__(self):
if not self.NAME:
raise ValueError("Generator name must be defined.")
raise GeneratorError("Generator name must be defined.")

super().__init__(self.NAME, callback=self._generate, **self.OPTIONS)

Expand Down
24 changes: 20 additions & 4 deletions grace/generators/project_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ class ProjectGenerator(Generator):
"hidden": True
}

def generate(self, name, database=True):
def generate(self, name: str, database: bool = True):
info(f"Creating '{name}'")

self.generate_template(self.NAME, values={
Expand All @@ -18,9 +18,25 @@ def generate(self, name, database=True):
"database": "yes" if database else "no"
})

def validate(self, name, **_kwargs):
return match('([a-z]|[0-9]|-)+', name)
def validate(self, name: str, **_kwargs) -> bool:
"""Validate the project name.

A valid project name must:
- contain only lowercase letters, numbers, and hyphens

def generator():
Example:
- "awesome-project" is valid
- "awesomeproject" is valid
- "awesome-project1" is valid
- "my-awesome-project" is valid

- "awesomeProject" is invalid
- "AwesomeProject" is invalid
- "awesome_project" is invalid
- "myAwesomeproject12" is invalid
"""
return bool(match('([a-z]|[0-9]|-)+', name))


def generator() -> Generator:
return ProjectGenerator()
2 changes: 2 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ dependencies = [
"cookiecutter",
"mypy",
"pytest",
"flake8",
"pytest-mock",
"coverage",
]

Expand Down
Empty file added tests/__init__.py
Empty file.
55 changes: 55 additions & 0 deletions tests/generators/test_project_generator.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import pytest
from grace.generator import Generator
from grace.generators.project_generator import ProjectGenerator


@pytest.fixture
def generator():
return ProjectGenerator()


def test_generate_project_with_database(mocker, generator):
"""Test if the generate method creates the correct template with a database."""
mock_generate_template = mocker.patch.object(Generator, 'generate_template')
name = "example-project"

generator.generate(name, database=True)

mock_generate_template.assert_called_once_with('project', values={
'project_name': name,
'project_description': '',
'database': 'yes'
})


def test_generate_project_without_database(mocker, generator):
"""Test if the generate method creates the correct template without a database."""
mock_generate_template = mocker.patch.object(Generator, 'generate_template')
name = "example-project"

generator.generate(name, database=False)

mock_generate_template.assert_called_once_with('project', values={
'project_name': name,
'project_description': '',
'database': 'no'
})


def test_validate_valid_name(generator):
"""Test if the validate method passes for a valid project name."""
valid_name = "example-project"
assert generator.validate(valid_name) == True


def test_validate_invalid_name_no_hyphen(generator):
"""Test if the validate method raises ValueError for name without a hyphen."""
invalid_name = "ExampleProject"
assert generator.validate(invalid_name) == False


def test_validate_invalid_name_uppercase(generator):
"""Test if the validate method raises ValueError for uppercase name."""
invalid_name = "Example-Project"
assert generator.validate(invalid_name) == False

52 changes: 52 additions & 0 deletions tests/test_config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import pytest
from grace.config import Config


@pytest.fixture
def config():
return Config()


def test_set_environment(config):
"""Test if the environment is set correctly"""
config.set_environment("test")

assert config.current_environment == "test"


# def test_section_name(config):
# """Test if the section name is set correctly"""
# config.set_environment("test")

# assert config.environment.name == "test"


# def test_database(config):
# config.set_environment("test")

# assert config.database["adapter"] == "sqlite"
# assert config.database["database"] == "grace_test.db"


# def test_database_uri(config):
# from sqlalchemy.engine import URL

# config.set_environment("test")

# assert config.database_uri == URL.create(drivername="sqlite", database="grace_test.db")


# def test_get(config):
# config.set_environment("test")

# assert config.get("test", "test") == "test"
# assert config.get("test", "test_int") == 42
# assert config.get("test", "test_float") == 42.5
# assert config.get("test", "test_bool") is True
# assert config.get("test", "test_fallback") is None


# def test_client(config):
# config.set_environment("test")

# assert config.client is not None
60 changes: 60 additions & 0 deletions tests/test_generator.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import pytest
from unittest.mock import patch, MagicMock
from grace.generator import Generator
from grace.exceptions import ValidationError
from grace.generator import register_generators


class MockGenerator(Generator):
NAME = 'mock'


@pytest.fixture
def generator():
return MockGenerator()


def test_generator(generator):
"""Test if the generator is initialized correctly"""
assert generator.NAME == 'mock'
assert generator.OPTIONS == {}


def test_validate(generator):
"""Test if the generator validate method returns True"""
assert generator.validate() == True


def test_generate_template(generator):
"""Test if the generator generate_template method calls cookiecutter with the correct arguments"""
with patch('grace.generator.cookiecutter') as cookiecutter:
generator.generate_template('project', values={})
template_path = str(generator.templates_path / 'project')
cookiecutter.assert_called_once_with(template_path, extra_context={}, no_input=True)


def test_generate(generator):
"""Test if the generator generate method raises a NotImplementedError"""
with pytest.raises(NotImplementedError):
generator.generate()


def test_register_generators():
"""Test if the register_generators function registers all the generators"""
with patch('grace.generator.import_package_modules') as import_package_modules:
import_package_modules.return_value = [MagicMock(generator=MagicMock())]
command_group = MagicMock()
register_generators(command_group)
command_group.add_command.assert_called_once()
import_package_modules.assert_called_once()
from grace import generators
import_package_modules.assert_called_with(generators, shallow=False)


def test_generate_validate(generator):
"""Test if the generator _generate method raises a ValidationError"""
with patch('grace.generator.Generator.validate') as validate:
validate.return_value = False
with pytest.raises(ValidationError):
generator._generate()
validate.assert_called_once()