add more tests

This commit is contained in:
gcarq 2017-11-07 22:27:44 +01:00
parent 18eec0f4d4
commit 6ce6018bb7
3 changed files with 194 additions and 27 deletions

View File

@ -14,7 +14,7 @@ from freqtrade.misc import CONF_SCHEMA
def default_conf():
""" Returns validated configuration suitable for most tests """
configuration = {
"max_open_trades": 3,
"max_open_trades": 1,
"stake_currency": "BTC",
"stake_amount": 0.05,
"dry_run": True,

View File

@ -1,16 +1,101 @@
# pragma pylint: disable=missing-docstring
import copy
from unittest.mock import MagicMock, call
from unittest.mock import MagicMock
import pytest
import requests
from freqtrade.exchange import Exchanges
from freqtrade.main import create_trade, handle_trade, close_trade_if_fulfilled, init, \
get_target_bid
get_target_bid, _process
from freqtrade.misc import get_state, State
from freqtrade.persistence import Trade
def test_process_trade_creation(default_conf, ticker, mocker):
mocker.patch.dict('freqtrade.main._CONF', default_conf)
mocker.patch.multiple('freqtrade.main.telegram', init=MagicMock(), send_msg=MagicMock())
mocker.patch('freqtrade.main.get_buy_signal', side_effect=lambda _: True)
mocker.patch.multiple('freqtrade.main.exchange',
validate_pairs=MagicMock(),
get_ticker=ticker,
buy=MagicMock(return_value='mocked_limit_buy'))
init(default_conf, 'sqlite://')
trades = Trade.query.filter(Trade.is_open.is_(True)).all()
assert len(trades) == 0
result = _process()
assert result is True
trades = Trade.query.filter(Trade.is_open.is_(True)).all()
assert len(trades) == 1
trade = trades[0]
assert trade is not None
assert trade.stake_amount == default_conf['stake_amount']
assert trade.is_open
assert trade.open_date is not None
assert trade.exchange == Exchanges.BITTREX.name
assert trade.open_rate == 0.072661
assert trade.amount == 0.6864067381401302
def test_process_exchange_failures(default_conf, ticker, mocker):
mocker.patch.dict('freqtrade.main._CONF', default_conf)
mocker.patch.multiple('freqtrade.main.telegram', init=MagicMock(), send_msg=MagicMock())
mocker.patch('freqtrade.main.get_buy_signal', side_effect=lambda _: True)
sleep_mock = mocker.patch('time.sleep', side_effect=lambda _: None)
mocker.patch.multiple('freqtrade.main.exchange',
validate_pairs=MagicMock(),
get_ticker=ticker,
buy=MagicMock(side_effect=requests.exceptions.RequestException))
init(default_conf, 'sqlite://')
result = _process()
assert result is False
assert sleep_mock.has_calls()
def test_process_runtime_error(default_conf, ticker, mocker):
msg_mock = MagicMock()
mocker.patch.dict('freqtrade.main._CONF', default_conf)
mocker.patch.multiple('freqtrade.main.telegram', init=MagicMock(), send_msg=msg_mock)
mocker.patch('freqtrade.main.get_buy_signal', side_effect=lambda _: True)
mocker.patch.multiple('freqtrade.main.exchange',
validate_pairs=MagicMock(),
get_ticker=ticker,
buy=MagicMock(side_effect=RuntimeError))
init(default_conf, 'sqlite://')
assert get_state() == State.RUNNING
result = _process()
assert result is False
assert get_state() == State.STOPPED
assert 'RuntimeError' in msg_mock.call_args_list[-1][0][0]
def test_process_trade_handling(default_conf, ticker, limit_buy_order, mocker):
mocker.patch.dict('freqtrade.main._CONF', default_conf)
mocker.patch.multiple('freqtrade.main.telegram', init=MagicMock(), send_msg=MagicMock())
mocker.patch('freqtrade.main.get_buy_signal', side_effect=lambda _: True)
mocker.patch.multiple('freqtrade.main.exchange',
validate_pairs=MagicMock(),
get_ticker=ticker,
buy=MagicMock(return_value='mocked_limit_buy'),
get_order=MagicMock(return_value=limit_buy_order)),
init(default_conf, 'sqlite://')
assert len(Trade.query.filter(Trade.is_open.is_(True)).all()) == 0
result = _process()
assert result is True
assert len(Trade.query.filter(Trade.is_open.is_(True)).all()) == 1
result = _process()
assert result is False
def test_create_trade(default_conf, ticker, limit_buy_order, mocker):
mocker.patch.dict('freqtrade.main._CONF', default_conf)
buy_signal = mocker.patch('freqtrade.main.get_buy_signal', side_effect=lambda _: True)
mocker.patch('freqtrade.main.get_buy_signal', side_effect=lambda _: True)
mocker.patch.multiple('freqtrade.main.telegram', init=MagicMock(), send_msg=MagicMock())
mocker.patch.multiple('freqtrade.main.exchange',
validate_pairs=MagicMock(),
@ -20,31 +105,56 @@ def test_create_trade(default_conf, ticker, limit_buy_order, mocker):
whitelist = copy.deepcopy(default_conf['exchange']['pair_whitelist'])
init(default_conf, 'sqlite://')
for _ in ['BTC_ETH', 'BTC_TKN', 'BTC_TRST', 'BTC_SWT']:
trade = create_trade(15.0)
Trade.session.add(trade)
Trade.session.flush()
assert trade is not None
assert trade.stake_amount == 15.0
assert trade.is_open
assert trade.open_date is not None
assert trade.exchange == Exchanges.BITTREX.name
trade = create_trade(15.0)
Trade.session.add(trade)
Trade.session.flush()
assert trade is not None
assert trade.stake_amount == 15.0
assert trade.is_open
assert trade.open_date is not None
assert trade.exchange == Exchanges.BITTREX.name
# Simulate fulfilled LIMIT_BUY order for trade
trade.update(limit_buy_order)
# Simulate fulfilled LIMIT_BUY order for trade
trade.update(limit_buy_order)
assert trade.open_rate == 0.07256061
assert trade.amount == 206.43811673387373
assert trade.open_rate == 0.07256061
assert trade.amount == 206.43811673387373
assert whitelist == default_conf['exchange']['pair_whitelist']
buy_signal.assert_has_calls(
[call('BTC_ETH'), call('BTC_TKN'), call('BTC_TRST'), call('BTC_SWT')]
)
assert whitelist == default_conf['exchange']['pair_whitelist']
def test_handle_trade(default_conf, limit_sell_order, mocker):
def test_create_trade_no_stake_amount(default_conf, ticker, mocker):
mocker.patch.dict('freqtrade.main._CONF', default_conf)
mocker.patch('freqtrade.main.get_buy_signal', side_effect=lambda _: True)
mocker.patch.multiple('freqtrade.main.telegram', init=MagicMock(), send_msg=MagicMock())
mocker.patch.multiple('freqtrade.main.exchange',
validate_pairs=MagicMock(),
get_ticker=ticker,
buy=MagicMock(return_value='mocked_limit_buy'),
get_balance=MagicMock(return_value=default_conf['stake_amount'] * 0.5))
with pytest.raises(ValueError, match=r'.*stake amount.*'):
create_trade(default_conf['stake_amount'])
def test_create_trade_no_pairs(default_conf, ticker, mocker):
mocker.patch.dict('freqtrade.main._CONF', default_conf)
mocker.patch('freqtrade.main.get_buy_signal', side_effect=lambda _: True)
mocker.patch.multiple('freqtrade.main.telegram', init=MagicMock(), send_msg=MagicMock())
mocker.patch.multiple('freqtrade.main.exchange',
validate_pairs=MagicMock(),
get_ticker=ticker,
buy=MagicMock(return_value='mocked_limit_buy'))
with pytest.raises(ValueError, match=r'.*No pair in whitelist.*'):
conf = copy.deepcopy(default_conf)
conf['exchange']['pair_whitelist'] = []
mocker.patch.dict('freqtrade.main._CONF', conf)
create_trade(default_conf['stake_amount'])
def test_handle_trade(default_conf, limit_buy_order, limit_sell_order, mocker):
mocker.patch.dict('freqtrade.main._CONF', default_conf)
mocker.patch('freqtrade.main.get_buy_signal', side_effect=lambda _: True)
mocker.patch.multiple('freqtrade.main.telegram', init=MagicMock(), send_msg=MagicMock())
mocker.patch.multiple('freqtrade.main.exchange',
validate_pairs=MagicMock(),
@ -53,12 +163,19 @@ def test_handle_trade(default_conf, limit_sell_order, mocker):
'ask': 0.172661,
'last': 0.17256061
}),
buy=MagicMock(return_value='mocked_limit_buy'),
sell=MagicMock(return_value='mocked_limit_sell'))
init(default_conf, 'sqlite://')
trade = create_trade(15.0)
trade.update(limit_buy_order)
Trade.session.add(trade)
Trade.session.flush()
trade = Trade.query.filter(Trade.is_open.is_(True)).first()
assert trade
handle_trade(trade)
assert trade.open_order_id == 'mocked_limit_sell'
assert close_trade_if_fulfilled(trade) is False
# Simulate fulfilled LIMIT_SELL order for trade
trade.update(limit_sell_order)
@ -68,8 +185,23 @@ def test_handle_trade(default_conf, limit_sell_order, mocker):
assert trade.close_date is not None
def test_close_trade(default_conf, mocker):
def test_close_trade(default_conf, ticker, limit_buy_order, limit_sell_order, mocker):
mocker.patch.dict('freqtrade.main._CONF', default_conf)
mocker.patch('freqtrade.main.get_buy_signal', side_effect=lambda _: True)
mocker.patch.multiple('freqtrade.main.telegram', init=MagicMock(), send_msg=MagicMock())
mocker.patch.multiple('freqtrade.main.exchange',
validate_pairs=MagicMock(),
get_ticker=ticker,
buy=MagicMock(return_value='mocked_limit_buy'))
# Create trade and sell it
init(default_conf, 'sqlite://')
trade = create_trade(15.0)
trade.update(limit_buy_order)
trade.update(limit_sell_order)
Trade.session.add(trade)
Trade.session.flush()
trade = Trade.query.filter(Trade.is_open.is_(True)).first()
assert trade
@ -79,6 +211,8 @@ def test_close_trade(default_conf, mocker):
closed = close_trade_if_fulfilled(trade)
assert closed
assert not trade.is_open
with pytest.raises(ValueError, match=r'.*closed trade.*'):
handle_trade(trade)
def test_balance_fully_ask_side(mocker):

