Merge pull request #52 from gcarq/convert-to-pytest

Switch to using Pytest
This commit is contained in:
Janne Sinivirta 2017-10-01 17:28:23 +03:00 committed by GitHub
commit 3fe5302db3
8 changed files with 313 additions and 326 deletions

View File

@ -1,7 +1,5 @@
# pragma pylint: disable=missing-docstring # pragma pylint: disable=missing-docstring
import unittest import pytest
from unittest.mock import patch
import arrow import arrow
from pandas import DataFrame from pandas import DataFrame
@ -19,34 +17,31 @@ RESULT_BITTREX = {
] ]
} }
class TestAnalyze(unittest.TestCase): @pytest.fixture
def setUp(self): def result():
self.result = parse_ticker_dataframe(RESULT_BITTREX['result'], arrow.get('2017-08-30T10:00:00')) return parse_ticker_dataframe(RESULT_BITTREX['result'], arrow.get('2017-08-30T10:00:00'))
def test_1_dataframe_has_correct_columns(self): def test_dataframe_has_correct_columns(result):
self.assertEqual(self.result.columns.tolist(), assert result.columns.tolist() == \
['close', 'high', 'low', 'open', 'date', 'volume']) ['close', 'high', 'low', 'open', 'date', 'volume']
def test_2_orders_by_date(self): def test_orders_by_date(result):
self.assertEqual(self.result['date'].tolist(), assert result['date'].tolist() == \
['2017-08-30T10:34:00', ['2017-08-30T10:34:00',
'2017-08-30T10:37:00', '2017-08-30T10:37:00',
'2017-08-30T10:40:00', '2017-08-30T10:40:00',
'2017-08-30T10:42:00']) '2017-08-30T10:42:00']
def test_3_populates_buy_trend(self): def test_populates_buy_trend(result):
dataframe = populate_buy_trend(populate_indicators(self.result)) dataframe = populate_buy_trend(populate_indicators(result))
self.assertTrue('buy' in dataframe.columns) assert 'buy' in dataframe.columns
self.assertTrue('buy_price' in dataframe.columns) assert 'buy_price' in dataframe.columns
def test_4_returns_latest_buy_signal(self): def test_returns_latest_buy_signal(mocker):
buydf = DataFrame([{'buy': 1, 'date': arrow.utcnow()}]) buydf = DataFrame([{'buy': 1, 'date': arrow.utcnow()}])
with patch('freqtrade.analyze.analyze_ticker', return_value=buydf): mocker.patch('freqtrade.analyze.analyze_ticker', return_value=buydf)
self.assertEqual(get_buy_signal('BTC-ETH'), True) assert get_buy_signal('BTC-ETH')
buydf = DataFrame([{'buy': 0, 'date': arrow.utcnow()}]) buydf = DataFrame([{'buy': 0, 'date': arrow.utcnow()}])
with patch('freqtrade.analyze.analyze_ticker', return_value=buydf): mocker.patch('freqtrade.analyze.analyze_ticker', return_value=buydf)
self.assertEqual(get_buy_signal('BTC-ETH'), False) assert not get_buy_signal('BTC-ETH')
if __name__ == '__main__':
unittest.main()

View File

