178 lines
5.6 KiB
Python
178 lines
5.6 KiB
Python
"""
|
|
Tests for the Candles module.
|
|
|
|
Note: The candle data fetching has been moved to EDM (Exchange Data Manager).
|
|
These tests use mocked EDM responses to avoid requiring a running EDM server.
|
|
Functions like ts_of_n_minutes_ago and timeframe_to_minutes are tested in
|
|
test_shared_utilities.py.
|
|
"""
|
|
import datetime as dt
|
|
import pytest
|
|
import pandas as pd
|
|
from unittest.mock import MagicMock, patch
|
|
|
|
from candles import Candles
|
|
from Configuration import Configuration
|
|
from DataCache_v3 import DataCache
|
|
|
|
|
|
@pytest.fixture
|
|
def mock_edm_client():
|
|
"""Create a mock EDM client."""
|
|
mock = MagicMock()
|
|
# Mock get_candles_sync to return sample candle data
|
|
sample_candles = pd.DataFrame({
|
|
'time': [1700000000000, 1700000060000, 1700000120000, 1700000180000, 1700000240000],
|
|
'open': [100.0, 101.0, 102.0, 101.5, 103.0],
|
|
'high': [102.0, 103.0, 104.0, 103.5, 105.0],
|
|
'low': [99.0, 100.0, 101.0, 100.5, 102.0],
|
|
'close': [101.0, 102.0, 101.5, 103.0, 104.0],
|
|
'volume': [1000.0, 1200.0, 800.0, 1500.0, 900.0]
|
|
})
|
|
mock.get_candles_sync.return_value = sample_candles
|
|
return mock
|
|
|
|
|
|
@pytest.fixture
|
|
def mock_exchanges():
|
|
"""Create mock exchange interface."""
|
|
return MagicMock()
|
|
|
|
|
|
@pytest.fixture
|
|
def mock_users():
|
|
"""Create mock users object."""
|
|
mock = MagicMock()
|
|
mock.get_chart_view.return_value = {'timeframe': '1m', 'exchange': 'binance', 'market': 'BTC/USDT'}
|
|
return mock
|
|
|
|
|
|
@pytest.fixture
|
|
def data_cache():
|
|
"""Create a fresh DataCache."""
|
|
return DataCache()
|
|
|
|
|
|
@pytest.fixture
|
|
def config():
|
|
"""Create a Configuration instance."""
|
|
return Configuration()
|
|
|
|
|
|
@pytest.fixture
|
|
def candles(mock_exchanges, mock_users, data_cache, config, mock_edm_client):
|
|
"""Create a Candles instance with mocked dependencies."""
|
|
return Candles(
|
|
exchanges=mock_exchanges,
|
|
users=mock_users,
|
|
datacache=data_cache,
|
|
config=config,
|
|
edm_client=mock_edm_client
|
|
)
|
|
|
|
|
|
class TestCandles:
|
|
"""Tests for the Candles class."""
|
|
|
|
def test_candles_creation(self, candles):
|
|
"""Test that Candles object can be created."""
|
|
assert candles is not None
|
|
|
|
def test_get_last_n_candles(self, candles, mock_edm_client):
|
|
"""Test getting last N candles."""
|
|
result = candles.get_last_n_candles(
|
|
num_candles=5,
|
|
asset='BTC/USDT',
|
|
timeframe='1m',
|
|
exchange='binance',
|
|
user_name='test_user'
|
|
)
|
|
|
|
assert result is not None
|
|
assert isinstance(result, pd.DataFrame)
|
|
assert len(result) == 5
|
|
assert 'open' in result.columns
|
|
assert 'high' in result.columns
|
|
assert 'low' in result.columns
|
|
assert 'close' in result.columns
|
|
assert 'volume' in result.columns
|
|
|
|
def test_get_last_n_candles_caps_at_1000(self, candles, mock_edm_client):
|
|
"""Test that requests for more than 1000 candles are capped."""
|
|
candles.get_last_n_candles(
|
|
num_candles=2000,
|
|
asset='BTC/USDT',
|
|
timeframe='1m',
|
|
exchange='binance',
|
|
user_name='test_user'
|
|
)
|
|
|
|
# Check that EDM was called with capped limit
|
|
call_args = mock_edm_client.get_candles_sync.call_args
|
|
assert call_args.kwargs.get('limit', call_args[1].get('limit')) == 1000
|
|
|
|
def test_candles_raises_without_edm(self, mock_exchanges, mock_users, data_cache, config):
|
|
"""Test that Candles raises error when EDM is not available."""
|
|
candles_no_edm = Candles(
|
|
exchanges=mock_exchanges,
|
|
users=mock_users,
|
|
datacache=data_cache,
|
|
config=config,
|
|
edm_client=None
|
|
)
|
|
|
|
with pytest.raises(RuntimeError, match="EDM client not initialized"):
|
|
candles_no_edm.get_last_n_candles(
|
|
num_candles=5,
|
|
asset='BTC/USDT',
|
|
timeframe='1m',
|
|
exchange='binance',
|
|
user_name='test_user'
|
|
)
|
|
|
|
def test_get_latest_values(self, candles, mock_edm_client):
|
|
"""Test getting latest values for a specific field."""
|
|
result = candles.get_latest_values(
|
|
value_name='close',
|
|
symbol='BTC/USDT',
|
|
timeframe='1m',
|
|
exchange='binance',
|
|
num_record=5,
|
|
user_name='test_user'
|
|
)
|
|
|
|
assert result is not None
|
|
# Should return series/list of close values
|
|
assert len(result) <= 5
|
|
|
|
def test_max_records_from_config(self, candles, config):
|
|
"""Test that max_records is loaded from config."""
|
|
expected_max = config.get_setting('max_data_loaded')
|
|
assert candles.max_records == expected_max
|
|
|
|
def test_candle_cache_created(self, candles, data_cache):
|
|
"""Test that candle cache is created on initialization."""
|
|
# The cache should exist
|
|
assert 'candles' in data_cache.caches
|
|
|
|
|
|
class TestCandlesIntegration:
|
|
"""Integration-style tests that verify EDM client interaction."""
|
|
|
|
def test_edm_client_called_correctly(self, candles, mock_edm_client):
|
|
"""Test that EDM client is called with correct parameters."""
|
|
candles.get_last_n_candles(
|
|
num_candles=10,
|
|
asset='ETH/USDT',
|
|
timeframe='5m',
|
|
exchange='binance',
|
|
user_name='test_user'
|
|
)
|
|
|
|
mock_edm_client.get_candles_sync.assert_called_once()
|
|
call_kwargs = mock_edm_client.get_candles_sync.call_args.kwargs
|
|
assert call_kwargs['symbol'] == 'ETH/USDT'
|
|
assert call_kwargs['timeframe'] == '5m'
|
|
assert call_kwargs['exchange'] == 'binance'
|
|
assert call_kwargs['limit'] == 10
|