Skip to main content

Athena's testing framework provides a comprehensive set of shared utilities that enable consistent, efficient, and maintainable testing across all modules. These utilities are organized hierarchically to maximize reusability while allowing module-specific customizations.

Utility Organization

The shared utilities are organized in a hierarchical structure:

tests/modules/
├── text/
│ └── utils/ # Text module shared utilities
│ ├── mock_config.py # Mock configuration objects
│ ├── mock_env.py # Mock environment variables
│ ├── mock_llm_config.py # Mock LLM configuration
│ ├── mock_llm.py # Mock LLM implementations
│ └── mock_openai.py # Mock OpenAI API responses
└── {module_type}/
└── module_{module_name}/
├── mock/
│ └── utils/ # Module-specific mock utilities
└── real/
└── utils/ # Module-specific real test utilities

Core Utility Categories

Mock Configuration Utilities

MockApproachConfig

Provides standardized mock configuration objects for testing:

class MockApproachConfig:
"""Mock configuration for approach testing."""

def __init__(self, max_input_tokens=5000, model=None, type="default"):
self.max_input_tokens = max_input_tokens
self.model = model or MockModelConfig()
self.type = type

MockModelConfig

Standardized mock model configuration:

class MockModelConfig:
"""Mock model configuration for testing."""

def __init__(self):
self.model_name = "mock-model"
self.provider = "mock"

Mock LLM Implementations

MockLanguageModel

Base mock LLM implementation with configurable responses:

class MockLanguageModel:
"""Mock language model for testing."""

def __init__(self):
self.responses = {
"default": "Mock LLM response",
"feedback": "This is mock feedback.",
"grading": "Mock grading analysis."
}

async def ainvoke(self, prompt):
"""Return mock response based on prompt content."""
if "feedback" in prompt.lower():
return self.responses["feedback"]
elif "grading" in prompt.lower():
return self.responses["grading"]
return self.responses["default"]

MockStructuredMockLanguageModel

Specialized mock for structured output testing:

class MockStructuredMockLanguageModel(MockLanguageModel):
"""Mock LLM for structured output testing."""

async def ainvoke(self, prompt):
"""Return structured mock response."""
return {
"feedback_suggestions": [
{
"title": "Mock Feedback Title",
"description": "Mock feedback description",
"credits": 1.0
}
]
}

MockAssessmentModel

Mock implementation for assessment and evaluation testing:

class MockAssessmentModel:
"""Mock assessment model for evaluation testing."""

async def evaluate(self, submission, feedback):
"""Return mock evaluation results."""
return {
"score": 0.85,
"confidence": 0.92,
"details": "Mock evaluation details"
}

Environment Mocking Utilities

Mock Environment Variables

Standardized environment variable mocking:

@pytest.fixture(autouse=True)
def mock_env_vars(monkeypatch):
"""Mock environment variables for testing."""
mock_vars = {
"MOCK_MODE": "true",
"API_KEY": "mock_api_key",
"MODULE_NAME": "mock_module",
"MODULE_TYPE": "text",
"PORT": "5001"
}

for key, value in mock_vars.items():
monkeypatch.setenv(key, value)

Mock API Configuration

Mock API client configurations:

class MockOpenAI:
"""Mock OpenAI API client."""

def __init__(self):
self.responses = {
"chat.completions.create": {
"choices": [{
"message": {
"content": "Mock OpenAI response"
}
}]
}
}

def chat(self):
return MockChatCompletion()

Fixture Utilities

Pytest Fixtures

Standardized pytest fixtures for consistent test setup:

@pytest.fixture
def mock_llm():
"""Provide a basic mock language model."""
return MockLanguageModel()

@pytest.fixture
def mock_structured_llm():
"""Provide a structured mock language model."""
return MockStructuredMockLanguageModel()

@pytest.fixture
def mock_assessment_model():
"""Provide a mock assessment model."""
return MockAssessmentModel()

@pytest.fixture
def mock_config():
"""Create a mock configuration for testing."""
return MockApproachConfig(
max_input_tokens=5000,
model=MockModelConfig(),
type="default"
)

