|
|
@@ -0,0 +1,127 @@
|
|
|
+'''
|
|
|
+
|
|
|
+@author: olivier.massot, 2018
|
|
|
+'''
|
|
|
+import inspect
|
|
|
+import sys
|
|
|
+
|
|
|
+
|
|
|
+UNKNOWN = 0
|
|
|
+SUCCESS = 1
|
|
|
+FAILURE = 2
|
|
|
+ERROR = 3
|
|
|
+
|
|
|
+_result_to_str = {UNKNOWN: 'Inconnu',
|
|
|
+ SUCCESS: 'Succès',
|
|
|
+ FAILURE: 'Echec',
|
|
|
+ ERROR: 'Erreur'}
|
|
|
+
|
|
|
+class TestError():
|
|
|
+ def __init__(self, message, info = {}, critical=False):
|
|
|
+ self.message = message
|
|
|
+ self.info = info
|
|
|
+ self.critical = critical
|
|
|
+
|
|
|
+ def __repr__(self):
|
|
|
+ return f"TestError<message='{self.message}'; info={self.info}; critical={self.critical}>"
|
|
|
+
|
|
|
+class TestResult():
|
|
|
+ def __init__(self, test):
|
|
|
+ self._test = test
|
|
|
+ self._name = ""
|
|
|
+ self._status = UNKNOWN
|
|
|
+ self.errors = []
|
|
|
+ self._exc_info = None
|
|
|
+
|
|
|
+ @property
|
|
|
+ def name(self):
|
|
|
+ return self._name or self._test.__name__[5:]
|
|
|
+
|
|
|
+ @property
|
|
|
+ def title(self):
|
|
|
+ return self._test.__doc__.split("\n")[0].strip()
|
|
|
+
|
|
|
+ @property
|
|
|
+ def description(self):
|
|
|
+ return self._test.__doc__.strip()
|
|
|
+
|
|
|
+ @property
|
|
|
+ def status(self):
|
|
|
+ return self._status
|
|
|
+
|
|
|
+ @property
|
|
|
+ def status_str(self):
|
|
|
+ return _result_to_str[self._status]
|
|
|
+
|
|
|
+ def __repr__(self):
|
|
|
+ return f"TestResult<title='{self.title}'; status={self.status}; name={self.name}; method={self._test.__name__}; errors_count={len(self.errors)}>"
|
|
|
+
|
|
|
+ def log_error(self, message, info={}):
|
|
|
+ self._status = FAILURE
|
|
|
+ error = TestError(message, info)
|
|
|
+ self.errors.append(error)
|
|
|
+
|
|
|
+ def handle_exception(self):
|
|
|
+ self._status = ERROR
|
|
|
+ error = TestError("Une erreur inconnue s'est produite, veuillez consulter les fichiers de journalisation.",
|
|
|
+ {"exc_info": sys.exc_info()})
|
|
|
+ self.errors.append(error)
|
|
|
+
|
|
|
+class BaseChecker():
|
|
|
+
|
|
|
+ def __init__(self):
|
|
|
+ self._test_running = None
|
|
|
+
|
|
|
+ def setUp(self):
|
|
|
+ pass
|
|
|
+
|
|
|
+ def tearDown(self):
|
|
|
+ pass
|
|
|
+
|
|
|
+ def log_error(self, message, info):
|
|
|
+ self._test_running.log_error(message, info)
|
|
|
+
|
|
|
+ def run(self):
|
|
|
+
|
|
|
+ tests_results = []
|
|
|
+
|
|
|
+ for mname, m in inspect.getmembers(self, predicate=inspect.ismethod):
|
|
|
+ if mname[:5] == 'test_':
|
|
|
+
|
|
|
+ r = TestResult(m)
|
|
|
+
|
|
|
+ self._test_running = r
|
|
|
+
|
|
|
+ self.setUp()
|
|
|
+
|
|
|
+ try:
|
|
|
+ m()
|
|
|
+ except:
|
|
|
+ r.handle_exception()
|
|
|
+
|
|
|
+ self.tearDown()
|
|
|
+
|
|
|
+ tests_results.append(r)
|
|
|
+
|
|
|
+ return tests_results
|
|
|
+
|
|
|
+ def test_a(self):
|
|
|
+ """ Contrôle des données 1 """
|
|
|
+ for i in range(10):
|
|
|
+ self.log_error(f"error-{i}", {"i": i})
|
|
|
+
|
|
|
+ def test_b(self):
|
|
|
+ """ Contrôle des données 2
|
|
|
+ bla bla bla """
|
|
|
+ return True
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+if __name__ == '__main__':
|
|
|
+ ch = BaseChecker()
|
|
|
+ results = ch.run()
|
|
|
+
|
|
|
+ for r in results:
|
|
|
+ print(r)
|
|
|
+ for e in r.errors:
|
|
|
+ print(e)
|