View File

@ -1,22 +1,55 @@
# pragma pylint: disable=missing-docstring, too-many-arguments, too-many-ancestors
import re
from datetime import datetime
from random import randint
from unittest.mock import MagicMock
from telegram import Bot
from telegram import Bot, Update, Message, Chat
from freqtrade.main import init, create_trade
from freqtrade.misc import update_state, State, get_state
from freqtrade.persistence import Trade
from freqtrade.rpc.telegram import (
_status, _status_table, _profit, _forcesell, _performance, _count, _start, _stop, _balance
)
_status, _status_table, _profit, _forcesell, _performance, _count, _start, _stop, _balance,
authorized_only)
class MagicBot(MagicMock, Bot):
pass
def test_authorized_only(default_conf, mocker):
mocker.patch.dict('freqtrade.rpc.telegram._CONF', default_conf)
chat = Chat(0, 0)
update = Update(randint(1, 100))
update.message = Message(randint(1, 100), 0, datetime.utcnow(), chat)
state = {'called': False}
@authorized_only
def dummy_handler(*args, **kwargs) -> None:
state['called'] = True
dummy_handler(MagicMock(), update)
assert state['called'] is True
def test_authorized_only_unauthorized(default_conf, mocker):
mocker.patch.dict('freqtrade.rpc.telegram._CONF', default_conf)
chat = Chat(0xdeadbeef, 0)
update = Update(randint(1, 100))
update.message = Message(randint(1, 100), 0, datetime.utcnow(), chat)
state = {'called': False}
@authorized_only
def dummy_handler(*args, **kwargs) -> None:
state['called'] = True
dummy_handler(MagicMock(), update)
assert state['called'] is False
def test_status_handle(default_conf, update, ticker, mocker):
mocker.patch.dict('freqtrade.main._CONF', default_conf)
mocker.patch('freqtrade.main.get_buy_signal', side_effect=lambda _: True)