@ -2,9 +2,8 @@
import json import json
import logging import logging
import os import os
import unittest
from unittest.mock import patch
import pytest
import arrow import arrow
from pandas import DataFrame from pandas import DataFrame
@ -12,6 +11,7 @@ from freqtrade.analyze import analyze_ticker
from freqtrade.main import should_sell from freqtrade.main import should_sell
from freqtrade.persistence import Trade from freqtrade.persistence import Trade
logging.disable(logging.DEBUG) # disable debug logs that slow backtesting a lot
def print_results(results): def print_results(results):
print('Made {} buys. Average profit {:.2f}%. Total profit was {:.3f}. Average duration {:.1f} mins.'.format( print('Made {} buys. Average profit {:.2f}%. Total profit was {:.3f}. Average duration {:.1f} mins.'.format(
@ -21,9 +21,14 @@ def print_results(results):
results.duration.mean()*5 results.duration.mean()*5
)) ))
class TestMain(unittest.TestCase): @pytest.fixture
pairs = ['btc-neo', 'btc-eth', 'btc-omg', 'btc-edg', 'btc-pay', 'btc-pivx', 'btc-qtum', 'btc-mtl', 'btc-etc', 'btc-ltc'] def pairs():
conf = { 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": { "minimal_roi": {
"60": 0.0, "60": 0.0,
"40": 0.01, "40": 0.01,
@ -33,20 +38,17 @@ class TestMain(unittest.TestCase):
"stoploss": -0.40 "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") @pytest.mark.skipif(not os.environ.get('BACKTEST', False), reason="BACKTEST not set")
def test_backtest(self): def test_backtest(conf, pairs, mocker):
trades = [] trades = []
with patch.dict('freqtrade.main._CONF', self.conf): mocker.patch.dict('freqtrade.main._CONF', conf)
for pair in self.pairs: for pair in pairs:
with open('testdata/'+pair+'.json') as data_file: with open('tests/testdata/'+pair+'.json') as data_file:
data = json.load(data_file) data = json.load(data_file)
with patch('freqtrade.analyze.get_ticker', return_value=data): mocker.patch('freqtrade.analyze.get_ticker', return_value=data)
with patch('arrow.utcnow', return_value=arrow.get('2017-08-20T14:50:00')): mocker.patch('arrow.utcnow', return_value=arrow.get('2017-08-20T14:50:00'))
ticker = analyze_ticker(pair) ticker = analyze_ticker(pair)
# for each buy point # for each buy point
for index, row in ticker[ticker.buy == 1].iterrows(): for index, row in ticker[ticker.buy == 1].iterrows():
@ -68,7 +70,7 @@ class TestMain(unittest.TestCase):
print('====================== BACKTESTING REPORT ================================') print('====================== BACKTESTING REPORT ================================')
for pair in self.pairs: for pair in pairs:
print('For currency {}:'.format(pair)) print('For currency {}:'.format(pair))
print_results(results[results.currency == pair]) print_results(results[results.currency == pair])
print('TOTAL OVER ALL TRADES:') print('TOTAL OVER ALL TRADES:')

View File

