Add parametrized tests

This commit is contained in:
Matthias 2019-02-24 20:08:27 +01:00
parent 5c18346cd5
commit 31be4d2454

View File

@ -12,7 +12,7 @@ import pytest
from pandas import DataFrame from pandas import DataFrame
from freqtrade import DependencyException, OperationalException, TemporaryError from freqtrade import DependencyException, OperationalException, TemporaryError
from freqtrade.exchange import Exchange, Kraken from freqtrade.exchange import Exchange, Kraken, Binance
from freqtrade.exchange.exchange import API_RETRY_COUNT from freqtrade.exchange.exchange import API_RETRY_COUNT
from freqtrade.tests.conftest import get_patched_exchange, log_has, log_has_re from freqtrade.tests.conftest import get_patched_exchange, log_has, log_has_re
from freqtrade.resolvers.exchange_resolver import ExchangeResolver from freqtrade.resolvers.exchange_resolver import ExchangeResolver
@ -127,6 +127,15 @@ def test_exchange_resolver(default_conf, mocker, caplog):
exchange = ExchangeResolver('Kraken', default_conf).exchange exchange = ExchangeResolver('Kraken', default_conf).exchange
assert isinstance(exchange, Exchange) assert isinstance(exchange, Exchange)
assert isinstance(exchange, Kraken) assert isinstance(exchange, Kraken)
assert not isinstance(exchange, Binance)
assert not log_has_re(r"No .* specific subclass found. Using the generic class instead.",
caplog.record_tuples)
exchange = ExchangeResolver('Binance', default_conf).exchange
assert isinstance(exchange, Exchange)
assert isinstance(exchange, Binance)
assert not isinstance(exchange, Kraken)
assert not log_has_re(r"No .* specific subclass found. Using the generic class instead.", assert not log_has_re(r"No .* specific subclass found. Using the generic class instead.",
caplog.record_tuples) caplog.record_tuples)
@ -452,9 +461,10 @@ def test_exchange_has(default_conf, mocker):
("buy"), ("buy"),
("sell") ("sell")
]) ])
def test_dry_run_order(default_conf, mocker, side): @pytest.mark.parametrize("exchange_name", EXCHANGES)
def test_dry_run_order(default_conf, mocker, side, exchange_name):
default_conf['dry_run'] = True default_conf['dry_run'] = True
exchange = get_patched_exchange(mocker, default_conf) exchange = get_patched_exchange(mocker, default_conf, id=exchange_name)
order = exchange.dry_run_order( order = exchange.dry_run_order(
pair='ETH/BTC', ordertype='limit', side=side, amount=1, rate=200) pair='ETH/BTC', ordertype='limit', side=side, amount=1, rate=200)
@ -471,7 +481,8 @@ def test_dry_run_order(default_conf, mocker, side):
("limit", 200), ("limit", 200),
("stop_loss_limit", 200) ("stop_loss_limit", 200)
]) ])
def test_create_order(default_conf, mocker, side, ordertype, rate): @pytest.mark.parametrize("exchange_name", EXCHANGES)
def test_create_order(default_conf, mocker, side, ordertype, rate, exchange_name):
api_mock = MagicMock() api_mock = MagicMock()
order_id = 'test_prod_{}_{}'.format(side, randint(0, 10 ** 6)) order_id = 'test_prod_{}_{}'.format(side, randint(0, 10 ** 6))
api_mock.create_order = MagicMock(return_value={ api_mock.create_order = MagicMock(return_value={
@ -483,7 +494,7 @@ def test_create_order(default_conf, mocker, side, ordertype, rate):
default_conf['dry_run'] = False default_conf['dry_run'] = False
mocker.patch('freqtrade.exchange.Exchange.symbol_amount_prec', lambda s, x, y: y) mocker.patch('freqtrade.exchange.Exchange.symbol_amount_prec', lambda s, x, y: y)
mocker.patch('freqtrade.exchange.Exchange.symbol_price_prec', lambda s, x, y: y) mocker.patch('freqtrade.exchange.Exchange.symbol_price_prec', lambda s, x, y: y)
exchange = get_patched_exchange(mocker, default_conf, api_mock) exchange = get_patched_exchange(mocker, default_conf, api_mock, id=exchange_name)
order = exchange.create_order( order = exchange.create_order(
pair='ETH/BTC', ordertype=ordertype, side=side, amount=1, rate=200) pair='ETH/BTC', ordertype=ordertype, side=side, amount=1, rate=200)
@ -508,7 +519,8 @@ def test_buy_dry_run(default_conf, mocker):
assert 'dry_run_buy_' in order['id'] assert 'dry_run_buy_' in order['id']
def test_buy_prod(default_conf, mocker): @pytest.mark.parametrize("exchange_name", EXCHANGES)
def test_buy_prod(default_conf, mocker, exchange_name):
api_mock = MagicMock() api_mock = MagicMock()
order_id = 'test_prod_buy_{}'.format(randint(0, 10 ** 6)) order_id = 'test_prod_buy_{}'.format(randint(0, 10 ** 6))
order_type = 'market' order_type = 'market'
@ -522,7 +534,7 @@ def test_buy_prod(default_conf, mocker):
default_conf['dry_run'] = False default_conf['dry_run'] = False
mocker.patch('freqtrade.exchange.Exchange.symbol_amount_prec', lambda s, x, y: y) mocker.patch('freqtrade.exchange.Exchange.symbol_amount_prec', lambda s, x, y: y)
mocker.patch('freqtrade.exchange.Exchange.symbol_price_prec', lambda s, x, y: y) mocker.patch('freqtrade.exchange.Exchange.symbol_price_prec', lambda s, x, y: y)
exchange = get_patched_exchange(mocker, default_conf, api_mock) exchange = get_patched_exchange(mocker, default_conf, api_mock, id=exchange_name)
order = exchange.buy(pair='ETH/BTC', ordertype=order_type, order = exchange.buy(pair='ETH/BTC', ordertype=order_type,
amount=1, rate=200, time_in_force=time_in_force) amount=1, rate=200, time_in_force=time_in_force)
@ -553,25 +565,25 @@ def test_buy_prod(default_conf, mocker):
# test exception handling # test exception handling
with pytest.raises(DependencyException): with pytest.raises(DependencyException):
api_mock.create_order = MagicMock(side_effect=ccxt.InsufficientFunds) api_mock.create_order = MagicMock(side_effect=ccxt.InsufficientFunds)
exchange = get_patched_exchange(mocker, default_conf, api_mock) exchange = get_patched_exchange(mocker, default_conf, api_mock, id=exchange_name)
exchange.buy(pair='ETH/BTC', ordertype=order_type, exchange.buy(pair='ETH/BTC', ordertype=order_type,
amount=1, rate=200, time_in_force=time_in_force) amount=1, rate=200, time_in_force=time_in_force)
with pytest.raises(DependencyException): with pytest.raises(DependencyException):
api_mock.create_order = MagicMock(side_effect=ccxt.InvalidOrder) api_mock.create_order = MagicMock(side_effect=ccxt.InvalidOrder)
exchange = get_patched_exchange(mocker, default_conf, api_mock) exchange = get_patched_exchange(mocker, default_conf, api_mock, id=exchange_name)
exchange.buy(pair='ETH/BTC', ordertype=order_type, exchange.buy(pair='ETH/BTC', ordertype=order_type,
amount=1, rate=200, time_in_force=time_in_force) amount=1, rate=200, time_in_force=time_in_force)
with pytest.raises(TemporaryError): with pytest.raises(TemporaryError):
api_mock.create_order = MagicMock(side_effect=ccxt.NetworkError) api_mock.create_order = MagicMock(side_effect=ccxt.NetworkError)
exchange = get_patched_exchange(mocker, default_conf, api_mock) exchange = get_patched_exchange(mocker, default_conf, api_mock, id=exchange_name)
exchange.buy(pair='ETH/BTC', ordertype=order_type, exchange.buy(pair='ETH/BTC', ordertype=order_type,
amount=1, rate=200, time_in_force=time_in_force) amount=1, rate=200, time_in_force=time_in_force)
with pytest.raises(OperationalException): with pytest.raises(OperationalException):
api_mock.create_order = MagicMock(side_effect=ccxt.BaseError) api_mock.create_order = MagicMock(side_effect=ccxt.BaseError)
exchange = get_patched_exchange(mocker, default_conf, api_mock) exchange = get_patched_exchange(mocker, default_conf, api_mock, id=exchange_name)
exchange.buy(pair='ETH/BTC', ordertype=order_type, exchange.buy(pair='ETH/BTC', ordertype=order_type,
amount=1, rate=200, time_in_force=time_in_force) amount=1, rate=200, time_in_force=time_in_force)
@ -676,7 +688,8 @@ def test_sell_dry_run(default_conf, mocker):
assert 'dry_run_sell_' in order['id'] assert 'dry_run_sell_' in order['id']
def test_sell_prod(default_conf, mocker): @pytest.mark.parametrize("exchange_name", EXCHANGES)
def test_sell_prod(default_conf, mocker, exchange_name):
api_mock = MagicMock() api_mock = MagicMock()
order_id = 'test_prod_sell_{}'.format(randint(0, 10 ** 6)) order_id = 'test_prod_sell_{}'.format(randint(0, 10 ** 6))
order_type = 'market' order_type = 'market'
@ -690,7 +703,7 @@ def test_sell_prod(default_conf, mocker):
mocker.patch('freqtrade.exchange.Exchange.symbol_amount_prec', lambda s, x, y: y) mocker.patch('freqtrade.exchange.Exchange.symbol_amount_prec', lambda s, x, y: y)
mocker.patch('freqtrade.exchange.Exchange.symbol_price_prec', lambda s, x, y: y) mocker.patch('freqtrade.exchange.Exchange.symbol_price_prec', lambda s, x, y: y)
exchange = get_patched_exchange(mocker, default_conf, api_mock) exchange = get_patched_exchange(mocker, default_conf, api_mock, id=exchange_name)
order = exchange.sell(pair='ETH/BTC', ordertype=order_type, amount=1, rate=200) order = exchange.sell(pair='ETH/BTC', ordertype=order_type, amount=1, rate=200)
@ -715,22 +728,22 @@ def test_sell_prod(default_conf, mocker):
# test exception handling # test exception handling
with pytest.raises(DependencyException): with pytest.raises(DependencyException):
api_mock.create_order = MagicMock(side_effect=ccxt.InsufficientFunds) api_mock.create_order = MagicMock(side_effect=ccxt.InsufficientFunds)
exchange = get_patched_exchange(mocker, default_conf, api_mock) exchange = get_patched_exchange(mocker, default_conf, api_mock, id=exchange_name)
exchange.sell(pair='ETH/BTC', ordertype=order_type, amount=1, rate=200) exchange.sell(pair='ETH/BTC', ordertype=order_type, amount=1, rate=200)
with pytest.raises(DependencyException): with pytest.raises(DependencyException):
api_mock.create_order = MagicMock(side_effect=ccxt.InvalidOrder) api_mock.create_order = MagicMock(side_effect=ccxt.InvalidOrder)
exchange = get_patched_exchange(mocker, default_conf, api_mock) exchange = get_patched_exchange(mocker, default_conf, api_mock, id=exchange_name)
exchange.sell(pair='ETH/BTC', ordertype=order_type, amount=1, rate=200) exchange.sell(pair='ETH/BTC', ordertype=order_type, amount=1, rate=200)
with pytest.raises(TemporaryError): with pytest.raises(TemporaryError):
api_mock.create_order = MagicMock(side_effect=ccxt.NetworkError) api_mock.create_order = MagicMock(side_effect=ccxt.NetworkError)
exchange = get_patched_exchange(mocker, default_conf, api_mock) exchange = get_patched_exchange(mocker, default_conf, api_mock, id=exchange_name)
exchange.sell(pair='ETH/BTC', ordertype=order_type, amount=1, rate=200) exchange.sell(pair='ETH/BTC', ordertype=order_type, amount=1, rate=200)
with pytest.raises(OperationalException): with pytest.raises(OperationalException):
api_mock.create_order = MagicMock(side_effect=ccxt.BaseError) api_mock.create_order = MagicMock(side_effect=ccxt.BaseError)
exchange = get_patched_exchange(mocker, default_conf, api_mock) exchange = get_patched_exchange(mocker, default_conf, api_mock, id=exchange_name)
exchange.sell(pair='ETH/BTC', ordertype=order_type, amount=1, rate=200) exchange.sell(pair='ETH/BTC', ordertype=order_type, amount=1, rate=200)
@ -741,23 +754,24 @@ def test_get_balance_dry_run(default_conf, mocker):
assert exchange.get_balance(currency='BTC') == 999.9 assert exchange.get_balance(currency='BTC') == 999.9
def test_get_balance_prod(default_conf, mocker): @pytest.mark.parametrize("exchange_name", EXCHANGES)
def test_get_balance_prod(default_conf, mocker, exchange_name):
api_mock = MagicMock() api_mock = MagicMock()
api_mock.fetch_balance = MagicMock(return_value={'BTC': {'free': 123.4}}) api_mock.fetch_balance = MagicMock(return_value={'BTC': {'free': 123.4}})
default_conf['dry_run'] = False default_conf['dry_run'] = False
exchange = get_patched_exchange(mocker, default_conf, api_mock) exchange = get_patched_exchange(mocker, default_conf, api_mock, id=exchange_name)
assert exchange.get_balance(currency='BTC') == 123.4 assert exchange.get_balance(currency='BTC') == 123.4
with pytest.raises(OperationalException): with pytest.raises(OperationalException):
api_mock.fetch_balance = MagicMock(side_effect=ccxt.BaseError) api_mock.fetch_balance = MagicMock(side_effect=ccxt.BaseError)
exchange = get_patched_exchange(mocker, default_conf, api_mock) exchange = get_patched_exchange(mocker, default_conf, api_mock, id=exchange_name)
exchange.get_balance(currency='BTC') exchange.get_balance(currency='BTC')
with pytest.raises(TemporaryError, match=r'.*balance due to malformed exchange response:.*'): with pytest.raises(TemporaryError, match=r'.*balance due to malformed exchange response:.*'):
exchange = get_patched_exchange(mocker, default_conf, api_mock) exchange = get_patched_exchange(mocker, default_conf, api_mock, id=exchange_name)
mocker.patch('freqtrade.exchange.Exchange.get_balances', MagicMock(return_value={})) mocker.patch('freqtrade.exchange.Exchange.get_balances', MagicMock(return_value={}))
exchange.get_balance(currency='BTC') exchange.get_balance(currency='BTC')
@ -971,7 +985,8 @@ def test_refresh_latest_ohlcv(mocker, default_conf, caplog) -> None:
@pytest.mark.asyncio @pytest.mark.asyncio
async def test__async_get_candle_history(default_conf, mocker, caplog): @pytest.mark.parametrize("exchange_name", EXCHANGES)
async def test__async_get_candle_history(default_conf, mocker, caplog, exchange_name):
tick = [ tick = [
[ [
arrow.utcnow().timestamp * 1000, # unix timestamp ms arrow.utcnow().timestamp * 1000, # unix timestamp ms
@ -984,11 +999,10 @@ async def test__async_get_candle_history(default_conf, mocker, caplog):
] ]
caplog.set_level(logging.DEBUG) caplog.set_level(logging.DEBUG)
exchange = get_patched_exchange(mocker, default_conf) exchange = get_patched_exchange(mocker, default_conf, id=exchange_name)
# Monkey-patch async function # Monkey-patch async function
exchange._api_async.fetch_ohlcv = get_mock_coro(tick) exchange._api_async.fetch_ohlcv = get_mock_coro(tick)
exchange = Exchange(default_conf)
pair = 'ETH/BTC' pair = 'ETH/BTC'
res = await exchange._async_get_candle_history(pair, "5m") res = await exchange._async_get_candle_history(pair, "5m")
assert type(res) is tuple assert type(res) is tuple
@ -1007,7 +1021,7 @@ async def test__async_get_candle_history(default_conf, mocker, caplog):
api_mock = MagicMock() api_mock = MagicMock()
with pytest.raises(OperationalException, match=r'Could not fetch ticker data*'): with pytest.raises(OperationalException, match=r'Could not fetch ticker data*'):
api_mock.fetch_ohlcv = MagicMock(side_effect=ccxt.BaseError) api_mock.fetch_ohlcv = MagicMock(side_effect=ccxt.BaseError)
exchange = get_patched_exchange(mocker, default_conf, api_mock) exchange = get_patched_exchange(mocker, default_conf, api_mock, id=exchange_name)
await exchange._async_get_candle_history(pair, "5m", await exchange._async_get_candle_history(pair, "5m",
(arrow.utcnow().timestamp - 2000) * 1000) (arrow.utcnow().timestamp - 2000) * 1000)