Session-Level Fixtures

Fixtures that persist across test sessions:

@pytest.fixture(scope="session", autouse=True)
def setup_test_environment():
"""Setup test environment for the entire session."""
# Download required NLTK data
nltk.download("punkt", quiet=True)
nltk.download("punkt_tab", quiet=True)

# Setup other session-level configurations
configure_test_logging()
setup_test_database()

Test Data Utilities

Exercise Data Loaders

Utilities for loading and managing test exercise data:

class PlaygroundExerciseLoader:
"""Helper class to load exercises from playground data."""

def __init__(self, data_dir=None):
if data_dir is None:
self.data_dir = Path(__file__).parent / "data" / "exercises"
else:
self.data_dir = Path(data_dir)

def load_exercise(self, exercise_id):
"""Load an exercise from JSON file."""
exercise_file = self.data_dir / f"exercise-{exercise_id}.json"
if not exercise_file.exists():
raise FileNotFoundError(f"Exercise file not found: {exercise_file}")

with open(exercise_file, 'r', encoding='utf-8') as f:
return json.load(f)

def convert_to_athena_exercise(self, exercise_data):
"""Convert playground data to Athena Exercise object."""
return Exercise(
id=exercise_data["id"],
title=exercise_data["title"],
type=ExerciseType(exercise_data["type"]),
max_points=exercise_data["max_points"],
bonus_points=exercise_data.get("bonus_points", 0),
grading_instructions=exercise_data.get("grading_instructions", ""),
problem_statement=exercise_data.get("problem_statement", ""),
example_solution=exercise_data.get("example_solution", ""),
grading_criteria=[],
meta=exercise_data.get("meta", {}),
)

Submission Data Utilities

Utilities for creating and managing test submissions:

def create_mock_submission(submission_id=1, text="Mock submission text"):
"""Create a mock submission for testing."""
return Submission(
id=submission_id,
exercise_id=1,
text=text,
meta={},
language=TextLanguageEnum.ENGLISH,
)

def create_mock_feedback(feedback_id=1, title="Mock Feedback", credits=1.0):
"""Create a mock feedback for testing."""
return Feedback(
exercise_id=1,
submission_id=1,
title=title,
description="Mock feedback description",
credits=credits,
is_graded=True,
meta={},
)

Module-Specific Utilities

Text Module Utilities

class TextModuleTestUtils:
"""Utilities specific to text module testing."""

@staticmethod
def create_text_exercise(title="Mock Text Exercise"):
"""Create a mock text exercise."""
return TextExercise(
id=1,
title=title,
type=ExerciseType.text,
max_points=10,
problem_statement="Mock problem statement",
example_solution="Mock example solution"
)

@staticmethod
def create_text_submission(text="Mock submission text"):
"""Create a mock text submission."""
return Submission(
id=1,
exercise_id=1,
text=text,
language=TextLanguageEnum.ENGLISH,
meta={}
)

Modeling Module Utilities

class ModelingModuleTestUtils:
"""Utilities specific to modeling module testing."""

@staticmethod
def create_modeling_exercise(title="Mock Modeling Exercise"):
"""Create a mock modeling exercise."""
return ModelingExercise(
id=1,
title=title,
type=ExerciseType.modeling,
max_points=20,
problem_statement="Create a UML diagram",
example_solution="{}"
)

@staticmethod
def create_model_submission(model_data="{}"):
"""Create a mock model submission."""
return Submission(
id=1,
exercise_id=1,
text="Mock model submission",
model=model_data,
meta={}
)

Programming Module Utilities

class ProgrammingModuleTestUtils:
"""Utilities specific to programming module testing."""

@staticmethod
def create_programming_exercise(title="Mock Programming Exercise"):
"""Create a mock programming exercise."""
return ProgrammingExercise(
id=1,
title=title,
type=ExerciseType.programming,
max_points=15,
programming_language="java",
solution_repository_uri="http://mock.com/solution.zip",
template_repository_uri="http://mock.com/template.zip",
tests_repository_uri="http://mock.com/tests.zip"
)