Skip to content

Commit 9e7e4ad

Browse files
author
Peter Simpson
committed
code checker unit tests
1 parent b27061a commit 9e7e4ad

File tree

2 files changed

+192
-0
lines changed

2 files changed

+192
-0
lines changed
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
"""
2+
Configuration and fixtures for code_checker tests.
3+
"""
4+
5+
import pytest
6+
from pathlib import Path
7+
from typing import Tuple, List
8+
9+
from code_utils.code_checker.codat_code_checker_config_models import CodeCheckerConfig, DEFAULT_CONFIG
10+
11+
12+
class DockerOperatorStub:
13+
"""
14+
A simplified stub for DockerOperator that provides controllable responses
15+
for testing CodeChecker in isolation from Docker daemon.
16+
"""
17+
18+
def __init__(self, config: CodeCheckerConfig = None, base_dir: Path = None):
19+
self.config = config or DEFAULT_CONFIG
20+
self.base_dir = base_dir or Path(__file__).parent
21+
22+
# Default responses - can be overridden in tests
23+
self._build_responses = {} # language -> (success, message)
24+
self._validation_responses = {} # language -> (success, output)
25+
26+
# Default to successful responses
27+
self._default_build_success = True
28+
self._default_build_message = "Build successful"
29+
self._default_validation_success = True
30+
self._default_validation_output = "Validation passed"
31+
32+
def set_build_response(self, language: str, success: bool, message: str):
33+
"""Set specific response for build_language_image calls."""
34+
self._build_responses[language] = (success, message)
35+
36+
def set_validation_response(self, language: str, success: bool, output: str):
37+
"""Set specific response for validate_language_snippets calls."""
38+
self._validation_responses[language] = (success, output)
39+
40+
def set_default_responses(self, build_success: bool = True, validation_success: bool = True):
41+
"""Set default responses for all languages."""
42+
self._default_build_success = build_success
43+
self._default_validation_success = validation_success
44+
45+
def build_language_image(self, language: str) -> Tuple[bool, str]:
46+
"""
47+
Stub for building Docker images.
48+
Returns configurable success/failure responses.
49+
"""
50+
if language in self._build_responses:
51+
return self._build_responses[language]
52+
53+
if self._default_build_success:
54+
return True, f"{self._default_build_message} for {language}"
55+
else:
56+
return False, f"Build failed for {language}"
57+
58+
def validate_language_snippets(self, language: str) -> Tuple[bool, str]:
59+
"""
60+
Stub for validating code snippets.
61+
Returns configurable success/failure responses.
62+
"""
63+
if language in self._validation_responses:
64+
return self._validation_responses[language]
65+
66+
if self._default_validation_success:
67+
return True, f"{self._default_validation_output} for {language}"
68+
else:
69+
return False, f"Validation failed for {language}"
70+
71+
72+
73+
@pytest.fixture
74+
def docker_operator_stub():
75+
"""
76+
Fixture providing a DockerOperator stub for testing.
77+
78+
Usage in tests:
79+
def test_code_checker_with_stub(docker_operator_stub):
80+
# Configure responses
81+
docker_operator_stub.set_build_response('python', True, 'Python build ok')
82+
docker_operator_stub.set_validation_response('python', False, 'Python validation failed')
83+
84+
# Inject into CodeChecker during initialization
85+
checker = CodeChecker(target_language='python', docker_operator=docker_operator_stub)
86+
87+
# Run tests
88+
results = checker.check_complete_snippets()
89+
90+
# Assert results
91+
assert results['build']['python']['success'] is True
92+
assert results['validation']['python']['success'] is False
93+
"""
94+
stub = DockerOperatorStub()
95+
return stub
96+
97+
98+
@pytest.fixture
99+
def failing_docker_operator_stub():
100+
"""
101+
Fixture providing a DockerOperator stub that fails by default.
102+
Useful for testing error handling scenarios.
103+
"""
104+
stub = DockerOperatorStub()
105+
stub.set_default_responses(build_success=False, validation_success=False)
106+
return stub
107+
108+
109+
@pytest.fixture
110+
def mock_config():
111+
"""Fixture providing a mock configuration for testing."""
112+
return DEFAULT_CONFIG
113+
114+
115+
@pytest.fixture
116+
def test_base_dir():
117+
"""Fixture providing a test base directory path."""
118+
return Path(__file__).parent.parent.parent / "code_checker"
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
"""
2+
Simple unit tests for CodeChecker using DockerOperator stub.
3+
"""
4+
5+
import pytest
6+
from code_utils.code_checker.code_checker import CodeChecker
7+
8+
9+
class TestCodeChecker:
10+
"""Simple unit tests for CodeChecker class."""
11+
12+
def test_successful_single_language_validation(self, docker_operator_stub):
13+
"""Test successful validation for a single language."""
14+
# Configure stub for success
15+
docker_operator_stub.set_build_response('python', True, 'Build successful')
16+
docker_operator_stub.set_validation_response('python', True, 'Validation passed')
17+
18+
# Create CodeChecker with injected stub
19+
checker = CodeChecker(target_language='python', docker_operator=docker_operator_stub)
20+
21+
# Run validation
22+
results = checker.check_complete_snippets()
23+
24+
# Assert success
25+
assert results['build']['python']['success'] is True
26+
assert results['validation']['python']['success'] is True
27+
assert 'Build successful' in results['build']['python']['message']
28+
assert 'Validation passed' in results['validation']['python']['output']
29+
30+
def test_build_failure_prevents_validation(self, docker_operator_stub):
31+
"""Test that build failure prevents validation from running."""
32+
# Configure stub for build failure
33+
docker_operator_stub.set_build_response('javascript', False, 'Build failed - missing deps')
34+
35+
# Create CodeChecker with injected stub
36+
checker = CodeChecker(target_language='javascript', docker_operator=docker_operator_stub)
37+
38+
# Run validation
39+
results = checker.check_complete_snippets()
40+
41+
# Assert build failed and no validation ran
42+
assert results['build']['javascript']['success'] is False
43+
assert 'Build failed' in results['build']['javascript']['message']
44+
assert len(results['validation']) == 0 # No validation due to build failure
45+
46+
def test_validation_failure_after_successful_build(self, docker_operator_stub):
47+
"""Test validation failure after successful build."""
48+
# Configure stub for build success but validation failure
49+
docker_operator_stub.set_build_response('csharp', True, 'Build OK')
50+
docker_operator_stub.set_validation_response('csharp', False, 'Compilation errors found')
51+
52+
# Create CodeChecker with injected stub
53+
checker = CodeChecker(target_language='csharp', docker_operator=docker_operator_stub)
54+
55+
# Run validation
56+
results = checker.check_complete_snippets()
57+
58+
# Assert build succeeded but validation failed
59+
assert results['build']['csharp']['success'] is True
60+
assert results['validation']['csharp']['success'] is False
61+
assert 'Compilation errors found' in results['validation']['csharp']['output']
62+
63+
def test_all_failing_scenario(self, failing_docker_operator_stub):
64+
"""Test scenario where all operations fail."""
65+
# Create CodeChecker with injected failing stub
66+
checker = CodeChecker(target_language='python', docker_operator=failing_docker_operator_stub)
67+
68+
# Run validation
69+
results = checker.check_complete_snippets()
70+
71+
# Assert build failed and no validation ran
72+
assert results['build']['python']['success'] is False
73+
assert len(results['validation']) == 0
74+

0 commit comments

Comments
 (0)