]> git.immae.eu Git - perso/Immae/Projets/Cryptomonnaies/Cryptoportfolio/Trader.git/commitdiff
Move acceptance tests to common directory
authorIsmaël Bouya <ismael.bouya@normalesup.org>
Fri, 20 Apr 2018 18:09:13 +0000 (20:09 +0200)
committerIsmaël Bouya <ismael.bouya@normalesup.org>
Fri, 20 Apr 2018 18:16:18 +0000 (20:16 +0200)
test.py
tests/acceptance.py [moved from test_acceptance.py with 90% similarity]
tests/helper.py
tests/test_acceptance.py [new file with mode: 0644]
tests/test_ccxt_wrapper.py
tests/test_main.py
tests/test_market.py
tests/test_portfolio.py
tests/test_store.py

diff --git a/test.py b/test.py
index 8b9d35b92345889dd8e425fed9438775d0d4937b..d7743b26ec11493b7cc62c51de698fae65842f2d 100644 (file)
--- a/test.py
+++ b/test.py
@@ -1,10 +1,17 @@
 import unittest
+from tests.acceptance import TimeMock
 
-from tests.test_ccxt_wrapper import *
-from tests.test_main import *
-from tests.test_market import *
-from tests.test_store import *
-from tests.test_portfolio import *
+from tests.helper import limits
+
+if "unit" in limits:
+    from tests.test_ccxt_wrapper import *
+    from tests.test_main import *
+    from tests.test_market import *
+    from tests.test_store import *
+    from tests.test_portfolio import *
+
+if "acceptance" in limits:
+    from tests.test_acceptance import *
 
 if __name__ == '__main__':
     unittest.main()
similarity index 90%
rename from test_acceptance.py
rename to tests/acceptance.py
index 3633928c455b5cec8e8cbbeae35b68a44ebd048d..66014ca5b19556a16ee6f7c67adaa54b19c91046 100644 (file)
@@ -2,7 +2,6 @@ import requests
 import requests_mock
 import sys, os
 import time, datetime
-import unittest
 from unittest import mock
 from ssl import SSLError
 from decimal import Decimal
@@ -11,8 +10,56 @@ import psycopg2
 from io import StringIO
 import re
 import functools
-import glob
+import threading
 
+class TimeMock:
+    delta = {}
+    delta_init = 0
+    true_time = time.time
+    true_sleep = time.sleep
+    time_patch = None
+    datetime_patch = None
+
+    @classmethod
+    def travel(cls, start_date):
+        cls.delta = {}
+        cls.delta_init = (datetime.datetime.now() - start_date).total_seconds()
+
+    @classmethod
+    def start(cls):
+        cls.delta = {}
+        cls.delta_init = 0
+
+        class fake_datetime(datetime.datetime):
+            @classmethod
+            def now(cls, tz=None):
+                if tz is None:
+                    return cls.fromtimestamp(time.time())
+                else:
+                    return tz.fromutc(cls.utcfromtimestamp(time.time()).replace(tzinfo=tz))
+
+        cls.time_patch = mock.patch.multiple(time, time=cls.fake_time, sleep=cls.fake_sleep)
+        cls.datetime_patch = mock.patch.multiple(datetime, datetime=fake_datetime)
+        cls.time_patch.start()
+        cls.datetime_patch.start()
+
+    @classmethod
+    def stop(cls):
+        cls.delta = {}
+        cls.delta_init = 0
+
+    @classmethod
+    def fake_time(cls):
+        cls.delta.setdefault(threading.current_thread(), cls.delta_init)
+        return cls.true_time() - cls.delta[threading.current_thread()]
+
+    @classmethod
+    def fake_sleep(cls, duration):
+        cls.delta.setdefault(threading.current_thread(), cls.delta_init)
+        cls.delta[threading.current_thread()] -= float(duration)
+        cls.true_sleep(min(float(duration), 0.1))
+
+TimeMock.start()
 import main
 
 class FileMock:
@@ -51,7 +98,6 @@ class FileMock:
                     if not line.startswith("[Worker] "):
                         self.tester.fail("« {} » not found in log file {}".format(line, split_logs))
     # Le fichier de log est écrit
