From 06ad311aa3e64bfe76967e3bdd050f1856d19a19 Mon Sep 17 00:00:00 2001 From: Janne Sinivirta Date: Sun, 1 Oct 2017 11:02:47 +0300 Subject: [PATCH] remove Test classes and use pytest fixtures --- freqtrade/tests/test_analyze.py | 52 +++--- freqtrade/tests/test_backtesting.py | 81 ++++---- freqtrade/tests/test_main.py | 139 +++++++------- freqtrade/tests/test_persistence.py | 38 ++-- freqtrade/tests/test_telegram.py | 280 ++++++++++++++-------------- 5 files changed, 288 insertions(+), 302 deletions(-) diff --git a/freqtrade/tests/test_analyze.py b/freqtrade/tests/test_analyze.py index 74e945da2..3f3c1610a 100644 --- a/freqtrade/tests/test_analyze.py +++ b/freqtrade/tests/test_analyze.py @@ -1,7 +1,7 @@ # pragma pylint: disable=missing-docstring -import unittest from unittest.mock import patch +import pytest import arrow from pandas import DataFrame @@ -19,34 +19,30 @@ RESULT_BITTREX = { ] } -class TestAnalyze(unittest.TestCase): - def setUp(self): - self.result = parse_ticker_dataframe(RESULT_BITTREX['result'], arrow.get('2017-08-30T10:00:00')) +@pytest.fixture +def result(): + return parse_ticker_dataframe(RESULT_BITTREX['result'], arrow.get('2017-08-30T10:00:00')) - def test_1_dataframe_has_correct_columns(self): - assert self.result.columns.tolist() == \ - ['close', 'high', 'low', 'open', 'date', 'volume'] +def test_1_dataframe_has_correct_columns(result): + assert result.columns.tolist() == \ + ['close', 'high', 'low', 'open', 'date', 'volume'] - def test_2_orders_by_date(self): - assert self.result['date'].tolist() == \ - ['2017-08-30T10:34:00', - '2017-08-30T10:37:00', - '2017-08-30T10:40:00', - '2017-08-30T10:42:00'] +def test_2_orders_by_date(result): + assert result['date'].tolist() == \ + ['2017-08-30T10:34:00', + '2017-08-30T10:37:00', + '2017-08-30T10:40:00', + '2017-08-30T10:42:00'] - def test_3_populates_buy_trend(self): - dataframe = populate_buy_trend(populate_indicators(self.result)) - assert 'buy' in dataframe.columns - assert 'buy_price' in dataframe.columns +def test_3_populates_buy_trend(result): + dataframe = populate_buy_trend(populate_indicators(result)) + assert 'buy' in dataframe.columns + assert 'buy_price' in dataframe.columns - def test_4_returns_latest_buy_signal(self): - buydf = DataFrame([{'buy': 1, 'date': arrow.utcnow()}]) - with patch('freqtrade.analyze.analyze_ticker', return_value=buydf): - assert get_buy_signal('BTC-ETH') == True - buydf = DataFrame([{'buy': 0, 'date': arrow.utcnow()}]) - with patch('freqtrade.analyze.analyze_ticker', return_value=buydf): - assert get_buy_signal('BTC-ETH') == False - - -if __name__ == '__main__': - unittest.main() +def test_4_returns_latest_buy_signal(): + buydf = DataFrame([{'buy': 1, 'date': arrow.utcnow()}]) + with patch('freqtrade.analyze.analyze_ticker', return_value=buydf): + assert get_buy_signal('BTC-ETH') == True + buydf = DataFrame([{'buy': 0, 'date': arrow.utcnow()}]) + with patch('freqtrade.analyze.analyze_ticker', return_value=buydf): + assert get_buy_signal('BTC-ETH') == False diff --git a/freqtrade/tests/test_backtesting.py b/freqtrade/tests/test_backtesting.py index ff8f8a039..fe69104ff 100644 --- a/freqtrade/tests/test_backtesting.py +++ b/freqtrade/tests/test_backtesting.py @@ -2,9 +2,9 @@ import json import logging import os -import unittest from unittest.mock import patch +import pytest import arrow from pandas import DataFrame @@ -12,6 +12,7 @@ from freqtrade.analyze import analyze_ticker from freqtrade.main import should_sell from freqtrade.persistence import Trade +logging.disable(logging.DEBUG) # disable debug logs that slow backtesting a lot def print_results(results): print('Made {} buys. Average profit {:.2f}%. Total profit was {:.3f}. Average duration {:.1f} mins.'.format( @@ -21,9 +22,14 @@ def print_results(results): results.duration.mean()*5 )) -class TestMain(unittest.TestCase): - pairs = ['btc-neo', 'btc-eth', 'btc-omg', 'btc-edg', 'btc-pay', 'btc-pivx', 'btc-qtum', 'btc-mtl', 'btc-etc', 'btc-ltc'] - conf = { +@pytest.fixture +def pairs(): + return ['btc-neo', 'btc-eth', 'btc-omg', 'btc-edg', 'btc-pay', + 'btc-pivx', 'btc-qtum', 'btc-mtl', 'btc-etc', 'btc-ltc'] + +@pytest.fixture +def conf(): + return { "minimal_roi": { "60": 0.0, "40": 0.01, @@ -33,43 +39,40 @@ class TestMain(unittest.TestCase): "stoploss": -0.40 } - @classmethod - def setUpClass(cls): - logging.disable(logging.DEBUG) # disable debug logs that slow backtesting a lot - @unittest.skipIf(not os.environ.get('BACKTEST', False), "slow, should be run manually") - def test_backtest(self): - trades = [] - with patch.dict('freqtrade.main._CONF', self.conf): - for pair in self.pairs: - with open('testdata/'+pair+'.json') as data_file: - data = json.load(data_file) +@pytest.mark.skipif(not os.environ.get('BACKTEST', False), reason="BACKTEST not set") +def test_backtest(conf, pairs): + trades = [] + with patch.dict('freqtrade.main._CONF', conf): + for pair in pairs: + with open('tests/testdata/'+pair+'.json') as data_file: + data = json.load(data_file) - with patch('freqtrade.analyze.get_ticker', return_value=data): - with patch('arrow.utcnow', return_value=arrow.get('2017-08-20T14:50:00')): - ticker = analyze_ticker(pair) - # for each buy point - for index, row in ticker[ticker.buy == 1].iterrows(): - trade = Trade( - open_rate=row['close'], - open_date=arrow.get(row['date']).datetime, - amount=1, - ) - # calculate win/lose forwards from buy point - for index2, row2 in ticker[index:].iterrows(): - if should_sell(trade, row2['close'], arrow.get(row2['date']).datetime): - current_profit = (row2['close'] - trade.open_rate) / trade.open_rate + with patch('freqtrade.analyze.get_ticker', return_value=data): + with patch('arrow.utcnow', return_value=arrow.get('2017-08-20T14:50:00')): + ticker = analyze_ticker(pair) + # for each buy point + for index, row in ticker[ticker.buy == 1].iterrows(): + trade = Trade( + open_rate=row['close'], + open_date=arrow.get(row['date']).datetime, + amount=1, + ) + # calculate win/lose forwards from buy point + for index2, row2 in ticker[index:].iterrows(): + if should_sell(trade, row2['close'], arrow.get(row2['date']).datetime): + current_profit = (row2['close'] - trade.open_rate) / trade.open_rate - trades.append((pair, current_profit, index2 - index)) - break - - labels = ['currency', 'profit', 'duration'] - results = DataFrame.from_records(trades, columns=labels) + trades.append((pair, current_profit, index2 - index)) + break + + labels = ['currency', 'profit', 'duration'] + results = DataFrame.from_records(trades, columns=labels) - print('====================== BACKTESTING REPORT ================================') + print('====================== BACKTESTING REPORT ================================') - for pair in self.pairs: - print('For currency {}:'.format(pair)) - print_results(results[results.currency == pair]) - print('TOTAL OVER ALL TRADES:') - print_results(results) + for pair in pairs: + print('For currency {}:'.format(pair)) + print_results(results[results.currency == pair]) + print('TOTAL OVER ALL TRADES:') + print_results(results) diff --git a/freqtrade/tests/test_main.py b/freqtrade/tests/test_main.py index 73bb153de..bb075aee0 100644 --- a/freqtrade/tests/test_main.py +++ b/freqtrade/tests/test_main.py @@ -1,7 +1,7 @@ -import unittest +import copy from unittest.mock import patch, MagicMock, call -import copy +import pytest from jsonschema import validate from freqtrade import exchange @@ -11,8 +11,9 @@ from freqtrade.misc import CONF_SCHEMA from freqtrade.persistence import Trade -class TestMain(unittest.TestCase): - conf = { +@pytest.fixture +def conf(): + configuration = { "max_open_trades": 3, "stake_currency": "BTC", "stake_amount": 0.05, @@ -42,86 +43,80 @@ class TestMain(unittest.TestCase): "chat_id": "chat_id" } } + validate(configuration, CONF_SCHEMA) + return configuration - def test_1_create_trade(self): - with patch.dict('freqtrade.main._CONF', self.conf): - with patch('freqtrade.main.get_buy_signal', side_effect=lambda _: True) as buy_signal: - with patch.multiple('freqtrade.main.telegram', init=MagicMock(), send_msg=MagicMock()): - with patch.multiple('freqtrade.main.exchange', - get_ticker=MagicMock(return_value={ - 'bid': 0.07256061, - 'ask': 0.072661, - 'last': 0.07256061 - }), - buy=MagicMock(return_value='mocked_order_id')): - # Save state of current whitelist - whitelist = copy.deepcopy(self.conf['bittrex']['pair_whitelist']) - - init(self.conf, 'sqlite://') - for pair in ['BTC_ETH', 'BTC_TKN', 'BTC_TRST', 'BTC_SWT']: - trade = create_trade(15.0, exchange.Exchange.BITTREX) - Trade.session.add(trade) - Trade.session.flush() - assert trade is not None - assert trade.open_rate == 0.072661 - assert trade.pair == pair - assert trade.exchange == exchange.Exchange.BITTREX - assert trade.amount == 206.43811673387373 - assert trade.stake_amount == 15.0 - assert trade.is_open == True - assert trade.open_date is not None - assert whitelist == self.conf['bittrex']['pair_whitelist'] - - buy_signal.assert_has_calls( - [call('BTC_ETH'), call('BTC_TKN'), call('BTC_TRST'), call('BTC_SWT')] - ) - - def test_2_handle_trade(self): - with patch.dict('freqtrade.main._CONF', self.conf): +def test_1_create_trade(conf): + with patch.dict('freqtrade.main._CONF', conf): + with patch('freqtrade.main.get_buy_signal', side_effect=lambda _: True) as buy_signal: with patch.multiple('freqtrade.main.telegram', init=MagicMock(), send_msg=MagicMock()): with patch.multiple('freqtrade.main.exchange', get_ticker=MagicMock(return_value={ - 'bid': 0.17256061, - 'ask': 0.172661, - 'last': 0.17256061 + 'bid': 0.07256061, + 'ask': 0.072661, + 'last': 0.07256061 }), buy=MagicMock(return_value='mocked_order_id')): - trade = Trade.query.filter(Trade.is_open.is_(True)).first() - assert trade - handle_trade(trade) - assert trade.close_rate == 0.17256061 - assert trade.close_profit == 137.4872490056564 - assert trade.close_date is not None - assert trade.open_order_id == 'dry_run' + # Save state of current whitelist + whitelist = copy.deepcopy(conf['bittrex']['pair_whitelist']) - def test_3_close_trade(self): - with patch.dict('freqtrade.main._CONF', self.conf): - trade = Trade.query.filter(Trade.is_open.is_(True)).first() - assert trade + init(conf, 'sqlite://') + for pair in ['BTC_ETH', 'BTC_TKN', 'BTC_TRST', 'BTC_SWT']: + trade = create_trade(15.0, exchange.Exchange.BITTREX) + Trade.session.add(trade) + Trade.session.flush() + assert trade is not None + assert trade.open_rate == 0.072661 + assert trade.pair == pair + assert trade.exchange == exchange.Exchange.BITTREX + assert trade.amount == 206.43811673387373 + assert trade.stake_amount == 15.0 + assert trade.is_open == True + assert trade.open_date is not None + assert whitelist == conf['bittrex']['pair_whitelist'] - # Simulate that there is no open order - trade.open_order_id = None + buy_signal.assert_has_calls( + [call('BTC_ETH'), call('BTC_TKN'), call('BTC_TRST'), call('BTC_SWT')] + ) - closed = close_trade_if_fulfilled(trade) - assert closed - assert trade.is_open == False +def test_2_handle_trade(conf): + with patch.dict('freqtrade.main._CONF', conf): + with patch.multiple('freqtrade.main.telegram', init=MagicMock(), send_msg=MagicMock()): + with patch.multiple('freqtrade.main.exchange', + get_ticker=MagicMock(return_value={ + 'bid': 0.17256061, + 'ask': 0.172661, + 'last': 0.17256061 + }), + buy=MagicMock(return_value='mocked_order_id')): + trade = Trade.query.filter(Trade.is_open.is_(True)).first() + assert trade + handle_trade(trade) + assert trade.close_rate == 0.17256061 + assert trade.close_profit == 137.4872490056564 + assert trade.close_date is not None + assert trade.open_order_id == 'dry_run' - def test_balance_fully_ask_side(self): - with patch.dict('freqtrade.main._CONF', {'bid_strategy': {'ask_last_balance': 0.0}}): - assert get_target_bid({'ask': 20, 'last': 10}) == 20 +def test_3_close_trade(conf): + with patch.dict('freqtrade.main._CONF', conf): + trade = Trade.query.filter(Trade.is_open.is_(True)).first() + assert trade - def test_balance_fully_last_side(self): - with patch.dict('freqtrade.main._CONF', {'bid_strategy': {'ask_last_balance': 1.0}}): - assert get_target_bid({'ask': 20, 'last': 10}) == 10 + # Simulate that there is no open order + trade.open_order_id = None - def test_balance_when_last_bigger_than_ask(self): - with patch.dict('freqtrade.main._CONF', {'bid_strategy': {'ask_last_balance': 1.0}}): - assert get_target_bid({'ask': 5, 'last': 10}) == 5 + closed = close_trade_if_fulfilled(trade) + assert closed + assert trade.is_open == False - @classmethod - def setUpClass(cls): - validate(cls.conf, CONF_SCHEMA) +def test_balance_fully_ask_side(): + with patch.dict('freqtrade.main._CONF', {'bid_strategy': {'ask_last_balance': 0.0}}): + assert get_target_bid({'ask': 20, 'last': 10}) == 20 +def test_balance_fully_last_side(): + with patch.dict('freqtrade.main._CONF', {'bid_strategy': {'ask_last_balance': 1.0}}): + assert get_target_bid({'ask': 20, 'last': 10}) == 10 -if __name__ == '__main__': - unittest.main() +def test_balance_when_last_bigger_than_ask(): + with patch.dict('freqtrade.main._CONF', {'bid_strategy': {'ask_last_balance': 1.0}}): + assert get_target_bid({'ask': 5, 'last': 10}) == 5 diff --git a/freqtrade/tests/test_persistence.py b/freqtrade/tests/test_persistence.py index 5b7c94989..eed6c1203 100644 --- a/freqtrade/tests/test_persistence.py +++ b/freqtrade/tests/test_persistence.py @@ -1,28 +1,22 @@ -import unittest from unittest.mock import patch from freqtrade.exchange import Exchange from freqtrade.persistence import Trade -class TestTrade(unittest.TestCase): - def test_1_exec_sell_order(self): - with patch('freqtrade.main.exchange.sell', side_effect='mocked_order_id') as api_mock: - trade = Trade( - pair='BTC_ETH', - stake_amount=1.00, - open_rate=0.50, - amount=10.00, - exchange=Exchange.BITTREX, - open_order_id='mocked' - ) - profit = trade.exec_sell_order(1.00, 10.00) - api_mock.assert_called_once_with('BTC_ETH', 1.0, 10.0) - assert profit == 100.0 - assert trade.close_rate == 1.0 - assert trade.close_profit == profit - assert trade.close_date is not None - - -if __name__ == '__main__': - unittest.main() +def test_1_exec_sell_order(): + with patch('freqtrade.main.exchange.sell', side_effect='mocked_order_id') as api_mock: + trade = Trade( + pair='BTC_ETH', + stake_amount=1.00, + open_rate=0.50, + amount=10.00, + exchange=Exchange.BITTREX, + open_order_id='mocked' + ) + profit = trade.exec_sell_order(1.00, 10.00) + api_mock.assert_called_once_with('BTC_ETH', 1.0, 10.0) + assert profit == 100.0 + assert trade.close_rate == 1.0 + assert trade.close_profit == profit + assert trade.close_date is not None diff --git a/freqtrade/tests/test_telegram.py b/freqtrade/tests/test_telegram.py index f86090d35..efc89ea25 100644 --- a/freqtrade/tests/test_telegram.py +++ b/freqtrade/tests/test_telegram.py @@ -1,7 +1,7 @@ -import unittest from datetime import datetime from unittest.mock import patch, MagicMock +import pytest from jsonschema import validate from telegram import Bot, Update, Message, Chat @@ -12,13 +12,9 @@ from freqtrade.persistence import Trade from freqtrade.rpc.telegram import _status, _profit, _forcesell, _performance, _start, _stop -class MagicBot(MagicMock, Bot): - pass - - -class TestTelegram(unittest.TestCase): - - conf = { +@pytest.fixture +def conf(): + configuration = { "max_open_trades": 3, "stake_currency": "BTC", "stake_amount": 0.05, @@ -46,150 +42,152 @@ class TestTelegram(unittest.TestCase): }, "initial_state": "running" } + validate(configuration, CONF_SCHEMA) + return configuration - def test_1_status_handle(self): - with patch.dict('freqtrade.main._CONF', self.conf): - with patch('freqtrade.main.get_buy_signal', side_effect=lambda _: True): - msg_mock = MagicMock() - with patch.multiple('freqtrade.main.telegram', _CONF=self.conf, init=MagicMock(), send_msg=msg_mock): - with patch.multiple('freqtrade.main.exchange', - get_ticker=MagicMock(return_value={ - 'bid': 0.07256061, - 'ask': 0.072661, - 'last': 0.07256061 - }), - buy=MagicMock(return_value='mocked_order_id')): - init(self.conf, 'sqlite://') +@pytest.fixture +def update(): + _update = Update(0) + _update.message = Message(0, 0, datetime.utcnow(), Chat(0, 0)) + return _update - # Create some test data - trade = create_trade(15.0, exchange.Exchange.BITTREX) - assert trade - Trade.session.add(trade) - Trade.session.flush() - _status(bot=MagicBot(), update=self.update) - assert msg_mock.call_count == 2 - assert '[BTC_ETH]' in msg_mock.call_args_list[-1][0][0] +class MagicBot(MagicMock, Bot): + pass - def test_2_profit_handle(self): - with patch.dict('freqtrade.main._CONF', self.conf): - with patch('freqtrade.main.get_buy_signal', side_effect=lambda _: True): - msg_mock = MagicMock() - with patch.multiple('freqtrade.main.telegram', _CONF=self.conf, init=MagicMock(), send_msg=msg_mock): - with patch.multiple('freqtrade.main.exchange', - get_ticker=MagicMock(return_value={ - 'bid': 0.07256061, - 'ask': 0.072661, - 'last': 0.07256061 - }), - buy=MagicMock(return_value='mocked_order_id')): - init(self.conf, 'sqlite://') - # Create some test data - trade = create_trade(15.0, exchange.Exchange.BITTREX) - assert trade - trade.close_rate = 0.07256061 - trade.close_profit = 100.00 - trade.close_date = datetime.utcnow() - trade.open_order_id = None - trade.is_open = False - Trade.session.add(trade) - Trade.session.flush() - - _profit(bot=MagicBot(), update=self.update) - assert msg_mock.call_count == 2 - assert '(100.00%)' in msg_mock.call_args_list[-1][0][0] - - def test_3_forcesell_handle(self): - with patch.dict('freqtrade.main._CONF', self.conf): - with patch('freqtrade.main.get_buy_signal', side_effect=lambda _: True): - msg_mock = MagicMock() - with patch.multiple('freqtrade.main.telegram', _CONF=self.conf, init=MagicMock(), send_msg=msg_mock): - with patch.multiple('freqtrade.main.exchange', - get_ticker=MagicMock(return_value={ - 'bid': 0.07256061, - 'ask': 0.072661, - 'last': 0.07256061 - }), - buy=MagicMock(return_value='mocked_order_id')): - init(self.conf, 'sqlite://') - - # Create some test data - trade = create_trade(15.0, exchange.Exchange.BITTREX) - assert trade - Trade.session.add(trade) - Trade.session.flush() - - self.update.message.text = '/forcesell 1' - _forcesell(bot=MagicBot(), update=self.update) - - assert msg_mock.call_count == 2 - assert 'Selling [BTC/ETH]' in msg_mock.call_args_list[-1][0][0] - assert '0.072561' in msg_mock.call_args_list[-1][0][0] - - def test_4_performance_handle(self): - with patch.dict('freqtrade.main._CONF', self.conf): - with patch('freqtrade.main.get_buy_signal', side_effect=lambda _: True): - msg_mock = MagicMock() - with patch.multiple('freqtrade.main.telegram', _CONF=self.conf, init=MagicMock(), send_msg=msg_mock): - with patch.multiple('freqtrade.main.exchange', - get_ticker=MagicMock(return_value={ - 'bid': 0.07256061, - 'ask': 0.072661, - 'last': 0.07256061 - }), - buy=MagicMock(return_value='mocked_order_id')): - init(self.conf, 'sqlite://') - - # Create some test data - trade = create_trade(15.0, exchange.Exchange.BITTREX) - assert trade - trade.close_rate = 0.07256061 - trade.close_profit = 100.00 - trade.close_date = datetime.utcnow() - trade.open_order_id = None - trade.is_open = False - Trade.session.add(trade) - Trade.session.flush() - - _performance(bot=MagicBot(), update=self.update) - assert msg_mock.call_count == 2 - assert 'Performance' in msg_mock.call_args_list[-1][0][0] - assert 'BTC_ETH 100.00%' in msg_mock.call_args_list[-1][0][0] - - def test_5_start_handle(self): - with patch.dict('freqtrade.main._CONF', self.conf): +def test_1_status_handle(conf, update): + with patch.dict('freqtrade.main._CONF', conf): + with patch('freqtrade.main.get_buy_signal', side_effect=lambda _: True): msg_mock = MagicMock() - with patch.multiple('freqtrade.main.telegram', _CONF=self.conf, init=MagicMock(), send_msg=msg_mock): - init(self.conf, 'sqlite://') + with patch.multiple('freqtrade.main.telegram', _CONF=conf, init=MagicMock(), send_msg=msg_mock): + with patch.multiple('freqtrade.main.exchange', + get_ticker=MagicMock(return_value={ + 'bid': 0.07256061, + 'ask': 0.072661, + 'last': 0.07256061 + }), + buy=MagicMock(return_value='mocked_order_id')): + init(conf, 'sqlite://') - update_state(State.STOPPED) - assert get_state() == State.STOPPED - _start(bot=MagicBot(), update=self.update) - assert get_state() == State.RUNNING - assert msg_mock.call_count == 0 + # Create some test data + trade = create_trade(15.0, exchange.Exchange.BITTREX) + assert trade + Trade.session.add(trade) + Trade.session.flush() - def test_6_stop_handle(self): - with patch.dict('freqtrade.main._CONF', self.conf): + _status(bot=MagicBot(), update=update) + assert msg_mock.call_count == 2 + assert '[BTC_ETH]' in msg_mock.call_args_list[-1][0][0] + +def test_2_profit_handle(conf, update): + with patch.dict('freqtrade.main._CONF', conf): + with patch('freqtrade.main.get_buy_signal', side_effect=lambda _: True): msg_mock = MagicMock() - with patch.multiple('freqtrade.main.telegram', _CONF=self.conf, init=MagicMock(), send_msg=msg_mock): - init(self.conf, 'sqlite://') + with patch.multiple('freqtrade.main.telegram', _CONF=conf, init=MagicMock(), send_msg=msg_mock): + with patch.multiple('freqtrade.main.exchange', + get_ticker=MagicMock(return_value={ + 'bid': 0.07256061, + 'ask': 0.072661, + 'last': 0.07256061 + }), + buy=MagicMock(return_value='mocked_order_id')): + init(conf, 'sqlite://') - update_state(State.RUNNING) - assert get_state() == State.RUNNING - _stop(bot=MagicBot(), update=self.update) - assert get_state() == State.STOPPED - assert msg_mock.call_count == 1 - assert 'Stopping trader' in msg_mock.call_args_list[0][0][0] + # Create some test data + trade = create_trade(15.0, exchange.Exchange.BITTREX) + assert trade + trade.close_rate = 0.07256061 + trade.close_profit = 100.00 + trade.close_date = datetime.utcnow() + trade.open_order_id = None + trade.is_open = False + Trade.session.add(trade) + Trade.session.flush() - def setUp(self): - self.update = Update(0) - self.update.message = Message(0, 0, datetime.utcnow(), Chat(0, 0)) + _profit(bot=MagicBot(), update=update) + assert msg_mock.call_count == 2 + assert '(100.00%)' in msg_mock.call_args_list[-1][0][0] - @classmethod - def setUpClass(cls): - validate(cls.conf, CONF_SCHEMA) +def test_3_forcesell_handle(conf, update): + with patch.dict('freqtrade.main._CONF', conf): + with patch('freqtrade.main.get_buy_signal', side_effect=lambda _: True): + msg_mock = MagicMock() + with patch.multiple('freqtrade.main.telegram', _CONF=conf, init=MagicMock(), send_msg=msg_mock): + with patch.multiple('freqtrade.main.exchange', + get_ticker=MagicMock(return_value={ + 'bid': 0.07256061, + 'ask': 0.072661, + 'last': 0.07256061 + }), + buy=MagicMock(return_value='mocked_order_id')): + init(conf, 'sqlite://') + # Create some test data + trade = create_trade(15.0, exchange.Exchange.BITTREX) + assert trade + Trade.session.add(trade) + Trade.session.flush() + + update.message.text = '/forcesell 1' + _forcesell(bot=MagicBot(), update=update) + + assert msg_mock.call_count == 2 + assert 'Selling [BTC/ETH]' in msg_mock.call_args_list[-1][0][0] + assert '0.072561' in msg_mock.call_args_list[-1][0][0] + +def test_4_performance_handle(conf, update): + with patch.dict('freqtrade.main._CONF', conf): + with patch('freqtrade.main.get_buy_signal', side_effect=lambda _: True): + msg_mock = MagicMock() + with patch.multiple('freqtrade.main.telegram', _CONF=conf, init=MagicMock(), send_msg=msg_mock): + with patch.multiple('freqtrade.main.exchange', + get_ticker=MagicMock(return_value={ + 'bid': 0.07256061, + 'ask': 0.072661, + 'last': 0.07256061 + }), + buy=MagicMock(return_value='mocked_order_id')): + init(conf, 'sqlite://') + + # Create some test data + trade = create_trade(15.0, exchange.Exchange.BITTREX) + assert trade + trade.close_rate = 0.07256061 + trade.close_profit = 100.00 + trade.close_date = datetime.utcnow() + trade.open_order_id = None + trade.is_open = False + Trade.session.add(trade) + Trade.session.flush() + + _performance(bot=MagicBot(), update=update) + assert msg_mock.call_count == 2 + assert 'Performance' in msg_mock.call_args_list[-1][0][0] + assert 'BTC_ETH 100.00%' in msg_mock.call_args_list[-1][0][0] + +def test_5_start_handle(conf, update): + with patch.dict('freqtrade.main._CONF', conf): + msg_mock = MagicMock() + with patch.multiple('freqtrade.main.telegram', _CONF=conf, init=MagicMock(), send_msg=msg_mock): + init(conf, 'sqlite://') + + update_state(State.STOPPED) + assert get_state() == State.STOPPED + _start(bot=MagicBot(), update=update) + assert get_state() == State.RUNNING + assert msg_mock.call_count == 0 + +def test_6_stop_handle(conf, update): + with patch.dict('freqtrade.main._CONF', conf): + msg_mock = MagicMock() + with patch.multiple('freqtrade.main.telegram', _CONF=conf, init=MagicMock(), send_msg=msg_mock): + init(conf, 'sqlite://') + + update_state(State.RUNNING) + assert get_state() == State.RUNNING + _stop(bot=MagicBot(), update=update) + assert get_state() == State.STOPPED + assert msg_mock.call_count == 1 + assert 'Stopping trader' in msg_mock.call_args_list[0][0][0] -if __name__ == '__main__': - unittest.main()