@ -1,7 +1,8 @@
import unittest # pragma pylint: disable=missing-docstring
from unittest.mock import patch, MagicMock, call
import copy import copy
from unittest.mock import MagicMock, call
import pytest
from jsonschema import validate from jsonschema import validate
from freqtrade import exchange from freqtrade import exchange
@ -11,8 +12,9 @@ from freqtrade.misc import CONF_SCHEMA
from freqtrade.persistence import Trade from freqtrade.persistence import Trade
class TestMain(unittest.TestCase): @pytest.fixture
conf = { def conf():
configuration = {
"max_open_trades": 3, "max_open_trades": 3,
"stake_currency": "BTC", "stake_currency": "BTC",
"stake_amount": 0.05, "stake_amount": 0.05,
@ -42,86 +44,80 @@ class TestMain(unittest.TestCase):
"chat_id": "chat_id" "chat_id": "chat_id"
} }
} }
validate(configuration, CONF_SCHEMA)
return configuration
def test_1_create_trade(self): def test_create_trade(conf, mocker):
with patch.dict('freqtrade.main._CONF', self.conf): mocker.patch.dict('freqtrade.main._CONF', conf)
with patch('freqtrade.main.get_buy_signal', side_effect=lambda _: True) as buy_signal: buy_signal = mocker.patch('freqtrade.main.get_buy_signal', side_effect=lambda _: True)
with patch.multiple('freqtrade.main.telegram', init=MagicMock(), send_msg=MagicMock()): mocker.patch.multiple('freqtrade.main.telegram', init=MagicMock(), send_msg=MagicMock())
with patch.multiple('freqtrade.main.exchange', mocker.patch.multiple('freqtrade.main.exchange',
get_ticker=MagicMock(return_value={ get_ticker=MagicMock(return_value={
'bid': 0.07256061, 'bid': 0.07256061,
'ask': 0.072661, 'ask': 0.072661,
'last': 0.07256061 'last': 0.07256061
}), }),
buy=MagicMock(return_value='mocked_order_id')): buy=MagicMock(return_value='mocked_order_id'))
# Save state of current whitelist # Save state of current whitelist
whitelist = copy.deepcopy(self.conf['bittrex']['pair_whitelist']) whitelist = copy.deepcopy(conf['bittrex']['pair_whitelist'])
init(self.conf, 'sqlite://') init(conf, 'sqlite://')
for pair in ['BTC_ETH', 'BTC_TKN', 'BTC_TRST', 'BTC_SWT']: for pair in ['BTC_ETH', 'BTC_TKN', 'BTC_TRST', 'BTC_SWT']:
trade = create_trade(15.0, exchange.Exchange.BITTREX) trade = create_trade(15.0, exchange.Exchange.BITTREX)
Trade.session.add(trade) Trade.session.add(trade)
Trade.session.flush() Trade.session.flush()
self.assertIsNotNone(trade) assert trade is not None
self.assertEqual(trade.open_rate, 0.072661) assert trade.open_rate == 0.072661
self.assertEqual(trade.pair, pair) assert trade.pair == pair
self.assertEqual(trade.exchange, exchange.Exchange.BITTREX) assert trade.exchange == exchange.Exchange.BITTREX
self.assertEqual(trade.amount, 206.43811673387373) assert trade.amount == 206.43811673387373
self.assertEqual(trade.stake_amount, 15.0) assert trade.stake_amount == 15.0
self.assertEqual(trade.is_open, True) assert trade.is_open
self.assertIsNotNone(trade.open_date) assert trade.open_date is not None
self.assertEqual(whitelist, self.conf['bittrex']['pair_whitelist']) assert whitelist == conf['bittrex']['pair_whitelist']
buy_signal.assert_has_calls( buy_signal.assert_has_calls(
[call('BTC_ETH'), call('BTC_TKN'), call('BTC_TRST'), call('BTC_SWT')] [call('BTC_ETH'), call('BTC_TKN'), call('BTC_TRST'), call('BTC_SWT')]
) )
def test_2_handle_trade(self): def test_handle_trade(conf, mocker):
with patch.dict('freqtrade.main._CONF', self.conf): mocker.patch.dict('freqtrade.main._CONF', conf)
with patch.multiple('freqtrade.main.telegram', init=MagicMock(), send_msg=MagicMock()): mocker.patch.multiple('freqtrade.main.telegram', init=MagicMock(), send_msg=MagicMock())
with patch.multiple('freqtrade.main.exchange', mocker.patch.multiple('freqtrade.main.exchange',
get_ticker=MagicMock(return_value={ get_ticker=MagicMock(return_value={
'bid': 0.17256061, 'bid': 0.17256061,
'ask': 0.172661, 'ask': 0.172661,
'last': 0.17256061 'last': 0.17256061
}), }),
buy=MagicMock(return_value='mocked_order_id')): buy=MagicMock(return_value='mocked_order_id'))
trade = Trade.query.filter(Trade.is_open.is_(True)).first() trade = Trade.query.filter(Trade.is_open.is_(True)).first()
self.assertTrue(trade) assert trade
handle_trade(trade) handle_trade(trade)
self.assertEqual(trade.close_rate, 0.17256061) assert trade.close_rate == 0.17256061
self.assertEqual(trade.close_profit, 137.4872490056564) assert trade.close_profit == 137.4872490056564
self.assertIsNotNone(trade.close_date) assert trade.close_date is not None
self.assertEqual(trade.open_order_id, 'dry_run') assert trade.open_order_id == 'dry_run'
def test_3_close_trade(self): def test_close_trade(conf, mocker):
with patch.dict('freqtrade.main._CONF', self.conf): mocker.patch.dict('freqtrade.main._CONF', conf)
trade = Trade.query.filter(Trade.is_open.is_(True)).first() trade = Trade.query.filter(Trade.is_open.is_(True)).first()
self.assertTrue(trade) assert trade
# Simulate that there is no open order # Simulate that there is no open order
trade.open_order_id = None trade.open_order_id = None
closed = close_trade_if_fulfilled(trade) closed = close_trade_if_fulfilled(trade)
self.assertTrue(closed) assert closed
self.assertEqual(trade.is_open, False) assert not trade.is_open
def test_balance_fully_ask_side(self): def test_balance_fully_ask_side(mocker):
with patch.dict('freqtrade.main._CONF', {'bid_strategy': {'ask_last_balance': 0.0}}): mocker.patch.dict('freqtrade.main._CONF', {'bid_strategy': {'ask_last_balance': 0.0}})
self.assertEqual(get_target_bid({'ask': 20, 'last': 10}), 20) assert get_target_bid({'ask': 20, 'last': 10}) == 20
def test_balance_fully_last_side(self): def test_balance_fully_last_side(mocker):
with patch.dict('freqtrade.main._CONF', {'bid_strategy': {'ask_last_balance': 1.0}}): mocker.patch.dict('freqtrade.main._CONF', {'bid_strategy': {'ask_last_balance': 1.0}})
self.assertEqual(get_target_bid({'ask': 20, 'last': 10}), 10) assert get_target_bid({'ask': 20, 'last': 10}) == 10
def test_balance_when_last_bigger_than_ask(self): def test_balance_when_last_bigger_than_ask(mocker):
with patch.dict('freqtrade.main._CONF', {'bid_strategy': {'ask_last_balance': 1.0}}): mocker.patch.dict('freqtrade.main._CONF', {'bid_strategy': {'ask_last_balance': 1.0}})
self.assertEqual(get_target_bid({'ask': 5, 'last': 10}), 5) assert get_target_bid({'ask': 5, 'last': 10}) == 5
@classmethod
def setUpClass(cls):
validate(cls.conf, CONF_SCHEMA)
if __name__ == '__main__':
unittest.main()

