Skip to content

Commit 812cace

Browse files
committed
f
1 parent 4800929 commit 812cace

File tree

2 files changed

+104
-100
lines changed

2 files changed

+104
-100
lines changed

tests/integration/README.md

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
# Integration Tests
2+
3+
This directory contains integration tests for OpenEvolve. Tests are organized into two categories:
4+
5+
## Fast Tests (CI)
6+
7+
**Smoke tests** that run in CI to validate basic functionality without requiring slow LLM inference:
8+
9+
```bash
10+
# Run only fast tests (for CI)
11+
pytest tests/integration/ -m "not slow"
12+
```
13+
14+
These tests:
15+
- Complete in <10 seconds total
16+
- Test core API validation, configuration, and basic component initialization
17+
- No real LLM calls required
18+
19+
## Slow Tests (Local Development)
20+
21+
**Full integration tests** with real LLM inference for comprehensive validation:
22+
23+
```bash
24+
# Run all tests including slow ones (for local development)
25+
pytest tests/integration/
26+
27+
# Run only slow tests
28+
pytest tests/integration/ -m "slow"
29+
```
30+
31+
These tests:
32+
- Take ~1 hour to complete
33+
- Use real optillm server with google/gemma-3-270m-it model
34+
- Test complete evolution pipelines, checkpointing, island migration, etc.
35+
- Require optillm server running on localhost:8000
36+
37+
## Test Setup
38+
39+
For slow tests that require LLM inference:
40+
41+
1. **Install optillm**: `pip install optillm`
42+
2. **Start server**: `OPTILLM_API_KEY=optillm optillm --model google/gemma-3-270m-it --port 8000`
43+
3. **Set environment**: `export OPTILLM_API_KEY=optillm OPENAI_API_KEY=optillm`
44+
4. **Run tests**: `pytest tests/integration/ -m "slow"`
45+
46+
## Configuration
47+
48+
All integration tests use:
49+
- **0 retries** for fast failure
50+
- **120 second timeout** per LLM call
51+
- **In-memory database** for speed
52+
- **Small iteration counts** (1-8 iterations) for CI compatibility
53+
54+
## CI Behavior
55+
56+
GitHub Actions will:
57+
- Run **fast tests only** (`-m "not slow"`)
58+
- Complete in <30 seconds
59+
- Validate core functionality without requiring model downloads
60+
- Skip all tests marked with `@pytest.mark.slow`

tests/integration/test_smoke.py

Lines changed: 44 additions & 100 deletions
Original file line numberDiff line numberDiff line change
@@ -9,98 +9,20 @@
99

1010
from openevolve import run_evolution, evolve_function, evolve_code
1111
from openevolve.config import Config, LLMModelConfig
12-
from openevolve.controller import OpenEvolve
13-
import sys
14-
import os
15-
sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..'))
16-
from test_utils import get_evolution_test_program, get_evolution_test_evaluator
17-
18-
19-
def get_mock_config() -> Config:
20-
"""Get config with mock/fast settings for smoke tests"""
21-
config = Config()
22-
config.max_iterations = 1
23-
config.checkpoint_interval = 50
24-
config.database.in_memory = True
25-
config.evaluator.cascade_evaluation = False
26-
config.evaluator.parallel_evaluations = 1
27-
config.evaluator.timeout = 5 # Very short timeout
28-
29-
# Use empty models list - will trigger validation but won't try to make LLM calls
30-
config.llm.timeout = 5
31-
config.llm.retries = 0
32-
config.llm.models = []
33-
34-
return config
3512

3613

3714
class TestSmoke:
3815
"""Fast smoke tests for CI"""
3916

