Skip to content
Merged
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
24 changes: 23 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,33 @@ jobs:
run: |
python -m pip install --upgrade pip
pip install -e .[dev]
pip install pytest ruff mypy
- name: Run linter
run: ruff check .
- name: Run type checks
run: |
PYTHONPATH=src mypy --ignore-missing-imports src tests
- name: Run tests
run: pytest -q

# Build with coverage for PRs only
build-with-coverage:
runs-on: ubuntu-latest
if: github.event_name == 'pull_request'
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: '3.11'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -e .[dev]
- name: Run tests with coverage
run: |
PYTHONPATH=src python -m pytest --cov=src --cov-report=term-missing --cov-report=html --cov-fail-under=39
- name: Upload coverage reports
if: always()
uses: actions/upload-artifact@v4
with:
name: coverage-report
path: coverage_html_report/
42 changes: 40 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,16 @@ dependencies = [
"anthropic>=0.7.0",
"openai>=1.0.0",
"google-generativeai>=0.3.0",
"types-requests>=2.32",
]

[project.optional-dependencies]
dev = [
"pytest>=7.0",
"pytest-cov>=5.0",
"pre-commit>=3.0",
"ruff>=0.3.0",
"mypy>=1.0",
"types-requests>=2.32",
"pre-commit>=3.0"
]

[project.scripts]
Expand All @@ -33,3 +36,38 @@ packages = ["src"]
[tool.ruff]
line-length = 120
target-version = "py311"

[tool.pytest.ini_options]
testpaths = ["tests"]
pythonpath = ["src"]
addopts = "--strict-markers --strict-config"

[tool.coverage.run]
source = ["src"]
branch = true
omit = [
"*/tests/*",
"*/test_*",
"*/__pycache__/*",
"*/conftest.py",
"*/cli/*", # Exclude CLI tools
"*/bench/*", # Exclude benchmark tools
"*/validators/*", # Exclude validators (placeholder code)
]

[tool.coverage.report]
fail_under = 39
show_missing = true
skip_covered = false
precision = 2
exclude_lines = [
"pragma: no cover",
"def __repr__",
"raise AssertionError",
"raise NotImplementedError",
"if __name__ == .__main__.:",
"@abstract",
]

[tool.coverage.html]
directory = "coverage_html_report"
12 changes: 0 additions & 12 deletions requirements.txt

This file was deleted.

Empty file added tests/agentNodes/__init__.py
Empty file.
14 changes: 7 additions & 7 deletions tests/agentNodes/test_hld_designer.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
from agentNodes.hld_designer import HLDDesigner
from src.agentNodes.hld_designer import HLDDesigner
from pydantic import TypeAdapter

from dataModel.task import Task, TaskType
from dataModel.model_response import (
from src.dataModel.task import Task, TaskType
from src.dataModel.model_response import (
DecomposedResponse,
ImplementedResponse,
DesignerResponse,
ModelResponse,
)
from modelAccessors.base_accessor import BaseModelAccessor
from src.modelAccessors.base_accessor import BaseModelAccessor


class _StubAccessor(BaseModelAccessor):
Expand All @@ -18,12 +18,12 @@ def call_model(
self,
prompt: str,
*,
adapter: TypeAdapter[DesignerResponse],
adapter: TypeAdapter[ModelResponse],
schema: dict,
model: str = "gpt-4",
system_prompt: str = "",
tools=None,
) -> DesignerResponse:
) -> ModelResponse:
return self._result


Expand Down
12 changes: 6 additions & 6 deletions tests/agentNodes/test_implementer.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
from pydantic import TypeAdapter

from agentNodes.implementer import Implementer
from modelAccessors.base_accessor import BaseModelAccessor
from dataModel.model_response import ImplementedResponse
from dataModel.task import Task, TaskType
from src.agentNodes.implementer import Implementer
from src.modelAccessors.base_accessor import BaseModelAccessor
from src.dataModel.model_response import ImplementedResponse, ModelResponse
from src.dataModel.task import Task, TaskType


class _StubAccessor(BaseModelAccessor):
Expand All @@ -14,12 +14,12 @@ def call_model(
self,
prompt: str,
*,
adapter: TypeAdapter[ImplementedResponse],
adapter: TypeAdapter[ModelResponse],
schema: dict,
model: str = "gpt-4",
system_prompt: str = "",
tools=None,
) -> ImplementedResponse:
) -> ModelResponse:
return self._result