-    # Le fichier de log est printed uniquement si non quiet
     # Le rapport est écrit si pertinent
     # Le rapport contient le bon nombre de lignes
 
@@ -142,11 +188,16 @@ class RequestsMock:
     def stop(self):
         self.mocker.stop()
 
+    lazy_calls = [
+            "https://cryptoportfolio.io/wp-content/uploads/portfolio/json/cryptoportfolio.json",
+            "https://poloniex.com/public?command=returnTicker",
+            ]
     def check_calls(self):
         self.tester.assertEqual([], self.error_calls)
         for (method, url), elements in self.mocks.items():
             for market_id, element in elements.items():
-                self.tester.assertEqual(0, len(element), "Missing calls to {} {}, market_id {}".format(method, url, market_id))
+                if url not in self.lazy_calls:
+                    self.tester.assertEqual(0, len(element), "Missing calls to {} {}, market_id {}".format(method, url, market_id))
 
     def clean_body(self, body):
         if body is None:
@@ -168,6 +219,8 @@ def callback(self, elements, request, context):
     elif element["response"] is not None:
         self.last_https[element["date"]] = element["response"]
 
+    time.sleep(element.get("duration", 0))
+
     assert self.clean_body(request.body) == \
             self.clean_body(element["body"]), "Body does not match"
     context.status_code = element["status"]
@@ -202,45 +255,6 @@ class GlobalVariablesMock:
         pass
 
 
-class TimeMock:
-    delta = 0
-    true_time = time.time
-    true_sleep = time.sleep
-    time_patch = None
-    datetime_patch = None
-
-    @classmethod
-    def start(cls, start_date):
-        cls.delta = (datetime.datetime.now() - start_date).total_seconds()
-
-        class fake_datetime(datetime.datetime):
-            @classmethod
-            def now(cls, tz=None):
-                if tz is None:
-                    return cls.fromtimestamp(time.time())
-                else:
-                    return tz.fromutc(cls.utcfromtimestamp(time.time()).replace(tzinfo=tz))
-
-        cls.time_patch = mock.patch.multiple(time, time=cls.fake_time, sleep=cls.fake_sleep)
-        cls.datetime_patch = mock.patch.multiple(datetime, datetime=fake_datetime)
-        cls.time_patch.start()
-        cls.datetime_patch.start()
-
-    @classmethod
-    def stop(cls):
-        cls.delta = 0
-        cls.datetime_patch.stop()
-        cls.time_patch.stop()
-
-    @classmethod
-    def fake_time(cls):
-        return cls.true_time() - cls.delta
-
-    @classmethod
-    def fake_sleep(cls, duration):
-        cls.delta -= duration
-        cls.true_sleep(0.2)
-
 class AcceptanceTestCase():
     def parse_file(self, report_file):
         with open(report_file, "rb") as f:
@@ -327,7 +341,7 @@ class AcceptanceTestCase():
         self.requests_mock.start()
         self.file_mock.start()
         self.global_variables_mock.start()
-        TimeMock.start(self.start_date)
+        TimeMock.travel(self.start_date)
 
     def base_test(self):
         main.main(self.config)
@@ -342,20 +356,3 @@ class AcceptanceTestCase():
         self.requests_mock.stop()
         self.database_mock.stop()
 
-for dirfile in glob.glob("tests/acceptance/**/*/", recursive=True):
-    json_files = glob.glob("{}/*.json".format(dirfile))
-    log_files = glob.glob("{}/*.log".format(dirfile))
-    if len(json_files) > 0:
-        name = dirfile.replace("tests/acceptance/", "").replace("/", "_")[0:-1]
-        cname = "".join(list(map(lambda x: x.capitalize(), name.split("_"))))
-
-        globals()[cname] = type(cname,
-                (AcceptanceTestCase,unittest.TestCase), {
-            "log_files": log_files,
-            "files": json_files,
-            "test_{}".format(name): AcceptanceTestCase.base_test
-            })
-
-if __name__ == '__main__':
-    unittest.main()
-
index 4548b169f430ed0abbd6e78ddc1963171fc5e1c9..b85bf3ac58d8967edf0c7d691e3de2870b3f1374 100644 (file)
@@ -6,9 +6,19 @@ import requests_mock
 from io import StringIO
 import portfolio, market, main, store
 
