Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -140,5 +140,8 @@ cython_debug/
# Editor
.vscode/

# Claude Code settings
.claude/*

# Project
kubeconfig
960 changes: 960 additions & 0 deletions poetry.lock

Large diffs are not rendered by default.

82 changes: 82 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
[tool.poetry]
name = "gepp"
version = "0.1.0"
description = "GEPP - Developer's Helper to K8s"
authors = ["Your Name <[email protected]>"]
readme = "README.md"

[tool.poetry.dependencies]
python = "^3.8"
docker = "4.2"
GitPython = "3.1"
Jinja2 = "^2.11.3"
MarkupSafe = "<2.1.0"
prompt-toolkit = "3.0"
python-slugify = "4.0"
cdktf = "0.0.17"
diceware = "0.9.6"

[tool.poetry.group.test.dependencies]
pytest = "^7.4.0"
pytest-cov = "^4.1.0"
pytest-mock = "^3.11.0"


[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"

[tool.pytest.ini_options]
minversion = "6.0"
addopts = "-ra -q --strict-markers --strict-config"
testpaths = ["tests"]
python_files = ["test_*.py", "*_test.py"]
python_classes = ["Test*"]
python_functions = ["test_*"]
markers = [
"unit: marks tests as unit tests (fast)",
"integration: marks tests as integration tests (slower)",
"slow: marks tests as slow running tests",
]

[tool.coverage.run]
source = ["."]
omit = [
"tests/*",
"venv/*",
".venv/*",
"*/site-packages/*",
".tox/*",
"build/*",
"dist/*",
"*.egg-info/*",
".pytest_cache/*",
"htmlcov/*",
"cdktf.out/*",
"kubernetes/*",
"Dockerfiles/*",
]
branch = true

[tool.coverage.report]
show_missing = true
skip_covered = false
fail_under = 80
exclude_lines = [
"pragma: no cover",
"def __repr__",
"if self.debug:",
"if settings.DEBUG",
"raise AssertionError",
"raise NotImplementedError",
"if 0:",
"if __name__ == .__main__.:",
"class .*\\bProtocol\\):",
"@(abc\\.)?abstractmethod",
]

[tool.coverage.html]
directory = "htmlcov"

[tool.coverage.xml]
output = "coverage.xml"
1 change: 1 addition & 0 deletions tests/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# Testing package for GEPP
128 changes: 128 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
"""Shared pytest fixtures for GEPP testing infrastructure."""

import os
import tempfile
import shutil
from pathlib import Path
from unittest.mock import Mock, MagicMock
import pytest


@pytest.fixture
def temp_dir():
"""Create a temporary directory for test files."""
temp_path = tempfile.mkdtemp()
yield Path(temp_path)
shutil.rmtree(temp_path)


@pytest.fixture
def mock_cwd(temp_dir, monkeypatch):
"""Mock the current working directory to use a temp directory."""
monkeypatch.chdir(temp_dir)
yield temp_dir


@pytest.fixture
def mock_docker_client():
"""Mock Docker client for testing Docker operations."""
mock_client = Mock()
mock_client.version.return_value = {
'Components': [{'Version': '20.10.0'}]
}
mock_client.images = Mock()
mock_client.containers = Mock()
return mock_client


@pytest.fixture
def mock_git_repo():
"""Mock Git repository for testing Git operations."""
mock_repo = Mock()
mock_repo.head.commit.hexsha = "abcdef1234567890"
return mock_repo


@pytest.fixture
def sample_requirements():
"""Sample requirements.txt content for testing."""
return [
"docker==4.2",
"GitPython==3.1",
"Jinja2==2.11",
"prompt-toolkit==3.0",
"python-slugify==4.0",
"cdktf==0.0.17",
"diceware==0.9.6"
]


@pytest.fixture
def mock_subprocess():
"""Mock subprocess for testing system command execution."""
mock_result = Mock()
mock_result.stdout = b"mock stdout"
mock_result.stderr = b""
mock_result.returncode = 0
return mock_result


@pytest.fixture
def mock_template_env():
"""Mock Jinja2 template environment for testing."""
mock_env = Mock()
mock_template = Mock()
mock_template.render.return_value = "mocked template content"
mock_env.get_template.return_value = mock_template
return mock_env


@pytest.fixture
def sample_config():
"""Sample configuration dictionary for testing."""
return {
'appObject': 'app',
'appName': 'test-app',
'mainFile': 'main.py',
'appPort': 80,
'codeDir': '.',
'dependencyFile': 'requirements.txt',
'baseImage': 'python:3-alpine3.12',
'currentCommit': 'abcdef12',
'baseDir': 'test-project',
'imageWorkDir': '/code',
'userID': 0,
'ports': [{'name': 'http', 'protocol': 'TCP', 'port': 80}],
'dnsName': 'localhost'
}


@pytest.fixture
def mock_file_exists(monkeypatch):
"""Mock file existence checking."""
def mock_exists(filename):
# By default, assume files don't exist unless specified
existing_files = {'main.py', 'requirements.txt'}
return filename in existing_files

monkeypatch.setattr(os.path, 'exists', mock_exists)


@pytest.fixture(autouse=True)
def clean_environment(monkeypatch):
"""Clean environment variables for consistent testing."""
# Remove environment variables that might affect tests
env_vars_to_remove = ['PROJECT_NAME', 'KUBECONFIG']
for var in env_vars_to_remove:
monkeypatch.delenv(var, raising=False)


@pytest.fixture
def mock_k3d_cluster():
"""Mock k3d cluster operations."""
mock_cluster = {
'name': 'test-cluster',
'ports': {'80': '30080', '443': '30443', '6443': '30643'},
'status': 'running'
}
return mock_cluster
1 change: 1 addition & 0 deletions tests/integration/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# Integration tests package
119 changes: 119 additions & 0 deletions tests/test_infrastructure.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
"""Validation tests for testing infrastructure setup."""

import pytest
import sys
from pathlib import Path

# Add the project root to the path for imports
project_root = Path(__file__).parent.parent
sys.path.insert(0, str(project_root))


class TestInfrastructure:
"""Test that the testing infrastructure is properly configured."""

def test_pytest_is_available(self):
"""Test that pytest is available and working."""
import pytest
assert pytest.__version__ is not None

def test_coverage_is_available(self):
"""Test that pytest-cov is available."""
try:
import pytest_cov
assert pytest_cov is not None
except ImportError:
pytest.fail("pytest-cov is not available")

def test_mock_is_available(self):
"""Test that pytest-mock is available."""
try:
import pytest_mock
assert pytest_mock is not None
except ImportError:
pytest.fail("pytest-mock is not available")

def test_project_structure_exists(self):
"""Test that the project structure is correct."""
project_root = Path(__file__).parent.parent

# Check main project files exist
assert (project_root / "main.py").exists()
assert (project_root / "pyproject.toml").exists()
assert (project_root / "requirements.txt").exists()

# Check testing structure exists
assert (project_root / "tests").exists()
assert (project_root / "tests" / "__init__.py").exists()
assert (project_root / "tests" / "conftest.py").exists()
assert (project_root / "tests" / "unit").exists()
assert (project_root / "tests" / "unit" / "__init__.py").exists()
assert (project_root / "tests" / "integration").exists()
assert (project_root / "tests" / "integration" / "__init__.py").exists()

@pytest.mark.unit
def test_unit_marker_works(self):
"""Test that the unit marker is properly configured."""
assert True

@pytest.mark.integration
def test_integration_marker_works(self):
"""Test that the integration marker is properly configured."""
assert True

@pytest.mark.slow
def test_slow_marker_works(self):
"""Test that the slow marker is properly configured."""
assert True

def test_fixtures_are_available(self, temp_dir, mock_docker_client, sample_config):
"""Test that common fixtures are available and working."""
# Test temp_dir fixture
assert temp_dir.exists()
assert temp_dir.is_dir()

# Test mock_docker_client fixture
assert mock_docker_client is not None
assert hasattr(mock_docker_client, 'version')

# Test sample_config fixture
assert isinstance(sample_config, dict)
assert 'appName' in sample_config

def test_main_module_can_be_imported(self):
"""Test that the main module can be imported without errors."""
try:
import main
assert hasattr(main, 'main')
except ImportError as e:
pytest.fail(f"Cannot import main module: {e}")


class TestSampleFunctionality:
"""Sample tests to validate testing capabilities."""

def test_basic_assertion(self):
"""Test basic assertion works."""
assert 1 + 1 == 2

def test_with_temp_dir(self, temp_dir):
"""Test that temp_dir fixture works."""
test_file = temp_dir / "test.txt"
test_file.write_text("hello world")
assert test_file.read_text() == "hello world"

def test_with_mock(self, mocker):
"""Test that pytest-mock works."""
mock_func = mocker.Mock(return_value=42)
result = mock_func()
assert result == 42
mock_func.assert_called_once()

@pytest.mark.parametrize("input,expected", [
(1, 2),
(2, 4),
(3, 6),
])
def test_parametrized(self, input, expected):
"""Test parametrized testing works."""
assert input * 2 == expected
1 change: 1 addition & 0 deletions tests/unit/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# Unit tests package