View File

@ -1,13 +1,9 @@
import unittest # pragma pylint: disable=missing-docstring
from unittest.mock import patch
from freqtrade.exchange import Exchange from freqtrade.exchange import Exchange
from freqtrade.persistence import Trade from freqtrade.persistence import Trade
def test_exec_sell_order(mocker):
class TestTrade(unittest.TestCase): api_mock = mocker.patch('freqtrade.main.exchange.sell', side_effect='mocked_order_id')
def test_1_exec_sell_order(self):
with patch('freqtrade.main.exchange.sell', side_effect='mocked_order_id') as api_mock:
trade = Trade( trade = Trade(
pair='BTC_ETH', pair='BTC_ETH',
stake_amount=1.00, stake_amount=1.00,
@ -18,11 +14,7 @@ class TestTrade(unittest.TestCase):
) )
profit = trade.exec_sell_order(1.00, 10.00) profit = trade.exec_sell_order(1.00, 10.00)
api_mock.assert_called_once_with('BTC_ETH', 1.0, 10.0) api_mock.assert_called_once_with('BTC_ETH', 1.0, 10.0)
self.assertEqual(profit, 100.0) assert profit == 100.0
self.assertEqual(trade.close_rate, 1.0) assert trade.close_rate == 1.0
self.assertEqual(trade.close_profit, profit) assert trade.close_profit == profit
self.assertIsNotNone(trade.close_date) assert trade.close_date is not None
if __name__ == '__main__':
unittest.main()

View File