-__all__ = ["unittest", "WebMockTestCase", "mock", "D",
+__all__ = ["limits", "unittest", "WebMockTestCase", "mock", "D",
         "StringIO"]
 
+limits = ["acceptance", "unit"]
+for test_type in limits:
+    if "--no{}".format(test_type) in sys.argv:
+        sys.argv.remove("--no{}".format(test_type))
+        limits.remove(test_type)
+    if "--only{}".format(test_type) in sys.argv:
+        sys.argv.remove("--only{}".format(test_type))
+        limits = [test_type]
+        break
+
 class WebMockTestCase(unittest.TestCase):
     import time
 
diff --git a/tests/test_acceptance.py b/tests/test_acceptance.py
new file mode 100644 (file)
index 0000000..77a6cca
--- /dev/null
@@ -0,0 +1,25 @@
+from .helper import limits
+from tests.acceptance import AcceptanceTestCase
+
+import unittest
+import glob
+
+__all__ = []
+
+for dirfile in glob.glob("tests/acceptance/**/*/", recursive=True):
+    json_files = glob.glob("{}/*.json".format(dirfile))
+    log_files = glob.glob("{}/*.log".format(dirfile))
+    if len(json_files) > 0:
+        name = dirfile.replace("tests/acceptance/", "").replace("/", "_")[0:-1]
+        cname = "".join(list(map(lambda x: x.capitalize(), name.split("_"))))
+
+        globals()[cname] = unittest.skipUnless("acceptance" in limits, "Acceptance skipped")(
+                type(cname, (AcceptanceTestCase, unittest.TestCase), {
+                    "log_files": log_files,
+                    "files": json_files,
+                    "test_{}".format(name): AcceptanceTestCase.base_test
+                    })
+                )
+        __all__.append(cname)
+
+
index 18feab32da53f3252541b116aee3fa13052ba11e..10e334daee0d102aa3997d46201da8c6ee9cc40d 100644 (file)
@@ -1,7 +1,8 @@
-from .helper import unittest, mock, D
+from .helper import limits, unittest, mock, D
 import requests_mock
 import market
 
+@unittest.skipUnless("unit" in limits, "Unit skipped")
 class poloniexETest(unittest.TestCase):
     def setUp(self):
         super().setUp()
index cee89ce6cb35d638914824ca12e85f236aee677f..d2f80297b37f6b499289944d723020e889e01be9 100644 (file)
@@ -1,6 +1,7 @@
 from .helper import *
 import main, market
 
+@unittest.skipUnless("unit" in limits, "Unit skipped")
 class MainTest(WebMockTestCase):
     def test_make_order(self):
         self.m.get_ticker.return_value = {
index fd23162a6c79cf378df7a6ec65a43a85aadcab52..14b23b5db968c6c886209aead82d13b847a067ac 100644 (file)
@@ -2,6 +2,7 @@ from .helper import *
 import market, store, portfolio
 import datetime
 
+@unittest.skipUnless("unit" in limits, "Unit skipped")
 class MarketTest(WebMockTestCase):
     def setUp(self):
         super().setUp()
@@ -729,6 +730,7 @@ class MarketTest(WebMockTestCase):
             store_report.assert_called_once()
  
 
+@unittest.skipUnless("unit" in limits, "Unit skipped")
 class ProcessorTest(WebMockTestCase):
     def test_values(self):
         processor = market.Processor(self.m)
index 14dc9954f63679c03a12a087c2f69102c3109705..4d789965673b9090c0df2ac7d74c0cd81e46d4ce 100644 (file)
@@ -2,6 +2,7 @@ from .helper import *
 import portfolio
 import datetime
 
+@unittest.skipUnless("unit" in limits, "Unit skipped")
 class ComputationTest(WebMockTestCase):
     def test_compute_value(self):
         compute = mock.Mock()
@@ -25,6 +26,7 @@ class ComputationTest(WebMockTestCase):
         portfolio.Computation.compute_value("foo", "bid", compute_value="test")
         compute.assert_called_with("foo", "bid")
 
+@unittest.skipUnless("unit" in limits, "Unit skipped")
 class TradeTest(WebMockTestCase):
 
     def test_values_assertion(self):
@@ -609,6 +611,7 @@ class TradeTest(WebMockTestCase):
         self.assertEqual("ETH", as_json["currency"])
         self.assertEqual("BTC", as_json["base_currency"])
 
+@unittest.skipUnless("unit" in limits, "Unit skipped")
 class BalanceTest(WebMockTestCase):
     def test_values(self):
         balance = portfolio.Balance("BTC", {
@@ -684,6 +687,7 @@ class BalanceTest(WebMockTestCase):
         self.assertEqual(D(0), as_json["margin_available"])
         self.assertEqual(D(0), as_json["margin_borrowed"])
 
+@unittest.skipUnless("unit" in limits, "Unit skipped")
 class OrderTest(WebMockTestCase):
     def test_values(self):
         order = portfolio.Order("buy", portfolio.Amount("ETH", 10),
@@ -1745,6 +1749,7 @@ class OrderTest(WebMockTestCase):
             result = order.retrieve_order()
             self.assertFalse(result)
 
+@unittest.skipUnless("unit" in limits, "Unit skipped")
 class MouvementTest(WebMockTestCase):
     def test_values(self):
         mouvement = portfolio.Mouvement("ETH", "BTC", {
@@ -1802,6 +1807,7 @@ class MouvementTest(WebMockTestCase):
         self.assertEqual("BTC", as_json["base_currency"])
         self.assertEqual("ETH", as_json["currency"])
 
+@unittest.skipUnless("unit" in limits, "Unit skipped")
 class AmountTest(WebMockTestCase):
     def test_values(self):
         amount = portfolio.Amount("BTC", "0.65")
index e281adb3a62d2013d0acd090595263ff843f0461..ffd264555f9116ac09e9e94b31cb64e0cf8fd476 100644 (file)
@@ -4,12 +4,14 @@ import datetime
 import threading
 import market, portfolio, store
 
+@unittest.skipUnless("unit" in limits, "Unit skipped")
 class NoopLockTest(unittest.TestCase):
     def test_with(self):
         noop_lock = store.NoopLock()
         with noop_lock:
             self.assertTrue(True)
 
+@unittest.skipUnless("unit" in limits, "Unit skipped")
 class LockedVarTest(unittest.TestCase):
 
     def test_values(self):
@@ -61,6 +63,7 @@ class LockedVarTest(unittest.TestCase):
         thread3.join()
         self.assertEqual("Bar", locked_var.get()[0:3])
 
+@unittest.skipUnless("unit" in limits, "Unit skipped")
 class TradeStoreTest(WebMockTestCase):
     def test_compute_trades(self):
         self.m.balances.currencies.return_value = ["XMR", "DASH", "XVG", "BTC", "ETH"]
@@ -285,6 +288,7 @@ class TradeStoreTest(WebMockTestCase):
 
         self.assertEqual([trade_mock1, trade_mock2], trade_store.pending)
 
+@unittest.skipUnless("unit" in limits, "Unit skipped")
 class BalanceStoreTest(WebMockTestCase):
     def setUp(self):
         super().setUp()
@@ -437,6 +441,7 @@ class BalanceStoreTest(WebMockTestCase):
         self.assertEqual(1, as_json["BTC"])
         self.assertEqual(2, as_json["ETH"])
 
+@unittest.skipUnless("unit" in limits, "Unit skipped")
 class ReportStoreTest(WebMockTestCase):
     def test_add_log(self):
         with self.subTest(market=self.m):
@@ -997,6 +1002,7 @@ class ReportStoreTest(WebMockTestCase):
             'action': 'Hey'
             })
 
+@unittest.skipUnless("unit" in limits, "Unit skipped")
 class PortfolioTest(WebMockTestCase):
     def setUp(self):
         super().setUp()