stable/tests/test_main.py

208 lines
8.1 KiB
Python
Raw Normal View History

2018-07-29 14:09:44 +00:00
# pragma pylint: disable=missing-docstring
from copy import deepcopy
2020-09-28 17:43:15 +00:00
from pathlib import Path
2019-08-16 12:53:46 +00:00
from unittest.mock import MagicMock, PropertyMock
2018-03-17 21:44:47 +00:00
2017-11-07 21:27:44 +00:00
import pytest
from freqtrade.commands import Arguments
2021-06-08 19:20:35 +00:00
from freqtrade.enums import State
from freqtrade.exceptions import FreqtradeException, OperationalException
from freqtrade.freqtradebot import FreqtradeBot
2019-03-26 09:42:19 +00:00
from freqtrade.main import main
from freqtrade.worker import Worker
2019-09-16 04:44:20 +00:00
from tests.conftest import (log_has, log_has_re, patch_exchange,
2019-09-08 08:07:09 +00:00
patched_configuration_load_config_file)
2018-01-10 09:25:45 +00:00
2019-09-16 04:44:20 +00:00
def test_parse_args_None(caplog) -> None:
with pytest.raises(SystemExit):
main([])
2019-11-13 09:03:59 +00:00
assert log_has_re(r"Usage of Freqtrade requires a subcommand.*", caplog)
2019-09-16 04:44:20 +00:00
def test_parse_args_backtesting(mocker) -> None:
"""
Test that main() can start backtesting and also ensure we can pass some specific arguments
further argument parsing is done in test_arguments.py
"""
mocker.patch.object(Path, "is_file", MagicMock(side_effect=[False, True]))
2020-01-26 12:33:13 +00:00
backtesting_mock = mocker.patch('freqtrade.commands.start_backtesting')
2019-08-16 12:53:46 +00:00
backtesting_mock.__name__ = PropertyMock("start_backtesting")
2019-05-28 20:25:53 +00:00
# it's sys.exit(0) at the end of backtesting
with pytest.raises(SystemExit):
main(['backtesting'])
assert backtesting_mock.call_count == 1
call_args = backtesting_mock.call_args[0][0]
2020-06-01 18:47:27 +00:00
assert call_args['config'] == ['config.json']
assert call_args['verbosity'] == 0
assert call_args['command'] == 'backtesting'
assert call_args['func'] is not None
assert callable(call_args['func'])
assert call_args['timeframe'] is None
def test_main_start_hyperopt(mocker) -> None:
2020-08-26 18:52:09 +00:00
mocker.patch.object(Path, 'is_file', MagicMock(side_effect=[False, True]))
2020-01-26 12:33:13 +00:00
hyperopt_mock = mocker.patch('freqtrade.commands.start_hyperopt', MagicMock())
2020-08-26 18:52:09 +00:00
hyperopt_mock.__name__ = PropertyMock('start_hyperopt')
2019-05-28 20:25:53 +00:00
# it's sys.exit(0) at the end of hyperopt
with pytest.raises(SystemExit):
main(['hyperopt'])
assert hyperopt_mock.call_count == 1
call_args = hyperopt_mock.call_args[0][0]
2020-08-26 18:52:09 +00:00
assert call_args['config'] == ['config.json']
assert call_args['verbosity'] == 0
assert call_args['command'] == 'hyperopt'
assert call_args['func'] is not None
assert callable(call_args['func'])
2018-06-07 20:28:21 +00:00
def test_main_fatal_exception(mocker, default_conf, caplog) -> None:
2018-06-17 20:38:31 +00:00
patch_exchange(mocker)
2019-03-26 08:07:24 +00:00
mocker.patch('freqtrade.freqtradebot.FreqtradeBot.cleanup', MagicMock())
mocker.patch('freqtrade.worker.Worker._worker', MagicMock(side_effect=Exception))
2019-07-11 21:39:42 +00:00
patched_configuration_load_config_file(mocker, default_conf)
2018-06-07 20:28:21 +00:00
mocker.patch('freqtrade.freqtradebot.RPCManager', MagicMock())
2020-10-16 05:39:12 +00:00
mocker.patch('freqtrade.freqtradebot.init_db', MagicMock())
2018-06-07 20:28:21 +00:00
args = ['trade', '-c', 'config_examples/config_bittrex.example.json']
# Test Main + the KeyboardInterrupt exception
2018-06-07 20:28:21 +00:00
with pytest.raises(SystemExit):
main(args)
assert log_has('Using config: config_examples/config_bittrex.example.json ...', caplog)
2019-08-11 18:17:39 +00:00
assert log_has('Fatal exception!', caplog)
2018-06-07 20:28:21 +00:00
2018-06-07 20:28:21 +00:00
def test_main_keyboard_interrupt(mocker, default_conf, caplog) -> None:
2018-06-17 20:38:31 +00:00
patch_exchange(mocker)
2019-03-26 08:07:24 +00:00
mocker.patch('freqtrade.freqtradebot.FreqtradeBot.cleanup', MagicMock())
mocker.patch('freqtrade.worker.Worker._worker', MagicMock(side_effect=KeyboardInterrupt))
2019-07-11 21:39:42 +00:00
patched_configuration_load_config_file(mocker, default_conf)
2018-06-07 20:28:21 +00:00
mocker.patch('freqtrade.freqtradebot.RPCManager', MagicMock())
2019-12-17 10:35:39 +00:00
mocker.patch('freqtrade.wallets.Wallets.update', MagicMock())
2020-10-16 05:39:12 +00:00
mocker.patch('freqtrade.freqtradebot.init_db', MagicMock())
2018-06-07 20:28:21 +00:00
args = ['trade', '-c', 'config_examples/config_bittrex.example.json']
2018-06-07 20:28:21 +00:00
# Test Main + the KeyboardInterrupt exception
with pytest.raises(SystemExit):
main(args)
assert log_has('Using config: config_examples/config_bittrex.example.json ...', caplog)
2019-08-11 18:17:39 +00:00
assert log_has('SIGINT received, aborting ...', caplog)
2018-06-07 20:28:21 +00:00
def test_main_operational_exception(mocker, default_conf, caplog) -> None:
2018-06-17 20:38:31 +00:00
patch_exchange(mocker)
2019-03-26 08:07:24 +00:00
mocker.patch('freqtrade.freqtradebot.FreqtradeBot.cleanup', MagicMock())
2019-03-29 23:19:43 +00:00
mocker.patch(
'freqtrade.worker.Worker._worker',
MagicMock(side_effect=FreqtradeException('Oh snap!'))
2019-03-29 23:19:43 +00:00
)
2019-07-11 21:39:42 +00:00
patched_configuration_load_config_file(mocker, default_conf)
2019-12-17 10:35:39 +00:00
mocker.patch('freqtrade.wallets.Wallets.update', MagicMock())
2018-06-07 20:28:21 +00:00
mocker.patch('freqtrade.freqtradebot.RPCManager', MagicMock())
2020-10-16 05:39:12 +00:00
mocker.patch('freqtrade.freqtradebot.init_db', MagicMock())
2018-06-07 20:28:21 +00:00
args = ['trade', '-c', 'config_examples/config_bittrex.example.json']
2018-06-07 20:28:21 +00:00
# Test Main + the KeyboardInterrupt exception
with pytest.raises(SystemExit):
main(args)
assert log_has('Using config: config_examples/config_bittrex.example.json ...', caplog)
2019-08-11 18:17:39 +00:00
assert log_has('Oh snap!', caplog)
2020-05-08 10:34:24 +00:00
def test_main_operational_exception1(mocker, default_conf, caplog) -> None:
patch_exchange(mocker)
mocker.patch(
'freqtrade.commands.list_commands.validate_exchanges',
2020-05-08 10:34:24 +00:00
MagicMock(side_effect=ValueError('Oh snap!'))
)
patched_configuration_load_config_file(mocker, default_conf)
args = ['list-exchanges']
# Test Main + the KeyboardInterrupt exception
with pytest.raises(SystemExit):
main(args)
assert log_has('Fatal exception!', caplog)
assert not log_has_re(r'SIGINT.*', caplog)
mocker.patch(
'freqtrade.commands.list_commands.validate_exchanges',
2020-05-08 10:34:24 +00:00
MagicMock(side_effect=KeyboardInterrupt)
)
2020-05-08 12:24:30 +00:00
with pytest.raises(SystemExit):
main(args)
assert log_has_re(r'SIGINT.*', caplog)
2020-05-08 10:34:24 +00:00
def test_main_reload_config(mocker, default_conf, caplog) -> None:
2018-06-17 20:38:31 +00:00
patch_exchange(mocker)
2019-03-26 08:07:24 +00:00
mocker.patch('freqtrade.freqtradebot.FreqtradeBot.cleanup', MagicMock())
# Simulate Running, reload, running workflow
worker_mock = MagicMock(side_effect=[State.RUNNING,
State.RELOAD_CONFIG,
State.RUNNING,
OperationalException("Oh snap!")])
mocker.patch('freqtrade.worker.Worker._worker', worker_mock)
2019-07-11 21:39:42 +00:00
patched_configuration_load_config_file(mocker, default_conf)
2019-12-17 10:35:39 +00:00
mocker.patch('freqtrade.wallets.Wallets.update', MagicMock())
2019-09-14 11:18:52 +00:00
reconfigure_mock = mocker.patch('freqtrade.worker.Worker._reconfigure', MagicMock())
mocker.patch('freqtrade.freqtradebot.RPCManager', MagicMock())
2020-10-16 05:39:12 +00:00
mocker.patch('freqtrade.freqtradebot.init_db', MagicMock())
2021-07-16 08:03:25 +00:00
args = Arguments([
'trade',
'-c',
'config_examples/config_bittrex.example.json'
]).get_parsed_arg()
worker = Worker(args=args, config=default_conf)
with pytest.raises(SystemExit):
main(['trade', '-c', 'config_examples/config_bittrex.example.json'])
assert log_has('Using config: config_examples/config_bittrex.example.json ...', caplog)
assert worker_mock.call_count == 4
assert reconfigure_mock.call_count == 1
assert isinstance(worker.freqtrade, FreqtradeBot)
def test_reconfigure(mocker, default_conf) -> None:
2018-06-17 20:38:31 +00:00
patch_exchange(mocker)
2019-03-26 08:07:24 +00:00
mocker.patch('freqtrade.freqtradebot.FreqtradeBot.cleanup', MagicMock())
2019-03-29 23:19:43 +00:00
mocker.patch(
'freqtrade.worker.Worker._worker',
MagicMock(side_effect=OperationalException('Oh snap!'))
)
2019-12-17 10:35:39 +00:00
mocker.patch('freqtrade.wallets.Wallets.update', MagicMock())
2019-07-11 21:39:42 +00:00
patched_configuration_load_config_file(mocker, default_conf)
mocker.patch('freqtrade.freqtradebot.RPCManager', MagicMock())
2020-10-16 05:39:12 +00:00
mocker.patch('freqtrade.freqtradebot.init_db', MagicMock())
2021-07-16 08:03:25 +00:00
args = Arguments([
'trade',
'-c',
'config_examples/config_bittrex.example.json'
]).get_parsed_arg()
2019-03-26 09:42:19 +00:00
worker = Worker(args=args, config=default_conf)
freqtrade = worker.freqtrade
# Renew mock to return modified data
conf = deepcopy(default_conf)
conf['stake_amount'] += 1
2019-07-11 21:39:42 +00:00
patched_configuration_load_config_file(mocker, conf)
2019-03-26 09:42:19 +00:00
worker._config = conf
# reconfigure should return a new instance
2019-03-26 09:42:19 +00:00
worker._reconfigure()
freqtrade2 = worker.freqtrade
# Verify we have a new instance with the new config
assert freqtrade is not freqtrade2
assert freqtrade.config['stake_amount'] + 1 == freqtrade2.config['stake_amount']