40-
def test_controller_initialization(self, test_program_file, test_evaluator_file):
41-
"""Test that OpenEvolve controller can be initialized"""
42-
config = get_mock_config()
43-
44-
controller = OpenEvolve(
45-
initial_program_path=str(test_program_file),
46-
evaluation_file=str(test_evaluator_file),
47-
config=config,
48-
output_dir=tempfile.mkdtemp()
49-
)
50-
51-
# Test basic initialization
52-
assert controller is not None
53-
assert controller.database is not None
54-
assert controller.evaluator is not None
55-
assert len(controller.database.programs) == 1 # Initial program loaded
56-
57-
def test_database_operations(self, test_program_file, test_evaluator_file):
58-
"""Test database operations work correctly"""
59-
config = get_mock_config()
60-
61-
controller = OpenEvolve(
62-
initial_program_path=str(test_program_file),
63-
evaluation_file=str(test_evaluator_file),
64-
config=config,
65-
output_dir=tempfile.mkdtemp()
66-
)
67-
68-
# Test database functionality
69-
initial_count = len(controller.database.programs)
70-
assert initial_count == 1
71-
72-
# Test program retrieval
73-
program_ids = list(controller.database.programs.keys())
74-
assert len(program_ids) == 1
75-
76-
first_program = controller.database.get(program_ids[0])
77-
assert first_program is not None
78-
assert hasattr(first_program, 'code')
79-
assert hasattr(first_program, 'metrics')
80-
81-
def test_evaluator_works(self, test_program_file, test_evaluator_file):
82-
"""Test that evaluator can evaluate the initial program"""
83-
config = get_mock_config()
84-
85-
controller = OpenEvolve(
86-
initial_program_path=str(test_program_file),
87-
evaluation_file=str(test_evaluator_file),
88-
config=config,
89-
output_dir=tempfile.mkdtemp()
90-
)
91-
92-
# The initial program should have been evaluated during initialization
93-
programs = list(controller.database.programs.values())
94-
initial_program = programs[0]
95-
96-
assert initial_program.metrics is not None
97-
assert 'score' in initial_program.metrics
98-
assert 'combined_score' in initial_program.metrics
99-
10017
def test_library_api_validation(self):
10118
"""Test library API gives proper error messages when not configured"""
10219
with tempfile.NamedTemporaryFile(mode='w', suffix='.py', delete=False) as f:
103-
f.write(get_evolution_test_program())
20+
f.write("""
21+
# EVOLVE-BLOCK-START
22+
def solve(x):
23+
return x * 2
24+
# EVOLVE-BLOCK-END
25+
""")
10426
program_file = f.name
10527

10628
def simple_evaluator(path):
@@ -132,20 +54,42 @@ def test_config_validation(self):
13254
assert config.database.in_memory is True
13355
assert config.llm.retries >= 0
13456

57+
def test_llm_config_creation(self):
58+
"""Test that LLM configuration can be created properly"""
59+
config = Config()
60+
61+
# Test adding a model configuration
62+
config.llm.models = [
63+
LLMModelConfig(
64+
name="test-model",
65+
api_key="test-key",
66+
api_base="http://localhost:8000/v1",
67+
weight=1.0,
68+
timeout=60,
69+
retries=0
70+
)
71+
]
72+
73+
assert len(config.llm.models) == 1
74+
assert config.llm.models[0].name == "test-model"
75+
assert config.llm.models[0].retries == 0
13576

136-
@pytest.fixture
137-
def test_program_file():
138-
"""Create a temporary test program file"""
139-
with tempfile.NamedTemporaryFile(mode='w', suffix='.py', delete=False) as f:
140-
f.write(get_evolution_test_program())
141-
yield Path(f.name)
142-
Path(f.name).unlink()
143-
144-
145-
@pytest.fixture
146-
def test_evaluator_file():
147-
"""Create a temporary test evaluator file"""
148-
with tempfile.NamedTemporaryFile(mode='w', suffix='.py', delete=False) as f:
149-
f.write(get_evolution_test_evaluator())
150-
yield Path(f.name)
151-
Path(f.name).unlink()
77+
def test_evolution_result_structure(self):
78+
"""Test that EvolutionResult has the expected structure"""
79+
from openevolve.api import EvolutionResult
80+
from openevolve.database import Program
81+
82+
# Test creating an EvolutionResult
83+
result = EvolutionResult(
84+
best_program=None,
85+
best_score=0.85,
86+
best_code="def test(): pass",
87+
metrics={"accuracy": 0.85, "speed": 100},
88+
output_dir="/tmp/test"
89+
)
90+
91+
assert result.best_score == 0.85
92+
assert result.best_code == "def test(): pass"
93+
assert result.metrics["accuracy"] == 0.85
94+
assert result.output_dir == "/tmp/test"
95+
assert "0.8500" in str(result) # Test __repr__

0 commit comments

Comments
 (0)