orderflow_backtest/tests/test_main_visualization.py

109 lines
3.9 KiB
Python
Raw Normal View History

"""Tests for main.py visualization workflow."""
import sys
import sqlite3
import tempfile
from pathlib import Path
from unittest.mock import patch, MagicMock
sys.path.append(str(Path(__file__).resolve().parents[1]))
# Mock typer to avoid import issues in tests
sys.modules['typer'] = MagicMock()
from storage import Storage
from strategies import DefaultStrategy
from visualizer import Visualizer
def test_main_workflow_separation():
"""Test that main.py workflow properly separates strategy and visualization."""
with tempfile.NamedTemporaryFile(suffix=".db", delete=False) as tmp_file:
db_path = Path(tmp_file.name)
try:
# Create minimal test database
with sqlite3.connect(str(db_path)) as conn:
conn.execute("""
CREATE TABLE book (
id INTEGER PRIMARY KEY,
bids TEXT NOT NULL,
asks TEXT NOT NULL,
timestamp INTEGER NOT NULL
)
""")
conn.execute("""
CREATE TABLE trades (
id INTEGER PRIMARY KEY,
trade_id REAL NOT NULL,
price REAL NOT NULL,
size REAL NOT NULL,
side TEXT NOT NULL,
timestamp INTEGER NOT NULL
)
""")
# Insert minimal test data
bids = "[(50000.0, 10.0, 0, 1)]"
asks = "[(50001.0, 5.0, 0, 1)]"
conn.execute("INSERT INTO book (id, bids, asks, timestamp) VALUES (?, ?, ?, ?)",
(1, bids, asks, 1000))
conn.execute("INSERT INTO trades (id, trade_id, price, size, side, timestamp) VALUES (?, ?, ?, ?, ?, ?)",
(1, 1.0, 50000.0, 3.0, "buy", 1000))
conn.commit()
# Test the new main.py workflow
storage = Storage("BTC-USDT")
strategy = DefaultStrategy("BTC-USDT") # No visualization parameter
# Mock visualizer to avoid GUI issues in tests
with patch('matplotlib.pyplot.subplots') as mock_subplots:
mock_fig = type('MockFig', (), {'canvas': type('MockCanvas', (), {'draw_idle': lambda: None})()})()
mock_axes = [type('MockAx', (), {'clear': lambda: None})() for _ in range(4)]
mock_subplots.return_value = (mock_fig, tuple(mock_axes))
visualizer = Visualizer(window_seconds=60, max_bars=500)
# This simulates the new main.py workflow
strategy.set_db_path(db_path)
visualizer.set_db_path(db_path)
storage.build_booktick_from_db(db_path, None)
# Strategy analyzes metrics (no visualization)
strategy.on_booktick(storage.book)
# Verify strategy has database path but no visualizer
assert strategy._db_path == db_path
assert not hasattr(strategy, 'visualizer') or strategy.visualizer is None
# Verify visualizer can access database
assert visualizer._db_path == db_path
# Verify visualizer can load metrics
metrics = visualizer._load_stored_metrics(1000, 1000)
assert len(metrics) == 1
# Test visualization update (should work independently)
with patch.object(visualizer, '_draw') as mock_draw:
visualizer.update_from_book(storage.book)
mock_draw.assert_called_once()
finally:
db_path.unlink(missing_ok=True)
def test_strategy_has_no_visualization_dependency():
"""Test that strategy no longer depends on visualization."""
strategy = DefaultStrategy("BTC-USDT")
# Strategy should not have visualizer attribute
assert not hasattr(strategy, 'visualizer') or strategy.visualizer is None
# Strategy should work without any visualization setup
from models import Book
book = Book()
# Should not raise any errors
strategy.on_booktick(book)