aboutsummaryrefslogtreecommitdiff
path: root/tests/test_market.py
diff options
context:
space:
mode:
Diffstat (limited to 'tests/test_market.py')
-rw-r--r--tests/test_market.py192
1 files changed, 127 insertions, 65 deletions
diff --git a/tests/test_market.py b/tests/test_market.py
index 14b23b5..e3482b8 100644
--- a/tests/test_market.py
+++ b/tests/test_market.py
@@ -530,23 +530,55 @@ class MarketTest(WebMockTestCase):
530 m.store_database_report(datetime.datetime(2018, 3, 24)) 530 m.store_database_report(datetime.datetime(2018, 3, 24))
531 self.assertEqual(stdout_mock.getvalue(), "impossible to store report to database: Exception; Bouh\n") 531 self.assertEqual(stdout_mock.getvalue(), "impossible to store report to database: Exception; Bouh\n")
532 532
533 @mock.patch.object(market, "redis")
534 def test_store_redis_report(self, redis):
535 connect_mock = mock.Mock()
536 redis.Redis.return_value = connect_mock
537
538 m = market.Market(self.ccxt, self.market_args(),
539 redis_config={"config": "redis_config"}, market_id=1)
540
541 with self.subTest(error=False),\
542 mock.patch.object(m, "report") as report:
543 report.to_json_redis.return_value = [
544 ("type1", "payload1"),
545 ("type2", "payload2"),
546 ]
547 m.store_redis_report(datetime.datetime(2018, 3, 24))
548 connect_mock.assert_has_calls([
549 mock.call.set("/cryptoportfolio/1/2018-03-24T00:00:00/type1", "payload1", ex=31*24*60*60),
550 mock.call.set("/cryptoportfolio/1/latest/type1", "payload1"),
551 mock.call.set("/cryptoportfolio/1/2018-03-24T00:00:00/type2", "payload2", ex=31*24*60*60),
552 mock.call.set("/cryptoportfolio/1/latest/type2", "payload2"),
553 ])
554
555 connect_mock.reset_mock()
556 with self.subTest(error=True),\
557 mock.patch('sys.stdout', new_callable=StringIO) as stdout_mock:
558 redis.Redis.side_effect = Exception("Bouh")
559 m.store_redis_report(datetime.datetime(2018, 3, 24))
560 self.assertEqual(stdout_mock.getvalue(), "impossible to store report to redis: Exception; Bouh\n")
561
533 def test_store_report(self): 562 def test_store_report(self):
534 m = market.Market(self.ccxt, self.market_args(report_db=False), user_id=1) 563 m = market.Market(self.ccxt, self.market_args(report_db=False), user_id=1)
535 with self.subTest(file=None, pg_config=None),\ 564 with self.subTest(file=None, pg_config=None),\
536 mock.patch.object(m, "report") as report,\ 565 mock.patch.object(m, "report") as report,\
537 mock.patch.object(m, "store_database_report") as db_report,\ 566 mock.patch.object(m, "store_database_report") as db_report,\
567 mock.patch.object(m, "store_redis_report") as redis_report,\
538 mock.patch.object(m, "store_file_report") as file_report: 568 mock.patch.object(m, "store_file_report") as file_report:
539 m.store_report() 569 m.store_report()
540 report.merge.assert_called_with(store.Portfolio.report) 570 report.merge.assert_called_with(store.Portfolio.report)
541 571
542 file_report.assert_not_called() 572 file_report.assert_not_called()
543 db_report.assert_not_called() 573 db_report.assert_not_called()
574 redis_report.assert_not_called()
544 575
545 report.reset_mock() 576 report.reset_mock()
546 m = market.Market(self.ccxt, self.market_args(report_db=False, report_path="present"), user_id=1) 577 m = market.Market(self.ccxt, self.market_args(report_db=False, report_path="present"), user_id=1)
547 with self.subTest(file="present", pg_config=None),\ 578 with self.subTest(file="present", pg_config=None),\
548 mock.patch.object(m, "report") as report,\ 579 mock.patch.object(m, "report") as report,\
549 mock.patch.object(m, "store_file_report") as file_report,\ 580 mock.patch.object(m, "store_file_report") as file_report,\
581 mock.patch.object(m, "store_redis_report") as redis_report,\
550 mock.patch.object(m, "store_database_report") as db_report,\ 582 mock.patch.object(m, "store_database_report") as db_report,\
551 mock.patch.object(market.datetime, "datetime") as time_mock: 583 mock.patch.object(market.datetime, "datetime") as time_mock:
552 584
@@ -557,12 +589,14 @@ class MarketTest(WebMockTestCase):
557 report.merge.assert_called_with(store.Portfolio.report) 589 report.merge.assert_called_with(store.Portfolio.report)
558 file_report.assert_called_once_with(datetime.datetime(2018, 2, 25)) 590 file_report.assert_called_once_with(datetime.datetime(2018, 2, 25))
559 db_report.assert_not_called() 591 db_report.assert_not_called()
592 redis_report.assert_not_called()
560 593
561 report.reset_mock() 594 report.reset_mock()
562 m = market.Market(self.ccxt, self.market_args(report_db=True, report_path="present"), user_id=1) 595 m = market.Market(self.ccxt, self.market_args(report_db=True, report_path="present"), user_id=1)
563 with self.subTest(file="present", pg_config=None, report_db=True),\ 596 with self.subTest(file="present", pg_config=None, report_db=True),\
564 mock.patch.object(m, "report") as report,\ 597 mock.patch.object(m, "report") as report,\
565 mock.patch.object(m, "store_file_report") as file_report,\ 598 mock.patch.object(m, "store_file_report") as file_report,\
599 mock.patch.object(m, "store_redis_report") as redis_report,\
566 mock.patch.object(m, "store_database_report") as db_report,\ 600 mock.patch.object(m, "store_database_report") as db_report,\
567 mock.patch.object(market.datetime, "datetime") as time_mock: 601 mock.patch.object(market.datetime, "datetime") as time_mock:
568 602
@@ -573,12 +607,14 @@ class MarketTest(WebMockTestCase):
573 report.merge.assert_called_with(store.Portfolio.report) 607 report.merge.assert_called_with(store.Portfolio.report)
574 file_report.assert_called_once_with(datetime.datetime(2018, 2, 25)) 608 file_report.assert_called_once_with(datetime.datetime(2018, 2, 25))
575 db_report.assert_not_called() 609 db_report.assert_not_called()
610 redis_report.assert_not_called()
576 611
577 report.reset_mock() 612 report.reset_mock()
578 m = market.Market(self.ccxt, self.market_args(report_db=True), pg_config="present", user_id=1) 613 m = market.Market(self.ccxt, self.market_args(report_db=True), pg_config="present", user_id=1)
579 with self.subTest(file=None, pg_config="present"),\ 614 with self.subTest(file=None, pg_config="present"),\
580 mock.patch.object(m, "report") as report,\ 615 mock.patch.object(m, "report") as report,\
581 mock.patch.object(m, "store_file_report") as file_report,\ 616 mock.patch.object(m, "store_file_report") as file_report,\
617 mock.patch.object(m, "store_redis_report") as redis_report,\
582 mock.patch.object(m, "store_database_report") as db_report,\ 618 mock.patch.object(m, "store_database_report") as db_report,\
583 mock.patch.object(market.datetime, "datetime") as time_mock: 619 mock.patch.object(market.datetime, "datetime") as time_mock:
584 620
@@ -589,6 +625,7 @@ class MarketTest(WebMockTestCase):
589 report.merge.assert_called_with(store.Portfolio.report) 625 report.merge.assert_called_with(store.Portfolio.report)
590 file_report.assert_not_called() 626 file_report.assert_not_called()
591 db_report.assert_called_once_with(datetime.datetime(2018, 2, 25)) 627 db_report.assert_called_once_with(datetime.datetime(2018, 2, 25))
628 redis_report.assert_not_called()
592 629
593 report.reset_mock() 630 report.reset_mock()
594 m = market.Market(self.ccxt, self.market_args(report_db=True, report_path="present"), 631 m = market.Market(self.ccxt, self.market_args(report_db=True, report_path="present"),
@@ -596,6 +633,7 @@ class MarketTest(WebMockTestCase):
596 with self.subTest(file="present", pg_config="present"),\ 633 with self.subTest(file="present", pg_config="present"),\
597 mock.patch.object(m, "report") as report,\ 634 mock.patch.object(m, "report") as report,\
598 mock.patch.object(m, "store_file_report") as file_report,\ 635 mock.patch.object(m, "store_file_report") as file_report,\
636 mock.patch.object(m, "store_redis_report") as redis_report,\
599 mock.patch.object(m, "store_database_report") as db_report,\ 637 mock.patch.object(m, "store_database_report") as db_report,\
600 mock.patch.object(market.datetime, "datetime") as time_mock: 638 mock.patch.object(market.datetime, "datetime") as time_mock:
601 639
@@ -606,22 +644,54 @@ class MarketTest(WebMockTestCase):
606 report.merge.assert_called_with(store.Portfolio.report) 644 report.merge.assert_called_with(store.Portfolio.report)
607 file_report.assert_called_once_with(datetime.datetime(2018, 2, 25)) 645 file_report.assert_called_once_with(datetime.datetime(2018, 2, 25))
608 db_report.assert_called_once_with(datetime.datetime(2018, 2, 25)) 646 db_report.assert_called_once_with(datetime.datetime(2018, 2, 25))
647 redis_report.assert_not_called()
609 648
610 def test_print_orders(self): 649 report.reset_mock()
611 m = market.Market(self.ccxt, self.market_args()) 650 m = market.Market(self.ccxt, self.market_args(report_redis=False),
612 with mock.patch.object(m.report, "log_stage") as log_stage,\ 651 redis_config="redis_config", user_id=1)
613 mock.patch.object(m.balances, "fetch_balances") as fetch_balances,\ 652 with self.subTest(redis_config="present", report_redis=False),\
614 mock.patch.object(m, "prepare_trades") as prepare_trades,\ 653 mock.patch.object(m, "report") as report,\
615 mock.patch.object(m.trades, "prepare_orders") as prepare_orders: 654 mock.patch.object(m, "store_file_report") as file_report,\
616 m.print_orders() 655 mock.patch.object(m, "store_redis_report") as redis_report,\
656 mock.patch.object(m, "store_database_report") as db_report,\
657 mock.patch.object(market.datetime, "datetime") as time_mock:
617 658
618 log_stage.assert_called_with("print_orders") 659 time_mock.now.return_value = datetime.datetime(2018, 2, 25)
619 fetch_balances.assert_called_with(tag="print_orders")
620 prepare_trades.assert_called_with(base_currency="BTC",
621 compute_value="average")
622 prepare_orders.assert_called_with(compute_value="average")
623 660
624 def test_print_balances(self): 661 m.store_report()
662 redis_report.assert_not_called()
663
664 report.reset_mock()
665 m = market.Market(self.ccxt, self.market_args(report_redis=True),
666 user_id=1)
667 with self.subTest(redis_config="absent", report_redis=True),\
668 mock.patch.object(m, "report") as report,\
669 mock.patch.object(m, "store_file_report") as file_report,\
670 mock.patch.object(m, "store_redis_report") as redis_report,\
671 mock.patch.object(m, "store_database_report") as db_report,\
672 mock.patch.object(market.datetime, "datetime") as time_mock:
673
674 time_mock.now.return_value = datetime.datetime(2018, 2, 25)
675
676 m.store_report()
677 redis_report.assert_not_called()
678
679 report.reset_mock()
680 m = market.Market(self.ccxt, self.market_args(report_redis=True),
681 redis_config="redis_config", user_id=1)
682 with self.subTest(redis_config="present", report_redis=True),\
683 mock.patch.object(m, "report") as report,\
684 mock.patch.object(m, "store_file_report") as file_report,\
685 mock.patch.object(m, "store_redis_report") as redis_report,\
686 mock.patch.object(m, "store_database_report") as db_report,\
687 mock.patch.object(market.datetime, "datetime") as time_mock:
688
689 time_mock.now.return_value = datetime.datetime(2018, 2, 25)
690
691 m.store_report()
692 redis_report.assert_called_once_with(datetime.datetime(2018, 2, 25))
693
694 def test_print_tickers(self):
625 m = market.Market(self.ccxt, self.market_args()) 695 m = market.Market(self.ccxt, self.market_args())
626 696
627 with mock.patch.object(m.balances, "in_currency") as in_currency,\ 697 with mock.patch.object(m.balances, "in_currency") as in_currency,\
@@ -634,10 +704,8 @@ class MarketTest(WebMockTestCase):
634 "ETH": portfolio.Amount("BTC", "0.3"), 704 "ETH": portfolio.Amount("BTC", "0.3"),
635 } 705 }
636 706
637 m.print_balances() 707 m.print_tickers()
638 708
639 log_stage.assert_called_once_with("print_balances")
640 fetch_balances.assert_called_with()
641 print_log.assert_has_calls([ 709 print_log.assert_has_calls([
642 mock.call("total:"), 710 mock.call("total:"),
643 mock.call(portfolio.Amount("BTC", "0.95")), 711 mock.call(portfolio.Amount("BTC", "0.95")),
@@ -648,8 +716,8 @@ class MarketTest(WebMockTestCase):
648 @mock.patch("market.Market.store_report") 716 @mock.patch("market.Market.store_report")
649 def test_process(self, store_report, log_error, process): 717 def test_process(self, store_report, log_error, process):
650 m = market.Market(self.ccxt, self.market_args()) 718 m = market.Market(self.ccxt, self.market_args())
651 with self.subTest(before=False, after=False): 719 with self.subTest(actions=[], before=False, after=False):
652 m.process(None) 720 m.process([])
653 721
654 process.assert_not_called() 722 process.assert_not_called()
655 store_report.assert_called_once() 723 store_report.assert_called_once()
@@ -659,9 +727,9 @@ class MarketTest(WebMockTestCase):
659 log_error.reset_mock() 727 log_error.reset_mock()
660 store_report.reset_mock() 728 store_report.reset_mock()
661 with self.subTest(before=True, after=False): 729 with self.subTest(before=True, after=False):
662 m.process(None, before=True) 730 m.process(["foo"], before=True)
663 731
664 process.assert_called_once_with("sell_all", steps="before") 732 process.assert_called_once_with("foo", steps="before")
665 store_report.assert_called_once() 733 store_report.assert_called_once()
666 log_error.assert_not_called() 734 log_error.assert_not_called()
667 735
@@ -669,7 +737,7 @@ class MarketTest(WebMockTestCase):
669 log_error.reset_mock() 737 log_error.reset_mock()
670 store_report.reset_mock() 738 store_report.reset_mock()
671 with self.subTest(before=False, after=True): 739 with self.subTest(before=False, after=True):
672 m.process(None, after=True) 740 m.process(["sell_all"], after=True)
673 741
674 process.assert_called_once_with("sell_all", steps="after") 742 process.assert_called_once_with("sell_all", steps="after")
675 store_report.assert_called_once() 743 store_report.assert_called_once()
@@ -678,54 +746,30 @@ class MarketTest(WebMockTestCase):
678 process.reset_mock() 746 process.reset_mock()
679 log_error.reset_mock() 747 log_error.reset_mock()
680 store_report.reset_mock() 748 store_report.reset_mock()
681 with self.subTest(before=True, after=True): 749 with self.subTest(before=False, after=False):
682 m.process(None, before=True, after=True) 750 m.process(["foo"])
683 751
684 process.assert_has_calls([ 752 process.assert_called_once_with("foo", steps="all")
685 mock.call("sell_all", steps="before"),
686 mock.call("sell_all", steps="after"),
687 ])
688 store_report.assert_called_once() 753 store_report.assert_called_once()
689 log_error.assert_not_called() 754 log_error.assert_not_called()
690 755
691 process.reset_mock() 756 process.reset_mock()
692 log_error.reset_mock() 757 log_error.reset_mock()
693 store_report.reset_mock() 758 store_report.reset_mock()
694 with self.subTest(action="print_balances"),\ 759 with self.subTest(before=True, after=True):
695 mock.patch.object(m, "print_balances") as print_balances: 760 m.process(["sell_all"], before=True, after=True)
696 m.process(["print_balances"])
697 761
698 process.assert_not_called() 762 process.assert_called_once_with("sell_all", steps="all")
699 log_error.assert_not_called()
700 store_report.assert_called_once() 763 store_report.assert_called_once()
701 print_balances.assert_called_once_with()
702
703 log_error.reset_mock()
704 store_report.reset_mock()
705 with self.subTest(action="print_orders"),\
706 mock.patch.object(m, "print_orders") as print_orders,\
707 mock.patch.object(m, "print_balances") as print_balances:
708 m.process(["print_orders", "print_balances"])
709
710 process.assert_not_called()
711 log_error.assert_not_called() 764 log_error.assert_not_called()
712 store_report.assert_called_once()
713 print_orders.assert_called_once_with()
714 print_balances.assert_called_once_with()
715
716 log_error.reset_mock()
717 store_report.reset_mock()
718 with self.subTest(action="unknown"):
719 m.process(["unknown"])
720 log_error.assert_called_once_with("market_process", message="Unknown action unknown")
721 store_report.assert_called_once()
722 765
766 process.reset_mock()
723 log_error.reset_mock() 767 log_error.reset_mock()
724 store_report.reset_mock() 768 store_report.reset_mock()
725 with self.subTest(unhandled_exception=True): 769 with self.subTest(unhandled_exception=True):
726 process.side_effect = Exception("bouh") 770 process.side_effect = Exception("bouh")
727 771
728 m.process(None, before=True) 772 m.process(["some_action"], before=True)
729 log_error.assert_called_with("market_process", exception=mock.ANY) 773 log_error.assert_called_with("market_process", exception=mock.ANY)
730 store_report.assert_called_once() 774 store_report.assert_called_once()
731 775
@@ -768,24 +812,39 @@ class ProcessorTest(WebMockTestCase):
768 with self.assertRaises(TypeError): 812 with self.assertRaises(TypeError):
769 processor.select_steps(scenario, ["wait"]) 813 processor.select_steps(scenario, ["wait"])
770 814
815 def test_can_process(self):
816 processor = market.Processor(self.m)
817
818 with self.subTest(True):
819 self.assertTrue(processor.can_process("sell_all"))
820
821 with self.subTest(False):
822 self.assertFalse(processor.can_process("unknown_action"))
823
771 @mock.patch("market.Processor.process_step") 824 @mock.patch("market.Processor.process_step")
772 def test_process(self, process_step): 825 def test_process(self, process_step):
773 processor = market.Processor(self.m) 826 with self.subTest("unknown action"):
827 processor = market.Processor(self.m)
828 with self.assertRaises(TypeError):
829 processor.process("unknown_action")
774 830
775 processor.process("sell_all", foo="bar") 831 with self.subTest("nominal case"):
776 self.assertEqual(3, process_step.call_count) 832 processor = market.Processor(self.m)
777 833
778 steps = list(map(lambda x: x[1][1]["name"], process_step.mock_calls)) 834 processor.process("sell_all", foo="bar")
779 scenario_names = list(map(lambda x: x[1][0], process_step.mock_calls)) 835 self.assertEqual(3, process_step.call_count)
780 kwargs = list(map(lambda x: x[1][2], process_step.mock_calls))
781 self.assertEqual(["all_sell", "wait", "all_buy"], steps)
782 self.assertEqual(["sell_all", "sell_all", "sell_all"], scenario_names)
783 self.assertEqual([{"foo":"bar"}, {"foo":"bar"}, {"foo":"bar"}], kwargs)
784 836
785 process_step.reset_mock() 837 steps = list(map(lambda x: x[1][1]["name"], process_step.mock_calls))
838 scenario_names = list(map(lambda x: x[1][0], process_step.mock_calls))
839 kwargs = list(map(lambda x: x[1][2], process_step.mock_calls))
840 self.assertEqual(["all_sell", "wait", "all_buy"], steps)
841 self.assertEqual(["sell_all", "sell_all", "sell_all"], scenario_names)
842 self.assertEqual([{"foo":"bar"}, {"foo":"bar"}, {"foo":"bar"}], kwargs)
786 843
787 processor.process("sell_needed", steps=["before", "after"]) 844 process_step.reset_mock()
788 self.assertEqual(3, process_step.call_count) 845
846 processor.process("sell_needed", steps=["before", "after"])
847 self.assertEqual(3, process_step.call_count)
789 848
790 def test_method_arguments(self): 849 def test_method_arguments(self):
791 ccxt = mock.Mock(spec=market.ccxt.poloniexE) 850 ccxt = mock.Mock(spec=market.ccxt.poloniexE)
@@ -816,6 +875,9 @@ class ProcessorTest(WebMockTestCase):
816 method, arguments = processor.method_arguments("close_trades") 875 method, arguments = processor.method_arguments("close_trades")
817 self.assertEqual(m.trades.close_trades, method) 876 self.assertEqual(m.trades.close_trades, method)
818 877
878 method, arguments = processor.method_arguments("print_tickers")
879 self.assertEqual(m.print_tickers, method)
880
819 def test_process_step(self): 881 def test_process_step(self):
820 processor = market.Processor(self.m) 882 processor = market.Processor(self.m)
821 883