This document describes how to run tests for the Hybrid Verification Framework and what they verify.
- Python 3.7 or higher
- All framework dependencies installed
- Protocol configurations available (at minimum,
examples/raft/config/raft.yaml)
# From project root
python -m pytest tests/
# Or using unittest
python tests/test_framework_integration.py
# With verbose output
python tests/test_framework_integration.py -v# Test template loader only
python -m pytest tests/test_framework_integration.py::TestTemplateLoader -v
# Test code generation only
python -m pytest tests/test_framework_integration.py::TestCodeGeneration -v
# Test counterexample conversion only
python -m pytest tests/test_framework_integration.py::TestCounterexampleConversion -v# Test specific method
python -m pytest tests/test_framework_integration.py::TestTemplateLoader::test_load_protocol_config -vTests are organized in tests/test_framework_integration.py with the following test classes:
- TestTemplateLoader - Template and configuration loading
- TestCodeGeneration - Code generation tools
- TestCounterexampleConversion - Counterexample conversion
- TestPropertyAnalysis - Property analysis and synthesis
- TestProtocolAwareness - Protocol-specific functionality
- TestFrameworkScripts - Framework script integration
- TestDomainAgnosticFeatures - Generic/domain-agnostic features
- TestEndToEnd - End-to-end workflow tests
Test data is stored in tests/test_data/:
- Sample counterexamples
- Test configuration files
- Expected outputs
TestTemplateLoader verifies:
- ✅ Listing available domain templates
- ✅ Listing available property templates
- ✅ Listing available protocol configurations
- ✅ Loading domain templates
- ✅ Loading property templates
- ✅ Loading protocol configurations
- ✅ Expanding property templates with variables
Example:
def test_load_protocol_config(self):
"""Test loading a protocol configuration"""
config = self.loader.load_protocol_config('raft')
self.assertIsInstance(config, dict)
self.assertIn('protocol', config)
self.assertIn('properties', config)
self.assertEqual(config['protocol']['name'], 'Raft')TestCodeGeneration verifies:
- ✅ Property generation (JSON, KLEE C, TLA+)
- ✅ TLA+ specification generation
- ✅ KLEE test harness generation
- ✅ Generated files contain expected content
Example:
def test_generate_properties(self):
"""Test property generation"""
generator = PropertyGenerator()
result = generator.generate_properties('raft')
self.assertIn('json', result)
self.assertIn('klee', result)
self.assertIn('tla', result)
self.assertTrue(Path(result['json']).exists())TestCounterexampleConversion verifies:
- ✅ KLEE to TLA+ conversion (generic mode)
- ✅ TLA+ to KLEE conversion (generic mode)
- ✅ Protocol-specific conversion
- ✅ Conversion with protocol configuration
Example:
def test_convert_klee_to_tla_generic(self):
"""Test KLEE to TLA+ conversion in generic mode"""
klee_cex = {
'counterexample_id': 'test_001',
'property': 'SafetyProperty',
'assertion': 'klee_assert(condition)',
'symbolic_values': {'num_rounds': 5}
}
result = convert_klee_to_tla(klee_cex)
self.assertEqual(result['source'], 'KLEE')
self.assertIn('tla_code', result)TestPropertyAnalysis verifies:
- ✅ Generic counterexample analysis
- ✅ Protocol-specific analysis
- ✅ Violation pattern identification
- ✅ Property synthesis
Example:
def test_analyze_counterexample_generic(self):
"""Test counterexample analysis in generic mode"""
cex_file = self.test_data_dir / 'test_cex.json'
# ... create test file ...
result = analyze_counterexample(str(cex_file))
self.assertGreater(result['total_count'], 0)
self.assertIn('analyses', result)TestProtocolAwareness verifies:
- ✅ Protocol configuration loading with all fields
- ✅ Protocol-specific counterexample conversion
- ✅ Protocol metadata validation
Example:
def test_protocol_config_loading(self):
"""Test loading protocol configuration with all required fields"""
config = self.loader.load_protocol_config('raft')
self.assertIn('protocol', config)
self.assertEqual(config['protocol']['name'], 'Raft')
self.assertIn('properties', config)
self.assertIn('state_variables', config)TestFrameworkScripts verifies:
- ✅ Counterexample converter accepts
--protocolparameter - ✅ Analyze counterexample accepts protocol parameter
- ✅ Script integration with protocol configuration
Example:
def test_counterexample_converter_protocol_param(self):
"""Test counterexample converter accepts --protocol parameter"""
result = convert_counterexamples(
klee_json_file=str(klee_file),
output_dir=str(output_dir),
protocol_name='raft'
)
self.assertEqual(result['protocol'], 'raft')TestDomainAgnosticFeatures verifies:
- ✅ Generic violation pattern matching
- ✅ Generic counterexample conversion (no protocol)
- ✅ Pattern-based property identification
Example:
def test_generic_violation_patterns(self):
"""Test generic violation pattern matching"""
cex = {
'assertion': 'klee_assert(entities <= 1)',
'message': 'Uniqueness property violated',
'property': 'UniquenessViolation'
}
violation = identify_property_violation(cex)
self.assertEqual(violation['violation_type'], 'Safety')
self.assertEqual(violation['pattern'], 'multiple_entities_same_context')TestEndToEnd verifies:
- ✅ Full workflow for Raft protocol
- ✅ Hybrid verification workflow
- ✅ Integration of all components
Example:
def test_full_workflow_raft(self):
"""Test full workflow for Raft protocol"""
# 1. Load protocol configuration
loader = TemplateLoader()
config = loader.load_protocol_config('raft')
# 2. Generate properties
prop_gen = PropertyGenerator()
prop_result = prop_gen.generate_properties('raft')
# 3. Generate TLA+ spec
tla_gen = TLASpecGenerator()
tla_file = tla_gen.generate_spec('raft')
# 4. Generate KLEE harness
klee_gen = KLEETestGenerator()
klee_file = klee_gen.generate_harness('raft')#!/usr/bin/env python3
import unittest
from pathlib import Path
import sys
sys.path.insert(0, str(Path(__file__).parent.parent))
class TestMyFeature(unittest.TestCase):
"""Test my feature"""
def setUp(self):
"""Set up test fixtures"""
self.test_data_dir = Path(__file__).parent / "test_data"
self.test_data_dir.mkdir(exist_ok=True)
def tearDown(self):
"""Clean up after tests"""
# Clean up if needed
pass
def test_my_feature(self):
"""Test my feature functionality"""
# Arrange
# Act
# Assert
pass-
Use descriptive test names:
def test_load_protocol_config_with_all_fields(self): """Test loading protocol configuration with all required fields"""
-
Test both success and failure cases:
def test_load_nonexistent_protocol(self): """Test loading non-existent protocol raises error""" with self.assertRaises(FileNotFoundError): self.loader.load_protocol_config('nonexistent')
-
Clean up test data:
def tearDown(self): import shutil if self.test_output_dir.exists(): shutil.rmtree(self.test_output_dir)
-
Use test data directory:
def setUp(self): self.test_data_dir = Path(__file__).parent / "test_data" self.test_data_dir.mkdir(exist_ok=True)
-
Test protocol-agnostic and protocol-specific:
def test_generic_conversion(self): """Test generic conversion without protocol""" result = convert_klee_to_tla(klee_cex) # ... def test_protocol_specific_conversion(self): """Test conversion with protocol configuration""" config = self.loader.load_protocol_config('raft') result = convert_klee_to_tla(klee_cex, config) # ...
Create test data files in tests/test_data/:
# Create test counterexample
cex_file = self.test_data_dir / 'test_cex.json'
with open(cex_file, 'w') as f:
json.dump({
'counterexamples': [{
'counterexample_id': 'test_001',
'property': 'SafetyProperty',
'assertion': 'klee_assert(condition)'
}]
}, f)Create .github/workflows/test.yml:
name: Tests
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set up Python
uses: actions/setup-python@v2
with:
python-version: '3.9'
- name: Install dependencies
run: |
pip install -r requirements.txt
- name: Run tests
run: |
python tests/test_framework_integration.py -vTo measure test coverage:
# Install coverage tool
pip install coverage
# Run tests with coverage
coverage run -m pytest tests/
# Generate coverage report
coverage report
# Generate HTML report
coverage html-
FileNotFoundError:
- Ensure test data files exist
- Check file paths are correct
-
ImportError:
- Ensure
sys.pathincludes project root - Check module names are correct
- Ensure
-
AssertionError:
- Check expected vs actual values
- Verify test data is correct
-
Protocol not found:
- Ensure
examples/raft/config/raft.yamlexists - Check protocol name spelling
- Ensure
# Add debug output
def test_my_feature(self):
result = my_function()
print(f"Result: {result}") # Debug output
self.assertIsNotNone(result)# Run with verbose output
python -m pytest tests/ -v -s
# Run with debugger
python -m pdb tests/test_framework_integration.py- API Documentation - API reference for tested components
- Usage Examples - Examples of framework usage