diff --git a/freqtrade/main.py b/freqtrade/main.py index e0fd784d0..9368fa844 100755 --- a/freqtrade/main.py +++ b/freqtrade/main.py @@ -399,15 +399,18 @@ def cleanup() -> None: exit(0) -def main() -> None: +def main(sysargv=sys.argv[1:]) -> None: """ Loads and validates the config and handles the main loop :return: None """ global _CONF - args = parse_args(sys.argv[1:], + args = parse_args(sysargv, 'Simple High Frequency Trading Bot for crypto currencies') - if not args: + + # A subcommand has been issued + if hasattr(args, 'func'): + args.func(args) exit(0) # Initialize logger diff --git a/freqtrade/misc.py b/freqtrade/misc.py index 7ca5cf976..fada452cc 100644 --- a/freqtrade/misc.py +++ b/freqtrade/misc.py @@ -136,14 +136,7 @@ def parse_args(args: List[str], description: str): ) build_subcommands(parser) - parsed_args = parser.parse_args(args) - - # No subcommand as been selected - if not hasattr(parsed_args, 'func'): - return parsed_args - - parsed_args.func(parsed_args) - return None + return parser.parse_args(args) def build_subcommands(parser: argparse.ArgumentParser) -> None: diff --git a/freqtrade/tests/test_main.py b/freqtrade/tests/test_main.py index 004126268..fab2aa5fd 100644 --- a/freqtrade/tests/test_main.py +++ b/freqtrade/tests/test_main.py @@ -15,6 +15,39 @@ from freqtrade.main import create_trade, handle_trade, init, \ get_target_bid, _process, execute_sell, check_handle_timedout from freqtrade.misc import get_state, State from freqtrade.persistence import Trade +import freqtrade.main as main + + +# Test that main() can start backtesting or hyperopt. +# and also ensure we can pass some specific arguments +# argument parsing is done in test_misc.py + +def test_parse_args_backtesting(mocker): + backtesting_mock = mocker.patch( + 'freqtrade.optimize.backtesting.start', MagicMock()) + with pytest.raises(SystemExit, match=r'0'): + main.main(['backtesting']) + assert backtesting_mock.call_count == 1 + call_args = backtesting_mock.call_args[0][0] + assert call_args.config == 'config.json' + assert call_args.live is False + assert call_args.loglevel == 20 + assert call_args.subparser == 'backtesting' + assert call_args.func is not None + assert call_args.ticker_interval == 5 + + +def test_main_start_hyperopt(mocker): + hyperopt_mock = mocker.patch( + 'freqtrade.optimize.hyperopt.start', MagicMock()) + with pytest.raises(SystemExit, match=r'0'): + main.main(['hyperopt']) + assert hyperopt_mock.call_count == 1 + call_args = hyperopt_mock.call_args[0][0] + assert call_args.config == 'config.json' + assert call_args.loglevel == 20 + assert call_args.subparser == 'hyperopt' + assert call_args.func is not None def test_process_trade_creation(default_conf, ticker, limit_buy_order, health, mocker): diff --git a/freqtrade/tests/test_misc.py b/freqtrade/tests/test_misc.py index 3271b1a1e..0b85000cb 100644 --- a/freqtrade/tests/test_misc.py +++ b/freqtrade/tests/test_misc.py @@ -3,7 +3,6 @@ import json import time import argparse from copy import deepcopy -from unittest.mock import MagicMock import pytest from jsonschema import ValidationError @@ -101,22 +100,6 @@ def test_parse_args_dynamic_whitelist_invalid_values(): parse_args(['--dynamic-whitelist', 'abc'], '') -def test_parse_args_backtesting(mocker): - backtesting_mock = mocker.patch( - 'freqtrade.optimize.backtesting.start', MagicMock()) - args = parse_args(['backtesting'], '') - assert args is None - assert backtesting_mock.call_count == 1 - - call_args = backtesting_mock.call_args[0][0] - assert call_args.config == 'config.json' - assert call_args.live is False - assert call_args.loglevel == 20 - assert call_args.subparser == 'backtesting' - assert call_args.func is not None - assert call_args.ticker_interval == 5 - - def test_parse_args_backtesting_invalid(): with pytest.raises(SystemExit, match=r'2'): parse_args(['backtesting --ticker-interval'], '') @@ -125,19 +108,14 @@ def test_parse_args_backtesting_invalid(): parse_args(['backtesting --ticker-interval', 'abc'], '') -def test_parse_args_backtesting_custom(mocker): - backtesting_mock = mocker.patch( - 'freqtrade.optimize.backtesting.start', MagicMock()) - args = parse_args([ +def test_parse_args_backtesting_custom(): + args = [ '-c', 'test_conf.json', 'backtesting', '--live', '--ticker-interval', '1', - '--refresh-pairs-cached'], '') - assert args is None - assert backtesting_mock.call_count == 1 - - call_args = backtesting_mock.call_args[0][0] + '--refresh-pairs-cached'] + call_args = parse_args(args, '') assert call_args.config == 'test_conf.json' assert call_args.live is True assert call_args.loglevel == 20 @@ -147,28 +125,9 @@ def test_parse_args_backtesting_custom(mocker): assert call_args.refresh_pairs is True -def test_parse_args_hyperopt(mocker): - hyperopt_mock = mocker.patch( - 'freqtrade.optimize.hyperopt.start', MagicMock()) - args = parse_args(['hyperopt'], '') - assert args is None - assert hyperopt_mock.call_count == 1 - - call_args = hyperopt_mock.call_args[0][0] - assert call_args.config == 'config.json' - assert call_args.loglevel == 20 - assert call_args.subparser == 'hyperopt' - assert call_args.func is not None - - def test_parse_args_hyperopt_custom(mocker): - hyperopt_mock = mocker.patch( - 'freqtrade.optimize.hyperopt.start', MagicMock()) - args = parse_args(['-c', 'test_conf.json', 'hyperopt', '--epochs', '20'], '') - assert args is None - assert hyperopt_mock.call_count == 1 - - call_args = hyperopt_mock.call_args[0][0] + args = ['-c', 'test_conf.json', 'hyperopt', '--epochs', '20'] + call_args = parse_args(args, '') assert call_args.config == 'test_conf.json' assert call_args.epochs == 20 assert call_args.loglevel == 20