@ -1,7 +1,8 @@
import unittest # pragma pylint: disable=missing-docstring
from datetime import datetime from datetime import datetime
from unittest.mock import patch, MagicMock from unittest.mock import MagicMock
import pytest
from jsonschema import validate from jsonschema import validate
from telegram import Bot, Update, Message, Chat from telegram import Bot, Update, Message, Chat
@ -12,13 +13,9 @@ from freqtrade.persistence import Trade
from freqtrade.rpc.telegram import _status, _profit, _forcesell, _performance, _start, _stop from freqtrade.rpc.telegram import _status, _profit, _forcesell, _performance, _start, _stop
class MagicBot(MagicMock, Bot): @pytest.fixture
pass def conf():
configuration = {
class TestTelegram(unittest.TestCase):
conf = {
"max_open_trades": 3, "max_open_trades": 3,
"stake_currency": "BTC", "stake_currency": "BTC",
"stake_amount": 0.05, "stake_amount": 0.05,
@ -46,48 +43,61 @@ class TestTelegram(unittest.TestCase):
}, },
"initial_state": "running" "initial_state": "running"
} }
validate(configuration, CONF_SCHEMA)
return configuration
def test_1_status_handle(self): @pytest.fixture
with patch.dict('freqtrade.main._CONF', self.conf): def update():
with patch('freqtrade.main.get_buy_signal', side_effect=lambda _: True): _update = Update(0)
_update.message = Message(0, 0, datetime.utcnow(), Chat(0, 0))
return _update
class MagicBot(MagicMock, Bot):
pass
def test_status_handle(conf, update, mocker):
mocker.patch.dict('freqtrade.main._CONF', conf)
mocker.patch('freqtrade.main.get_buy_signal', side_effect=lambda _: True)
msg_mock = MagicMock() msg_mock = MagicMock()
with patch.multiple('freqtrade.main.telegram', _CONF=self.conf, init=MagicMock(), send_msg=msg_mock): mocker.patch.multiple('freqtrade.main.telegram', _CONF=conf, init=MagicMock(), send_msg=msg_mock)
with patch.multiple('freqtrade.main.exchange', mocker.patch.multiple('freqtrade.main.exchange',
get_ticker=MagicMock(return_value={ get_ticker=MagicMock(return_value={
'bid': 0.07256061, 'bid': 0.07256061,
'ask': 0.072661, 'ask': 0.072661,
'last': 0.07256061 'last': 0.07256061
}), }),
buy=MagicMock(return_value='mocked_order_id')): buy=MagicMock(return_value='mocked_order_id'))
init(self.conf, 'sqlite://') init(conf, 'sqlite://')
# Create some test data # Create some test data
trade = create_trade(15.0, exchange.Exchange.BITTREX) trade = create_trade(15.0, exchange.Exchange.BITTREX)
self.assertTrue(trade) assert trade
Trade.session.add(trade) Trade.session.add(trade)
Trade.session.flush() Trade.session.flush()
_status(bot=MagicBot(), update=self.update) _status(bot=MagicBot(), update=update)
self.assertEqual(msg_mock.call_count, 2) assert msg_mock.call_count == 2
self.assertIn('[BTC_ETH]', msg_mock.call_args_list[-1][0][0]) assert '[BTC_ETH]' in msg_mock.call_args_list[-1][0][0]
def test_2_profit_handle(self): def test_profit_handle(conf, update, mocker):
with patch.dict('freqtrade.main._CONF', self.conf): mocker.patch.dict('freqtrade.main._CONF', conf)
with patch('freqtrade.main.get_buy_signal', side_effect=lambda _: True): mocker.patch('freqtrade.main.get_buy_signal', side_effect=lambda _: True)
msg_mock = MagicMock() msg_mock = MagicMock()
with patch.multiple('freqtrade.main.telegram', _CONF=self.conf, init=MagicMock(), send_msg=msg_mock): mocker.patch.multiple('freqtrade.main.telegram', _CONF=conf, init=MagicMock(), send_msg=msg_mock)
with patch.multiple('freqtrade.main.exchange', mocker.patch.multiple('freqtrade.main.exchange',
get_ticker=MagicMock(return_value={ get_ticker=MagicMock(return_value={
'bid': 0.07256061, 'bid': 0.07256061,
'ask': 0.072661, 'ask': 0.072661,
'last': 0.07256061 'last': 0.07256061
}), }),
buy=MagicMock(return_value='mocked_order_id')): buy=MagicMock(return_value='mocked_order_id'))
init(self.conf, 'sqlite://') init(conf, 'sqlite://')
# Create some test data # Create some test data
trade = create_trade(15.0, exchange.Exchange.BITTREX) trade = create_trade(15.0, exchange.Exchange.BITTREX)
self.assertTrue(trade) assert trade
trade.close_rate = 0.07256061 trade.close_rate = 0.07256061
trade.close_profit = 100.00 trade.close_profit = 100.00
trade.close_date = datetime.utcnow() trade.close_date = datetime.utcnow()
@ -96,54 +106,54 @@ class TestTelegram(unittest.TestCase):
Trade.session.add(trade) Trade.session.add(trade)
Trade.session.flush() Trade.session.flush()
_profit(bot=MagicBot(), update=self.update) _profit(bot=MagicBot(), update=update)
self.assertEqual(msg_mock.call_count, 2) assert msg_mock.call_count == 2
self.assertIn('(100.00%)', msg_mock.call_args_list[-1][0][0]) assert '(100.00%)' in msg_mock.call_args_list[-1][0][0]
def test_3_forcesell_handle(self): def test_forcesell_handle(conf, update, mocker):
with patch.dict('freqtrade.main._CONF', self.conf): mocker.patch.dict('freqtrade.main._CONF', conf)
with patch('freqtrade.main.get_buy_signal', side_effect=lambda _: True): mocker.patch('freqtrade.main.get_buy_signal', side_effect=lambda _: True)
msg_mock = MagicMock() msg_mock = MagicMock()
with patch.multiple('freqtrade.main.telegram', _CONF=self.conf, init=MagicMock(), send_msg=msg_mock): mocker.patch.multiple('freqtrade.main.telegram', _CONF=conf, init=MagicMock(), send_msg=msg_mock)
with patch.multiple('freqtrade.main.exchange', mocker.patch.multiple('freqtrade.main.exchange',
get_ticker=MagicMock(return_value={ get_ticker=MagicMock(return_value={
'bid': 0.07256061, 'bid': 0.07256061,
'ask': 0.072661, 'ask': 0.072661,
'last': 0.07256061 'last': 0.07256061
}), }),
buy=MagicMock(return_value='mocked_order_id')): buy=MagicMock(return_value='mocked_order_id'))
init(self.conf, 'sqlite://') init(conf, 'sqlite://')
# Create some test data # Create some test data
trade = create_trade(15.0, exchange.Exchange.BITTREX) trade = create_trade(15.0, exchange.Exchange.BITTREX)
self.assertTrue(trade) assert trade
Trade.session.add(trade) Trade.session.add(trade)
Trade.session.flush() Trade.session.flush()
self.update.message.text = '/forcesell 1' update.message.text = '/forcesell 1'
_forcesell(bot=MagicBot(), update=self.update) _forcesell(bot=MagicBot(), update=update)
self.assertEqual(msg_mock.call_count, 2) assert msg_mock.call_count == 2
self.assertIn('Selling [BTC/ETH]', msg_mock.call_args_list[-1][0][0]) assert 'Selling [BTC/ETH]' in msg_mock.call_args_list[-1][0][0]
self.assertIn('0.072561', 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): def test_performance_handle(conf, update, mocker):
with patch.dict('freqtrade.main._CONF', self.conf): mocker.patch.dict('freqtrade.main._CONF', conf)
with patch('freqtrade.main.get_buy_signal', side_effect=lambda _: True): mocker.patch('freqtrade.main.get_buy_signal', side_effect=lambda _: True)
msg_mock = MagicMock() msg_mock = MagicMock()
with patch.multiple('freqtrade.main.telegram', _CONF=self.conf, init=MagicMock(), send_msg=msg_mock): mocker.patch.multiple('freqtrade.main.telegram', _CONF=conf, init=MagicMock(), send_msg=msg_mock)
with patch.multiple('freqtrade.main.exchange', mocker.patch.multiple('freqtrade.main.exchange',
get_ticker=MagicMock(return_value={ get_ticker=MagicMock(return_value={
'bid': 0.07256061, 'bid': 0.07256061,
'ask': 0.072661, 'ask': 0.072661,
'last': 0.07256061 'last': 0.07256061
}), }),
buy=MagicMock(return_value='mocked_order_id')): buy=MagicMock(return_value='mocked_order_id'))
init(self.conf, 'sqlite://') init(conf, 'sqlite://')
# Create some test data # Create some test data
trade = create_trade(15.0, exchange.Exchange.BITTREX) trade = create_trade(15.0, exchange.Exchange.BITTREX)
self.assertTrue(trade) assert trade
trade.close_rate = 0.07256061 trade.close_rate = 0.07256061
trade.close_profit = 100.00 trade.close_profit = 100.00
trade.close_date = datetime.utcnow() trade.close_date = datetime.utcnow()
@ -152,44 +162,32 @@ class TestTelegram(unittest.TestCase):
Trade.session.add(trade) Trade.session.add(trade)
Trade.session.flush() Trade.session.flush()
_performance(bot=MagicBot(), update=self.update) _performance(bot=MagicBot(), update=update)
self.assertEqual(msg_mock.call_count, 2) assert msg_mock.call_count == 2
self.assertIn('Performance', msg_mock.call_args_list[-1][0][0]) assert 'Performance' in msg_mock.call_args_list[-1][0][0]
self.assertIn('BTC_ETH 100.00%', 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): def test_start_handle(conf, update, mocker):
with patch.dict('freqtrade.main._CONF', self.conf): mocker.patch.dict('freqtrade.main._CONF', conf)
msg_mock = MagicMock() msg_mock = MagicMock()
with patch.multiple('freqtrade.main.telegram', _CONF=self.conf, init=MagicMock(), send_msg=msg_mock): mocker.patch.multiple('freqtrade.main.telegram', _CONF=conf, init=MagicMock(), send_msg=msg_mock)
init(self.conf, 'sqlite://') init(conf, 'sqlite://')
update_state(State.STOPPED) update_state(State.STOPPED)
self.assertEqual(get_state(), State.STOPPED) assert get_state() == State.STOPPED
_start(bot=MagicBot(), update=self.update) _start(bot=MagicBot(), update=update)
self.assertEqual(get_state(), State.RUNNING) assert get_state() == State.RUNNING
self.assertEqual(msg_mock.call_count, 0) assert msg_mock.call_count == 0
def test_6_stop_handle(self): def test_stop_handle(conf, update, mocker):
with patch.dict('freqtrade.main._CONF', self.conf): mocker.patch.dict('freqtrade.main._CONF', conf)
msg_mock = MagicMock() msg_mock = MagicMock()
with patch.multiple('freqtrade.main.telegram', _CONF=self.conf, init=MagicMock(), send_msg=msg_mock): mocker.patch.multiple('freqtrade.main.telegram', _CONF=conf, init=MagicMock(), send_msg=msg_mock)
init(self.conf, 'sqlite://') init(conf, 'sqlite://')
update_state(State.RUNNING) update_state(State.RUNNING)
self.assertEqual(get_state(), State.RUNNING) assert get_state() == State.RUNNING
_stop(bot=MagicBot(), update=self.update) _stop(bot=MagicBot(), update=update)
self.assertEqual(get_state(), State.STOPPED) assert get_state() == State.STOPPED
self.assertEqual(msg_mock.call_count, 1) assert msg_mock.call_count == 1
self.assertIn('Stopping trader', msg_mock.call_args_list[0][0][0]) assert 'Stopping trader' in msg_mock.call_args_list[0][0][0]
def setUp(self):
self.update = Update(0)
self.update.message = Message(0, 0, datetime.utcnow(), Chat(0, 0))
@classmethod
def setUpClass(cls):
validate(cls.conf, CONF_SCHEMA)
if __name__ == '__main__':
unittest.main()

View File

@ -11,6 +11,8 @@ scipy==0.19.1
jsonschema==2.6.0 jsonschema==2.6.0
numpy==1.13.3 numpy==1.13.3
TA-Lib==0.4.10 TA-Lib==0.4.10
pytest==3.2.2
pytest-mock==1.6.3
# Required for plotting data # Required for plotting data
#matplotlib==2.0.2 #matplotlib==2.0.2

View File

@ -1,3 +1,5 @@
[aliases] [aliases]
test=pytest test=pytest
[tool:pytest]
addopts = --pyargs freqtrade

View File

@ -13,7 +13,7 @@ setup(name='freqtrade',
packages=['freqtrade'], packages=['freqtrade'],
scripts=['bin/freqtrade'], scripts=['bin/freqtrade'],
setup_requires=['pytest-runner'], setup_requires=['pytest-runner'],
tests_require=['pytest'], tests_require=['pytest', 'pytest-mock'],
install_requires=[ install_requires=[
'python-bittrex==0.1.3', 'python-bittrex==0.1.3',
'SQLAlchemy==1.1.13', 'SQLAlchemy==1.1.13',