+
+ def test_store_report(self):
+
+ file_open = mock.mock_open()
+ with self.subTest(file=None), mock.patch("market.open", file_open):
+ m = market.Market(self.ccxt, user_id=1)
+ m.store_report()
+ file_open.assert_not_called()
+
+ file_open = mock.mock_open()
+ m = market.Market(self.ccxt, report_path="present", user_id=1)
+ with self.subTest(file="present"),\
+ mock.patch("market.open", file_open),\
+ mock.patch.object(m, "report") as report,\
+ mock.patch.object(market, "datetime") as time_mock:
+
+ time_mock.now.return_value = datetime.datetime(2018, 2, 25)
+ report.to_json.return_value = "json_content"
+
+ m.store_report()
+
+ file_open.assert_any_call("present/2018-02-25T00:00:00_1.json", "w")
+ file_open().write.assert_called_once_with("json_content")
+ m.report.to_json.assert_called_once_with()
+
+ m = market.Market(self.ccxt, report_path="error", user_id=1)
+ with self.subTest(file="error"),\
+ mock.patch("market.open") as file_open,\
+ mock.patch('sys.stdout', new_callable=StringIO) as stdout_mock:
+ file_open.side_effect = FileNotFoundError
+
+ m.store_report()
+
+ self.assertRegex(stdout_mock.getvalue(), "impossible to store report file: FileNotFoundError;")
+
+ def test_print_orders(self):
+ m = market.Market(self.ccxt)
+ with mock.patch.object(m.report, "log_stage") as log_stage,\
+ mock.patch.object(m.balances, "fetch_balances") as fetch_balances,\
+ mock.patch.object(m, "prepare_trades") as prepare_trades,\
+ mock.patch.object(m.trades, "prepare_orders") as prepare_orders:
+ m.print_orders()
+
+ log_stage.assert_called_with("print_orders")
+ fetch_balances.assert_called_with(tag="print_orders")
+ prepare_trades.assert_called_with(base_currency="BTC",
+ compute_value="average")
+ prepare_orders.assert_called_with(compute_value="average")
+
+ def test_print_balances(self):
+ m = market.Market(self.ccxt)
+
+ with mock.patch.object(m.balances, "in_currency") as in_currency,\
+ mock.patch.object(m.report, "log_stage") as log_stage,\
+ mock.patch.object(m.balances, "fetch_balances") as fetch_balances,\
+ mock.patch.object(m.report, "print_log") as print_log:
+
+ in_currency.return_value = {
+ "BTC": portfolio.Amount("BTC", "0.65"),
+ "ETH": portfolio.Amount("BTC", "0.3"),
+ }
+
+ m.print_balances()
+
+ log_stage.assert_called_once_with("print_balances")
+ fetch_balances.assert_called_with()
+ print_log.assert_has_calls([
+ mock.call("total:"),
+ mock.call(portfolio.Amount("BTC", "0.95")),
+ ])
+
+ @mock.patch("market.Processor.process")
+ @mock.patch("market.ReportStore.log_error")
+ @mock.patch("market.Market.store_report")
+ def test_process(self, store_report, log_error, process):
+ m = market.Market(self.ccxt)
+ with self.subTest(before=False, after=False):
+ m.process(None)
+
+ process.assert_not_called()
+ store_report.assert_called_once()
+ log_error.assert_not_called()
+
+ process.reset_mock()
+ log_error.reset_mock()
+ store_report.reset_mock()
+ with self.subTest(before=True, after=False):
+ m.process(None, before=True)
+
+ process.assert_called_once_with("sell_all", steps="before")
+ store_report.assert_called_once()
+ log_error.assert_not_called()
+
+ process.reset_mock()
+ log_error.reset_mock()
+ store_report.reset_mock()
+ with self.subTest(before=False, after=True):
+ m.process(None, after=True)
+
+ process.assert_called_once_with("sell_all", steps="after")
+ store_report.assert_called_once()
+ log_error.assert_not_called()
+
+ process.reset_mock()
+ log_error.reset_mock()
+ store_report.reset_mock()
+ with self.subTest(before=True, after=True):
+ m.process(None, before=True, after=True)
+
+ process.assert_has_calls([
+ mock.call("sell_all", steps="before"),
+ mock.call("sell_all", steps="after"),
+ ])
+ store_report.assert_called_once()
+ log_error.assert_not_called()
+
+ process.reset_mock()
+ log_error.reset_mock()
+ store_report.reset_mock()
+ with self.subTest(action="print_balances"),\
+ mock.patch.object(m, "print_balances") as print_balances:
+ m.process(["print_balances"])
+
+ process.assert_not_called()
+ log_error.assert_not_called()
+ store_report.assert_called_once()
+ print_balances.assert_called_once_with()
+
+ log_error.reset_mock()
+ store_report.reset_mock()
+ with self.subTest(action="print_orders"),\
+ mock.patch.object(m, "print_orders") as print_orders,\
+ mock.patch.object(m, "print_balances") as print_balances:
+ m.process(["print_orders", "print_balances"])
+
+ process.assert_not_called()
+ log_error.assert_not_called()
+ store_report.assert_called_once()
+ print_orders.assert_called_once_with()
+ print_balances.assert_called_once_with()
+
+ log_error.reset_mock()
+ store_report.reset_mock()
+ with self.subTest(action="unknown"):
+ m.process(["unknown"])
+ log_error.assert_called_once_with("market_process", message="Unknown action unknown")
+ store_report.assert_called_once()
+
+ log_error.reset_mock()
+ store_report.reset_mock()
+ with self.subTest(unhandled_exception=True):
+ process.side_effect = Exception("bouh")
+
+ m.process(None, before=True)
+ log_error.assert_called_with("market_process", exception=mock.ANY)
+ store_report.assert_called_once()
+