aboutsummaryrefslogtreecommitdiff
path: root/test.py
diff options
context:
space:
mode:
authorIsmaël Bouya <ismael.bouya@normalesup.org>2018-03-23 01:11:34 +0100
committerIsmaël Bouya <ismael.bouya@normalesup.org>2018-03-24 10:39:35 +0100
commitb4e0ba0b0aa84550d0b06338b59557c3050798c9 (patch)
treeec3f6c1d6166e6d3598ecd630aa64853f8842828 /test.py
parent07fa7a4bf8f7a6f799120fb9a5965a09bea6c38e (diff)
downloadTrader-b4e0ba0b0aa84550d0b06338b59557c3050798c9.tar.gz
Trader-b4e0ba0b0aa84550d0b06338b59557c3050798c9.tar.zst
Trader-b4e0ba0b0aa84550d0b06338b59557c3050798c9.zip
Store reports to database
Fixes https://git.immae.eu/mantisbt/view.php?id=57
Diffstat (limited to 'test.py')
-rw-r--r--test.py165
1 files changed, 134 insertions, 31 deletions
diff --git a/test.py b/test.py
index 3ee34c6..5b9c56c 100644
--- a/test.py
+++ b/test.py
@@ -1386,18 +1386,7 @@ class MarketTest(WebMockTestCase):
1386 self.ccxt.transfer_balance.assert_any_call("USDT", 100, "exchange", "margin") 1386 self.ccxt.transfer_balance.assert_any_call("USDT", 100, "exchange", "margin")
1387 self.ccxt.transfer_balance.assert_any_call("ETC", 5, "margin", "exchange") 1387 self.ccxt.transfer_balance.assert_any_call("ETC", 5, "margin", "exchange")
1388 1388
1389 def test_store_report(self): 1389 def test_store_file_report(self):
1390
1391 file_open = mock.mock_open()
1392 m = market.Market(self.ccxt, self.market_args(), user_id=1)
1393 with self.subTest(file=None),\
1394 mock.patch.object(m, "report") as report,\
1395 mock.patch("market.open", file_open):
1396 m.store_report()
1397 report.merge.assert_called_with(store.Portfolio.report)
1398 file_open.assert_not_called()
1399
1400 report.reset_mock()
1401 file_open = mock.mock_open() 1390 file_open = mock.mock_open()
1402 m = market.Market(self.ccxt, self.market_args(), report_path="present", user_id=1) 1391 m = market.Market(self.ccxt, self.market_args(), report_path="present", user_id=1)
1403 with self.subTest(file="present"),\ 1392 with self.subTest(file="present"),\
@@ -1405,20 +1394,16 @@ class MarketTest(WebMockTestCase):
1405 mock.patch.object(m, "report") as report,\ 1394 mock.patch.object(m, "report") as report,\
1406 mock.patch.object(market, "datetime") as time_mock: 1395 mock.patch.object(market, "datetime") as time_mock:
1407 1396
1408 time_mock.now.return_value = datetime.datetime(2018, 2, 25)
1409 report.print_logs = [[time_mock.now(), "Foo"], [time_mock.now(), "Bar"]] 1397 report.print_logs = [[time_mock.now(), "Foo"], [time_mock.now(), "Bar"]]
1410 report.to_json.return_value = "json_content" 1398 report.to_json.return_value = "json_content"
1411 1399
1412 m.store_report() 1400 m.store_file_report(datetime.datetime(2018, 2, 25))
1413 1401
1414 file_open.assert_any_call("present/2018-02-25T00:00:00_1.json", "w") 1402 file_open.assert_any_call("present/2018-02-25T00:00:00_1.json", "w")
1415 file_open.assert_any_call("present/2018-02-25T00:00:00_1.log", "w") 1403 file_open.assert_any_call("present/2018-02-25T00:00:00_1.log", "w")
1416 file_open().write.assert_any_call("json_content") 1404 file_open().write.assert_any_call("json_content")
1417 file_open().write.assert_any_call("Foo\nBar") 1405 file_open().write.assert_any_call("Foo\nBar")
1418 m.report.to_json.assert_called_once_with() 1406 m.report.to_json.assert_called_once_with()
1419 report.merge.assert_called_with(store.Portfolio.report)
1420
1421 report.reset_mock()
1422 1407
1423 m = market.Market(self.ccxt, self.market_args(), report_path="error", user_id=1) 1408 m = market.Market(self.ccxt, self.market_args(), report_path="error", user_id=1)
1424 with self.subTest(file="error"),\ 1409 with self.subTest(file="error"),\
@@ -1427,10 +1412,106 @@ class MarketTest(WebMockTestCase):
1427 mock.patch('sys.stdout', new_callable=StringIO) as stdout_mock: 1412 mock.patch('sys.stdout', new_callable=StringIO) as stdout_mock:
1428 file_open.side_effect = FileNotFoundError 1413 file_open.side_effect = FileNotFoundError
1429 1414
1415 m.store_file_report(datetime.datetime(2018, 2, 25))
1416
1417 self.assertRegex(stdout_mock.getvalue(), "impossible to store report file: FileNotFoundError;")
1418
1419 @mock.patch.object(market, "psycopg2")
1420 def test_store_database_report(self, psycopg2):
1421 connect_mock = mock.Mock()
1422 cursor_mock = mock.MagicMock()
1423
1424 connect_mock.cursor.return_value = cursor_mock
1425 psycopg2.connect.return_value = connect_mock
1426 m = market.Market(self.ccxt, self.market_args(),
1427 pg_config={"config": "pg_config"}, user_id=1)
1428 cursor_mock.fetchone.return_value = [42]
1429
1430 with self.subTest(error=False),\
1431 mock.patch.object(m, "report") as report:
1432 report.to_json_array.return_value = [
1433 ("date1", "type1", "payload1"),
1434 ("date2", "type2", "payload2"),
1435 ]
1436 m.store_database_report(datetime.datetime(2018, 3, 24))
1437 connect_mock.assert_has_calls([
1438 mock.call.cursor(),
1439 mock.call.cursor().execute('INSERT INTO reports("date", "market_config_id", "debug") VALUES (%s, %s, %s) RETURNING id;', (datetime.datetime(2018, 3, 24), None, False)),
1440 mock.call.cursor().fetchone(),
1441 mock.call.cursor().execute('INSERT INTO report_lines("date", "report_id", "type", "payload") VALUES (%s, %s, %s, %s);', ('date1', 42, 'type1', 'payload1')),
1442 mock.call.cursor().execute('INSERT INTO report_lines("date", "report_id", "type", "payload") VALUES (%s, %s, %s, %s);', ('date2', 42, 'type2', 'payload2')),
1443 mock.call.commit(),
1444 mock.call.cursor().close(),
1445 mock.call.close()
1446 ])
1447
1448 connect_mock.reset_mock()
1449 with self.subTest(error=True),\
1450 mock.patch('sys.stdout', new_callable=StringIO) as stdout_mock:
1451 psycopg2.connect.side_effect = Exception("Bouh")
1452 m.store_database_report(datetime.datetime(2018, 3, 24))
1453 self.assertEqual(stdout_mock.getvalue(), "impossible to store report to database: Exception; Bouh\n")
1454
1455 def test_store_report(self):
1456 m = market.Market(self.ccxt, self.market_args(), user_id=1)
1457 with self.subTest(file=None, pg_config=None),\
1458 mock.patch.object(m, "report") as report,\
1459 mock.patch.object(m, "store_database_report") as db_report,\
1460 mock.patch.object(m, "store_file_report") as file_report:
1461 m.store_report()
1462 report.merge.assert_called_with(store.Portfolio.report)
1463
1464 file_report.assert_not_called()
1465 db_report.assert_not_called()
1466
1467 report.reset_mock()
1468 m = market.Market(self.ccxt, self.market_args(), report_path="present", user_id=1)
1469 with self.subTest(file="present", pg_config=None),\
1470 mock.patch.object(m, "report") as report,\
1471 mock.patch.object(m, "store_file_report") as file_report,\
1472 mock.patch.object(m, "store_database_report") as db_report,\
1473 mock.patch.object(market, "datetime") as time_mock:
1474
1475 time_mock.now.return_value = datetime.datetime(2018, 2, 25)
1476
1430 m.store_report() 1477 m.store_report()
1431 1478
1432 report.merge.assert_called_with(store.Portfolio.report) 1479 report.merge.assert_called_with(store.Portfolio.report)
1433 self.assertRegex(stdout_mock.getvalue(), "impossible to store report file: FileNotFoundError;") 1480 file_report.assert_called_once_with(datetime.datetime(2018, 2, 25))
1481 db_report.assert_not_called()
1482
1483 report.reset_mock()
1484 m = market.Market(self.ccxt, self.market_args(), pg_config="present", user_id=1)
1485 with self.subTest(file=None, pg_config="present"),\
1486 mock.patch.object(m, "report") as report,\
1487 mock.patch.object(m, "store_file_report") as file_report,\
1488 mock.patch.object(m, "store_database_report") as db_report,\
1489 mock.patch.object(market, "datetime") as time_mock:
1490
1491 time_mock.now.return_value = datetime.datetime(2018, 2, 25)
1492
1493 m.store_report()
1494
1495 report.merge.assert_called_with(store.Portfolio.report)
1496 file_report.assert_not_called()
1497 db_report.assert_called_once_with(datetime.datetime(2018, 2, 25))
1498
1499 report.reset_mock()
1500 m = market.Market(self.ccxt, self.market_args(),
1501 pg_config="pg_config", report_path="present", user_id=1)
1502 with self.subTest(file="present", pg_config="present"),\
1503 mock.patch.object(m, "report") as report,\
1504 mock.patch.object(m, "store_file_report") as file_report,\
1505 mock.patch.object(m, "store_database_report") as db_report,\
1506 mock.patch.object(market, "datetime") as time_mock:
1507
1508 time_mock.now.return_value = datetime.datetime(2018, 2, 25)
1509
1510 m.store_report()
1511
1512 report.merge.assert_called_with(store.Portfolio.report)
1513 file_report.assert_called_once_with(datetime.datetime(2018, 2, 25))
1514 db_report.assert_called_once_with(datetime.datetime(2018, 2, 25))
1434 1515
1435 def test_print_orders(self): 1516 def test_print_orders(self):
1436 m = market.Market(self.ccxt, self.market_args()) 1517 m = market.Market(self.ccxt, self.market_args())
@@ -3050,6 +3131,14 @@ class ReportStoreTest(WebMockTestCase):
3050 report_store.print_log(portfolio.Amount("BTC", 1)) 3131 report_store.print_log(portfolio.Amount("BTC", 1))
3051 self.assertEqual(stdout_mock.getvalue(), "") 3132 self.assertEqual(stdout_mock.getvalue(), "")
3052 3133
3134 def test_default_json_serial(self):
3135 report_store = market.ReportStore(self.m)
3136
3137 self.assertEqual("2018-02-24T00:00:00",
3138 report_store.default_json_serial(portfolio.datetime(2018, 2, 24)))
3139 self.assertEqual("1.00000000 BTC",
3140 report_store.default_json_serial(portfolio.Amount("BTC", 1)))
3141
3053 def test_to_json(self): 3142 def test_to_json(self):
3054 report_store = market.ReportStore(self.m) 3143 report_store = market.ReportStore(self.m)
3055 report_store.logs.append({"foo": "bar"}) 3144 report_store.logs.append({"foo": "bar"})
@@ -3059,6 +3148,20 @@ class ReportStoreTest(WebMockTestCase):
3059 report_store.logs.append({"amount": portfolio.Amount("BTC", 1)}) 3148 report_store.logs.append({"amount": portfolio.Amount("BTC", 1)})
3060 self.assertEqual('[\n {\n "foo": "bar"\n },\n {\n "date": "2018-02-24T00:00:00"\n },\n {\n "amount": "1.00000000 BTC"\n }\n]', report_store.to_json()) 3149 self.assertEqual('[\n {\n "foo": "bar"\n },\n {\n "date": "2018-02-24T00:00:00"\n },\n {\n "amount": "1.00000000 BTC"\n }\n]', report_store.to_json())
3061 3150
3151 def test_to_json_array(self):
3152 report_store = market.ReportStore(self.m)
3153 report_store.logs.append({
3154 "date": "date1", "type": "type1", "foo": "bar", "bla": "bla"
3155 })
3156 report_store.logs.append({
3157 "date": "date2", "type": "type2", "foo": "bar", "bla": "bla"
3158 })
3159 logs = list(report_store.to_json_array())
3160
3161 self.assertEqual(2, len(logs))
3162 self.assertEqual(("date1", "type1", '{\n "foo": "bar",\n "bla": "bla"\n}'), logs[0])
3163 self.assertEqual(("date2", "type2", '{\n "foo": "bar",\n "bla": "bla"\n}'), logs[1])
3164
3062 @mock.patch.object(market.ReportStore, "print_log") 3165 @mock.patch.object(market.ReportStore, "print_log")
3063 @mock.patch.object(market.ReportStore, "add_log") 3166 @mock.patch.object(market.ReportStore, "add_log")
3064 def test_log_stage(self, add_log, print_log): 3167 def test_log_stage(self, add_log, print_log):
@@ -3552,7 +3655,7 @@ class MainTest(WebMockTestCase):
3552 mock.patch("main.parse_config") as main_parse_config: 3655 mock.patch("main.parse_config") as main_parse_config:
3553 with self.subTest(debug=False): 3656 with self.subTest(debug=False):
3554 main_parse_config.return_value = ["pg_config", "report_path"] 3657 main_parse_config.return_value = ["pg_config", "report_path"]
3555 main_fetch_markets.return_value = [({"key": "market_config"},)] 3658 main_fetch_markets.return_value = [(1, {"key": "market_config"}, 3)]
3556 m = main.get_user_market("config_path.ini", 1) 3659 m = main.get_user_market("config_path.ini", 1)
3557 3660
3558 self.assertIsInstance(m, market.Market) 3661 self.assertIsInstance(m, market.Market)
@@ -3560,7 +3663,7 @@ class MainTest(WebMockTestCase):
3560 3663
3561 with self.subTest(debug=True): 3664 with self.subTest(debug=True):
3562 main_parse_config.return_value = ["pg_config", "report_path"] 3665 main_parse_config.return_value = ["pg_config", "report_path"]
3563 main_fetch_markets.return_value = [({"key": "market_config"},)] 3666 main_fetch_markets.return_value = [(1, {"key": "market_config"}, 3)]
3564 m = main.get_user_market("config_path.ini", 1, debug=True) 3667 m = main.get_user_market("config_path.ini", 1, debug=True)
3565 3668
3566 self.assertIsInstance(m, market.Market) 3669 self.assertIsInstance(m, market.Market)
@@ -3579,16 +3682,16 @@ class MainTest(WebMockTestCase):
3579 args_mock.after = "after" 3682 args_mock.after = "after"
3580 self.assertEqual("", stdout_mock.getvalue()) 3683 self.assertEqual("", stdout_mock.getvalue())
3581 3684
3582 main.process("config", 1, "report_path", args_mock) 3685 main.process(3, "config", 1, "report_path", args_mock, "pg_config")
3583 3686
3584 market_mock.from_config.assert_has_calls([ 3687 market_mock.from_config.assert_has_calls([
3585 mock.call("config", args_mock, user_id=1, report_path="report_path"), 3688 mock.call("config", args_mock, pg_config="pg_config", market_id=3, user_id=1, report_path="report_path"),
3586 mock.call().process("action", before="before", after="after"), 3689 mock.call().process("action", before="before", after="after"),
3587 ]) 3690 ])
3588 3691
3589 with self.subTest(exception=True): 3692 with self.subTest(exception=True):
3590 market_mock.from_config.side_effect = Exception("boo") 3693 market_mock.from_config.side_effect = Exception("boo")
3591 main.process("config", 1, "report_path", args_mock) 3694 main.process(3, "config", 1, "report_path", args_mock, "pg_config")
3592 self.assertEqual("Exception: boo\n", stdout_mock.getvalue()) 3695 self.assertEqual("Exception: boo\n", stdout_mock.getvalue())
3593 3696
3594 def test_main(self): 3697 def test_main(self):
@@ -3606,7 +3709,7 @@ class MainTest(WebMockTestCase):
3606 3709
3607 parse_config.return_value = ["pg_config", "report_path"] 3710 parse_config.return_value = ["pg_config", "report_path"]
3608 3711
3609 fetch_markets.return_value = [["config1", 1], ["config2", 2]] 3712 fetch_markets.return_value = [[3, "config1", 1], [1, "config2", 2]]
3610 3713
3611 main.main(["Foo", "Bar"]) 3714 main.main(["Foo", "Bar"])
3612 3715
@@ -3616,8 +3719,8 @@ class MainTest(WebMockTestCase):
3616 3719
3617 self.assertEqual(2, process.call_count) 3720 self.assertEqual(2, process.call_count)
3618 process.assert_has_calls([ 3721 process.assert_has_calls([
3619 mock.call("config1", 1, "report_path", args_mock), 3722 mock.call(3, "config1", 1, "report_path", args_mock, "pg_config"),
3620 mock.call("config2", 2, "report_path", args_mock), 3723 mock.call(1, "config2", 2, "report_path", args_mock, "pg_config"),
3621 ]) 3724 ])
3622 with self.subTest(parallel=True): 3725 with self.subTest(parallel=True):
3623 with mock.patch("main.parse_args") as parse_args,\ 3726 with mock.patch("main.parse_args") as parse_args,\
@@ -3634,7 +3737,7 @@ class MainTest(WebMockTestCase):
3634 3737
3635 parse_config.return_value = ["pg_config", "report_path"] 3738 parse_config.return_value = ["pg_config", "report_path"]
3636 3739
3637 fetch_markets.return_value = [["config1", 1], ["config2", 2]] 3740 fetch_markets.return_value = [[3, "config1", 1], [1, "config2", 2]]
3638 3741
3639 main.main(["Foo", "Bar"]) 3742 main.main(["Foo", "Bar"])
3640 3743
@@ -3646,9 +3749,9 @@ class MainTest(WebMockTestCase):
3646 self.assertEqual(2, process.call_count) 3749 self.assertEqual(2, process.call_count)
3647 process.assert_has_calls([ 3750 process.assert_has_calls([
3648 mock.call.__bool__(), 3751 mock.call.__bool__(),
3649 mock.call("config1", 1, "report_path", args_mock), 3752 mock.call(3, "config1", 1, "report_path", args_mock, "pg_config"),
3650 mock.call.__bool__(), 3753 mock.call.__bool__(),
3651 mock.call("config2", 2, "report_path", args_mock), 3754 mock.call(1, "config2", 2, "report_path", args_mock, "pg_config"),
3652 ]) 3755 ])
3653 3756
3654 @mock.patch.object(main.sys, "exit") 3757 @mock.patch.object(main.sys, "exit")
@@ -3734,7 +3837,7 @@ class MainTest(WebMockTestCase):
3734 rows = list(main.fetch_markets({"foo": "bar"}, None)) 3837 rows = list(main.fetch_markets({"foo": "bar"}, None))
3735 3838
3736 psycopg2.connect.assert_called_once_with(foo="bar") 3839 psycopg2.connect.assert_called_once_with(foo="bar")
3737 cursor_mock.execute.assert_called_once_with("SELECT config,user_id FROM market_configs") 3840 cursor_mock.execute.assert_called_once_with("SELECT id,config,user_id FROM market_configs")
3738 3841
3739 self.assertEqual(["row_1", "row_2"], rows) 3842 self.assertEqual(["row_1", "row_2"], rows)
3740 3843
@@ -3744,7 +3847,7 @@ class MainTest(WebMockTestCase):
3744 rows = list(main.fetch_markets({"foo": "bar"}, 1)) 3847 rows = list(main.fetch_markets({"foo": "bar"}, 1))
3745 3848
3746 psycopg2.connect.assert_called_once_with(foo="bar") 3849 psycopg2.connect.assert_called_once_with(foo="bar")
3747 cursor_mock.execute.assert_called_once_with("SELECT config,user_id FROM market_configs WHERE user_id = %s", 1) 3850 cursor_mock.execute.assert_called_once_with("SELECT id,config,user_id FROM market_configs WHERE user_id = %s", 1)
3748 3851
3749 self.assertEqual(["row_1", "row_2"], rows) 3852 self.assertEqual(["row_1", "row_2"], rows)
3750 3853