Expand Down
12 changes: 6 additions & 6 deletions tests/agentNodes/test_lld_designer.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import pytest
from pydantic import TypeAdapter, ValidationError

from agentNodes.lld_designer import LLDDesigner
from dataModel.model_response import ImplementedResponse
from dataModel.task import Task, TaskType
from modelAccessors.base_accessor import BaseModelAccessor
from src.agentNodes.lld_designer import LLDDesigner
from src.dataModel.model_response import ImplementedResponse, ModelResponse
from src.dataModel.task import Task, TaskType
from src.modelAccessors.base_accessor import BaseModelAccessor


class _StubAccessor(BaseModelAccessor):
Expand All @@ -15,12 +15,12 @@ def call_model(
self,
prompt: str,
*,
adapter: TypeAdapter[ImplementedResponse],
adapter: TypeAdapter[ModelResponse],
schema: dict,
model: str = "gpt-4",
system_prompt: str = "",
tools=None,
) -> ImplementedResponse:
) -> ModelResponse:
return self._result


Expand Down
14 changes: 7 additions & 7 deletions tests/agentNodes/test_researcher.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import pytest
from pydantic import TypeAdapter, ValidationError

from agentNodes.researcher import Researcher
from tools.web_search import WEB_SEARCH_TOOL
from dataModel.model_response import ImplementedResponse
from dataModel.task import Task, TaskType
from modelAccessors.base_accessor import BaseModelAccessor
from src.agentNodes.researcher import Researcher
from src.tools.web_search import WEB_SEARCH_TOOL
from src.dataModel.model_response import ImplementedResponse, ModelResponse
from src.dataModel.task import Task, TaskType
from src.modelAccessors.base_accessor import BaseModelAccessor


class _StubAccessor(BaseModelAccessor):
Expand All @@ -16,12 +16,12 @@ def call_model(
self,
prompt: str,
*,
adapter: TypeAdapter[ImplementedResponse],
adapter: TypeAdapter[ModelResponse],
schema: dict,
model: str = "gpt-4",
system_prompt: str = "",
tools=None,
) -> ImplementedResponse:
) -> ModelResponse:
return self._result


Expand Down
Empty file added tests/cli/__init__.py
Empty file.
Empty file added tests/dataBuilders/__init__.py
Empty file.
Empty file.
Empty file added tests/dataModel/__init__.py
Empty file.
File renamed without changes.
51 changes: 51 additions & 0 deletions tests/dataModel/test_validation_result.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import pytest

from src.dataModel.validation_result import ValidationResult


def test_validation_result_valid_with_no_errors():
"""Test creating a valid ValidationResult with no errors."""
result = ValidationResult(is_valid=True, errors=None)
assert result.is_valid is True
assert result.errors is None


def test_validation_result_valid_with_empty_errors():
"""Test creating a valid ValidationResult with empty errors list."""
result = ValidationResult(is_valid=True, errors=[])
assert result.is_valid is True
assert result.errors == []


def test_validation_result_invalid_with_errors():
"""Test creating an invalid ValidationResult with errors."""
errors = ["Error 1", "Error 2"]
result = ValidationResult(is_valid=False, errors=errors)
assert result.is_valid is False
assert result.errors == errors


def test_validation_result_invalid_with_single_error():
"""Test creating an invalid ValidationResult with a single error."""
error = ["Single error"]
result = ValidationResult(is_valid=False, errors=error)
assert result.is_valid is False
assert result.errors == error


def test_validation_result_invalid_valid_true_with_errors_raises_error():
"""Test that ValidationResult raises error when is_valid=True but errors are present."""
with pytest.raises(ValueError, match="Cannot have both is_valid=True and an error_message"):
ValidationResult(is_valid=True, errors=["Some error"])


def test_validation_result_invalid_valid_false_with_no_errors_raises_error():
"""Test that ValidationResult raises error when is_valid=False but no errors provided."""
with pytest.raises(ValueError, match="Must provide an error_message when is_valid=False"):
ValidationResult(is_valid=False, errors=None)


def test_validation_result_invalid_valid_false_with_empty_errors_raises_error():
"""Test that ValidationResult raises error when is_valid=False but empty errors provided."""
with pytest.raises(ValueError, match="Must provide an error_message when is_valid=False"):
ValidationResult(is_valid=False, errors=[])
Empty file.
Loading