init
This commit is contained in:
6
backend-django/backend/tests/utils/__init__.py
Normal file
6
backend-django/backend/tests/utils/__init__.py
Normal file
@@ -0,0 +1,6 @@
|
||||
from .alimentation import *
|
||||
from .decisions import *
|
||||
from .decorators import *
|
||||
from .functions import *
|
||||
from .logging import *
|
||||
from .predicates import *
|
||||
56
backend-django/backend/tests/utils/alimentation.py
Normal file
56
backend-django/backend/tests/utils/alimentation.py
Normal file
@@ -0,0 +1,56 @@
|
||||
from django.test import SimpleTestCase
|
||||
|
||||
from ...utils.alimentation import BOCols as Cols
|
||||
|
||||
|
||||
class BOColsTestCase(SimpleTestCase):
|
||||
""" tests pour BOCols """
|
||||
|
||||
def test_attributes(self):
|
||||
""" vérifie que les nouveaux attributs sont renseignés correctement """
|
||||
|
||||
for col in Cols:
|
||||
self.assertIsInstance(col.value, str, f"{col} : la valeur n'a pas le bon type")
|
||||
|
||||
def test_columns(self):
|
||||
""" vérifie les colonnes renvoyées """
|
||||
members = list(Cols)
|
||||
|
||||
col_names = [col.value for col in members]
|
||||
self.assertCountEqual(col_names, Cols.columns(), "les noms de colonnes (sans argument) ne sont pas les bons")
|
||||
|
||||
col = members[0]
|
||||
col_names = [col.value]
|
||||
self.assertCountEqual(col_names, Cols.columns(col), "les noms de colonnes (un argument) ne sont pas les bons")
|
||||
|
||||
col_list = members[0:2]
|
||||
col_names = [col.value for col in col_list]
|
||||
self.assertCountEqual(col_names, Cols.columns(*col_list), "les noms de colonnes (plusieurs arguments) ne sont pas les bons")
|
||||
|
||||
def test_col_mapping(self):
|
||||
""" vérifie les correspondances renvoyés """
|
||||
|
||||
members = list(Cols)
|
||||
std_mapping = {'a': 1, 'b': 'test'}
|
||||
enum_mapping = {members[0]: (2, 3), members[1]: members[1].name}
|
||||
mapping_before = {**enum_mapping, **std_mapping}
|
||||
mapping_after = Cols.col_mapping(mapping_before)
|
||||
self.assertTrue(all(k in mapping_after for k in std_mapping.keys()), "toutes les clés standard doivent faire partie du mapping final")
|
||||
self.assertTrue(all(v == mapping_after.get(k) for k, v in std_mapping.items()), "les valeurs de clés standard ne doivent pas changer")
|
||||
self.assertTrue(all(k.value in mapping_after for k in enum_mapping.keys()), f"tous les noms de colonnes de clés de type {Cols.__name__} doivent faire partie du mapping final")
|
||||
self.assertTrue(all(v == mapping_after.get(k.value) for k, v in enum_mapping.items()), f"les valeurs de clés de type {Cols.__name__} ne doivent pas changer")
|
||||
|
||||
def test_converters(self):
|
||||
""" vérifie les convertisseurs renvoyés """
|
||||
members = list(Cols)
|
||||
|
||||
col_names = [col.value for col in members if col.converter]
|
||||
self.assertCountEqual(col_names, Cols.converters().keys(), "les convertisseurs (sans argument) ne sont pas les bons")
|
||||
|
||||
col = members[0]
|
||||
col_names = [col.value]
|
||||
self.assertCountEqual(col_names, Cols.converters(col).keys(), "les convertisseurs (un argument) ne sont pas les bons")
|
||||
|
||||
col_list = members[0:2]
|
||||
col_names = [col.value for col in col_list]
|
||||
self.assertCountEqual(col_names, Cols.converters(*col_list).keys(), "les convertisseurs (plusieurs arguments) ne sont pas les bons")
|
||||
283
backend-django/backend/tests/utils/decisions.py
Normal file
283
backend-django/backend/tests/utils/decisions.py
Normal file
@@ -0,0 +1,283 @@
|
||||
from typing import Callable, List, Optional, Tuple, Union
|
||||
from unittest import mock
|
||||
|
||||
from django.test import TestCase
|
||||
|
||||
from ...models import Administre
|
||||
from ...models import AvisPosteChoices as AvisPoste
|
||||
from ...models import CustomUser, Decision, DecisionChoices, Poste, SousVivier
|
||||
from ...models import StatutPamChoices as StatutPam
|
||||
from ...utils.decisions import (DECISIONS, KEY_CHOICES, KEY_CREATE,
|
||||
KEY_PROFILES, KEY_UPDATE, ExtraDecisions,
|
||||
get_all_decisions, get_available_decisions)
|
||||
from ...utils.permissions import (KEY_READ, KEY_WRITE, Profiles,
|
||||
get_profiles_by_adm)
|
||||
|
||||
|
||||
class DecisionsTest(TestCase):
|
||||
|
||||
def setUp(self):
|
||||
""" vérifie qu'il n'existe aucun administré ou poste avant le test """
|
||||
|
||||
self.assertEqual(Administre.objects.exists(), False, "pas d'administré avant un test")
|
||||
self.assertEqual(Poste.objects.exists(), False, "pas de poste avant un test")
|
||||
|
||||
def tearDown(self):
|
||||
""" supprime tous les administrés, les postes, les décisions en fin de test """
|
||||
|
||||
Decision.objects.all().delete()
|
||||
Poste.objects.all().delete()
|
||||
Administre.objects.all().delete()
|
||||
|
||||
def __load_administres(self) -> List[Administre]:
|
||||
""" charge les administrés de la base à partir des IDs """
|
||||
|
||||
self.assertTrue(self.adm_ids, "il est nécessaire de renseigner des IDs d'administrés pour le chargement")
|
||||
return list(Administre.objects.filter(pk__in=self.adm_ids or ()))
|
||||
|
||||
def __setup_decisions(self, decision: Optional[Union[DecisionChoices, ExtraDecisions]]) -> None:
|
||||
""" supprime et recrée (si nécessaire) les postes et les décisions des administrés """
|
||||
|
||||
Decision.objects.all().delete()
|
||||
Poste.objects.all().delete()
|
||||
if decision and decision != ExtraDecisions.EMPTY:
|
||||
for adm_id in self.adm_ids:
|
||||
poste = Poste.objects.create(pk=str(adm_id), p_avis=AvisPoste.P1)
|
||||
Decision.objects.create(administre_id=adm_id, poste=poste, de_decision=decision)
|
||||
|
||||
def __do_for_profiles(self, action: Callable[[Profiles], None], profiles: Tuple[Profiles], decisions: Tuple[Union[DecisionChoices, ExtraDecisions]] = ()) -> None:
|
||||
"""
|
||||
exécute une action (un test) avec un sous-test :
|
||||
- soit pour chaque profil (utilise un mock)
|
||||
- soit pour chaque profil et chaque statut de décision (utilise un mock)
|
||||
implicite : self.adm_ids
|
||||
"""
|
||||
|
||||
def run_subTest(profile: Profiles, decision: Optional[Union[DecisionChoices, ExtraDecisions]] = None) -> None:
|
||||
with self.subTest(profile=profile.name, **({'decision': decision.name} if decision else {})):
|
||||
@mock.patch(
|
||||
f'{get_available_decisions.__module__}.{get_profiles_by_adm.__name__}',
|
||||
return_value={adm_id: {KEY_READ: (), KEY_WRITE: (profile,)} for adm_id in self.adm_ids}
|
||||
)
|
||||
def do_with_profile(mock):
|
||||
action(profile, decision)
|
||||
do_with_profile()
|
||||
|
||||
for p in profiles:
|
||||
if decisions:
|
||||
for decision in decisions:
|
||||
self.__setup_decisions(decision)
|
||||
run_subTest(p, decision)
|
||||
else:
|
||||
run_subTest(p)
|
||||
|
||||
def __assert_common(self, decisions_by_adm):
|
||||
"""
|
||||
assertions communes à propos des décisions renvoyées pour les administrés
|
||||
implicite : self.adm_ids
|
||||
"""
|
||||
|
||||
self.assertIsInstance(decisions_by_adm, dict, "le résultat n'est jamais None")
|
||||
for adm_id in self.adm_ids:
|
||||
self.assertTrue(adm_id in decisions_by_adm, "tous les administrés doivent être présents dans le résultat")
|
||||
|
||||
decisions = decisions_by_adm.get(adm_id)
|
||||
self.assertIsInstance(decisions, dict, "le format des décisions est un dictionnaire")
|
||||
for key in (KEY_CREATE, KEY_UPDATE):
|
||||
self.assertTrue(key in decisions, f"les décisions doivent contenir la clé {key}")
|
||||
self.assertIsInstance(decisions.get(key), tuple, f"la valeur de {key} des décisions n'a pas le type attendu")
|
||||
|
||||
def test_tree_attribute(self):
|
||||
""" vérifie que le comportement reste correct avec l'ajout de nouveaux attributs """
|
||||
|
||||
attr_trees = 'trees'
|
||||
for choice in DecisionChoices:
|
||||
self.assertIsInstance(choice.label, str, f"{choice} : le libellé n'a pas le bon type")
|
||||
self.assertIsInstance(choice.value, str, f"{choice} : la valeur n'a pas le bon type")
|
||||
self.assertEqual(choice.value, choice, f"{choice} : n'est pas égal à sa valeur")
|
||||
self.assertIsInstance(getattr(choice, attr_trees), tuple, f"{choice} : l'attribut {attr_trees} n'a pas le bon type")
|
||||
|
||||
def test_champ_decisions(self):
|
||||
""" vérifie la structure de DECISIONS """
|
||||
|
||||
to_test = DECISIONS
|
||||
|
||||
self.assertIsInstance(to_test, dict, "la structure n'a pas le type attendu")
|
||||
self.assertTrue(to_test, "la structure ne doit pas être vide")
|
||||
|
||||
for key, value in to_test.items():
|
||||
self.assertTrue(key is None or isinstance(key, DecisionChoices), f"la décision {key} n'a pas le type attendu")
|
||||
self.assertIsInstance(value, dict, f"la valeur pour la décision {key} n'a pas le type attendu")
|
||||
|
||||
profiles = value.get(KEY_PROFILES)
|
||||
self.assertTrue(profiles is None or isinstance(profiles, tuple), f"la valeur de {KEY_PROFILES} de la valeur pour la décision {key} n'a pas le type attendu")
|
||||
for p in profiles:
|
||||
self.assertIsInstance(p, Profiles, f"un élément de la clé {KEY_PROFILES} de la valeur pour la décision {key} n'a pas le type attendu")
|
||||
|
||||
choices = value.get(KEY_CHOICES)
|
||||
self.assertTrue(choices is None or isinstance(choices, tuple), f"la valeur de {KEY_CHOICES} de la valeur pour la décision {key} n'a pas le type attendu")
|
||||
for c in choices:
|
||||
self.assertIsInstance(c, (DecisionChoices, ExtraDecisions), f"un élément de la clé {KEY_CHOICES} de la valeur pour la décision {key} n'a pas le type attendu")
|
||||
|
||||
def test_get_all_decisions(self):
|
||||
""" vérifie les valeurs de get_all_decisions """
|
||||
|
||||
to_test = get_all_decisions()
|
||||
|
||||
self.assertIsInstance(to_test, tuple, "le résultat n'a pas le type attendu")
|
||||
self.assertTrue(to_test, "le résultat ne doit pas être vide")
|
||||
|
||||
for value in to_test:
|
||||
self.assertIsInstance(value, DecisionChoices, f"la valeur {value} n'a pas le type attendu")
|
||||
|
||||
def test_pam_wihout_choice(self):
|
||||
""" pour ces statuts PAM il n'y a aucun choix """
|
||||
|
||||
user = CustomUser()
|
||||
self.adm_ids = tuple(a.a_id_sap for a in (
|
||||
Administre.objects.create(pk=i + 1, a_statut_pam=status) for i, status in enumerate(StatutPam) if not status.dec_enabled
|
||||
))
|
||||
|
||||
def action(_p, _d):
|
||||
decisions_by_adm = get_available_decisions(self.__load_administres(), user=user)
|
||||
|
||||
self.__assert_common(decisions_by_adm)
|
||||
for adm_id in self.adm_ids:
|
||||
decisions = decisions_by_adm.get(adm_id)
|
||||
self.assertFalse(decisions.get(KEY_CREATE))
|
||||
self.assertFalse(decisions.get(KEY_UPDATE))
|
||||
|
||||
self.__do_for_profiles(action, profiles=tuple(Profiles))
|
||||
|
||||
def test_pam_with_choices(self):
|
||||
""" pour ces statuts PAM c'est l'arbre de décision qui est utilisé """
|
||||
|
||||
user = CustomUser()
|
||||
self.adm_ids = tuple(a.a_id_sap for a in (
|
||||
Administre.objects.create(pk=i + 1, a_statut_pam=status) for i, status in enumerate(StatutPam) if status.dec_enabled
|
||||
))
|
||||
D = DecisionChoices
|
||||
EX = ExtraDecisions
|
||||
|
||||
def action(p, d):
|
||||
decisions_by_adm = get_available_decisions(self.__load_administres(), user=user)
|
||||
|
||||
self.__assert_common(decisions_by_adm)
|
||||
for adm_id in self.adm_ids:
|
||||
decisions = decisions_by_adm.get(adm_id)
|
||||
|
||||
# create
|
||||
decisions_create = decisions.get(KEY_CREATE)
|
||||
if p == Profiles.FILIERE:
|
||||
self.assertCountEqual(decisions_create, (D.PROPOSITION_FE, D.HME_PROPOSITION_VIVIER))
|
||||
else:
|
||||
self.assertFalse(decisions_create)
|
||||
|
||||
# update
|
||||
decisions_update = decisions.get(KEY_UPDATE)
|
||||
if not d and p == Profiles.FILIERE:
|
||||
self.assertCountEqual(decisions_update, (D.PROPOSITION_FE, D.HME_PROPOSITION_VIVIER))
|
||||
|
||||
elif d == D.PROPOSITION_FE and p in (Profiles.PCP, Profiles.PCP_ACTUEL):
|
||||
self.assertCountEqual(decisions_update, (D.DIALOGUE_EN_COURS, D.FOREMP_EN_COURS))
|
||||
|
||||
elif d == D.DIALOGUE_EN_COURS and p in (Profiles.PCP, Profiles.PCP_ACTUEL):
|
||||
self.assertCountEqual(decisions_update, (D.DIALOGUE_TERMINE, D.DIALOGUE_INFRUCTUEUX))
|
||||
|
||||
elif d == D.DIALOGUE_TERMINE and p in (Profiles.PCP, Profiles.PCP_ACTUEL):
|
||||
self.assertCountEqual(decisions_update, (D.FOREMP_EN_COURS,))
|
||||
|
||||
elif d == D.DIALOGUE_INFRUCTUEUX and p in (Profiles.PCP, Profiles.PCP_ACTUEL):
|
||||
self.assertCountEqual(decisions_update, (D.FOREMP_EN_COURS, D.REMIS_A_DISPOSITION))
|
||||
|
||||
elif d == D.FOREMP_EN_COURS and p in (Profiles.PCP, Profiles.PCP_ACTUEL):
|
||||
self.assertCountEqual(decisions_update, (D.FOREMP_TERMINE,))
|
||||
|
||||
elif d == D.FOREMP_TERMINE and p in (Profiles.PCP, Profiles.PCP_ACTUEL):
|
||||
self.assertCountEqual(decisions_update, (D.PREPOSITIONNE, D.REMIS_A_DISPOSITION))
|
||||
|
||||
elif d == D.PREPOSITIONNE and p in (Profiles.PCP, Profiles.PCP_FUTUR):
|
||||
self.assertCountEqual(decisions_update, (D.POSITIONNE, D.REMIS_A_DISPOSITION))
|
||||
|
||||
elif d == D.POSITIONNE and p in (Profiles.PCP, Profiles.PCP_FUTUR):
|
||||
self.assertCountEqual(decisions_update, (D.OMIP_EN_COURS, D.OMI_EN_COURS, D.REMIS_A_DISPOSITION))
|
||||
|
||||
elif d == D.OMIP_EN_COURS and p in (Profiles.PCP, Profiles.PCP_FUTUR):
|
||||
self.assertCountEqual(decisions_update, (D.OMIP_TERMINE, D.REMIS_A_DISPOSITION))
|
||||
|
||||
elif d == D.OMIP_TERMINE and p in (Profiles.PCP, Profiles.PCP_FUTUR):
|
||||
self.assertCountEqual(decisions_update, (D.ATTENTE_AVIONAGE, D.OMI_EN_COURS, D.REMIS_A_DISPOSITION))
|
||||
|
||||
elif d == D.ATTENTE_AVIONAGE and p in (Profiles.PCP, Profiles.PCP_FUTUR):
|
||||
self.assertCountEqual(decisions_update, (D.OMI_EN_COURS,))
|
||||
|
||||
elif d == D.OMI_EN_COURS and p in (Profiles.PCP, Profiles.PCP_FUTUR):
|
||||
self.assertCountEqual(decisions_update, (D.OMI_ACTIVE, D.REMIS_A_DISPOSITION))
|
||||
|
||||
elif d == D.OMI_ACTIVE and p in (Profiles.PCP, Profiles.PCP_FUTUR):
|
||||
self.assertCountEqual(decisions_update, (D.OMI_ANNULE,))
|
||||
|
||||
elif d == D.OMI_ANNULE and p in (Profiles.PCP, Profiles.PCP_FUTUR):
|
||||
self.assertCountEqual(decisions_update, (D.REMIS_A_DISPOSITION,))
|
||||
|
||||
elif d == D.REMIS_A_DISPOSITION and p == Profiles.FILIERE:
|
||||
self.assertCountEqual(decisions_update, (EX.EMPTY,))
|
||||
|
||||
elif d == D.HME_PROPOSITION_VIVIER and p in (Profiles.PCP, Profiles.PCP_ACTUEL, Profiles.PCP_FUTUR):
|
||||
self.assertCountEqual(decisions_update, (D.HME_DIALOGUE_INITIE,))
|
||||
|
||||
elif d == D.HME_ETUDE_DESISTEMENT and p in (Profiles.PCP, Profiles.PCP_ACTUEL, Profiles.PCP_FUTUR):
|
||||
self.assertCountEqual(decisions_update, (D.HME_DESISTEMENT,))
|
||||
|
||||
elif d == D.HME_DESISTEMENT and p in (Profiles.PCP, Profiles.PCP_ACTUEL, Profiles.PCP_FUTUR):
|
||||
self.assertCountEqual(decisions_update, (D.REMIS_A_DISPOSITION,))
|
||||
|
||||
elif d == D.HME_DIALOGUE_INITIE and p in (Profiles.PCP, Profiles.PCP_ACTUEL, Profiles.PCP_FUTUR):
|
||||
self.assertCountEqual(decisions_update, (D.HME_DIALOGUE_EN_COURS,))
|
||||
|
||||
elif d == D.HME_DIALOGUE_EN_COURS and p in (Profiles.PCP, Profiles.PCP_ACTUEL, Profiles.PCP_FUTUR):
|
||||
self.assertCountEqual(decisions_update, (D.HME_DIALOGUE_TERMINE, D.HME_DIALOGUE_INFRUCTUEUX))
|
||||
|
||||
elif d == D.HME_DIALOGUE_TERMINE and p in (Profiles.PCP, Profiles.PCP_ACTUEL, Profiles.PCP_FUTUR):
|
||||
self.assertCountEqual(decisions_update, (D.HME_PREPOSITIONNE,))
|
||||
|
||||
elif d == D.HME_DIALOGUE_INFRUCTUEUX and p in (Profiles.PCP, Profiles.PCP_ACTUEL, Profiles.PCP_FUTUR):
|
||||
self.assertCountEqual(decisions_update, (D.HME_ETUDE_DESISTEMENT, D.HME_PREPOSITIONNE, D.REMIS_A_DISPOSITION))
|
||||
|
||||
elif d == D.HME_FOREMP_EN_COURS and p in (Profiles.PCP, Profiles.PCP_ACTUEL, Profiles.PCP_FUTUR):
|
||||
self.assertCountEqual(decisions_update, (D.HME_FOREMP_TERMINE, D.HME_OMI_EN_COURS))
|
||||
|
||||
elif d == D.HME_FOREMP_TERMINE and p in (Profiles.PCP, Profiles.PCP_ACTUEL, Profiles.PCP_FUTUR):
|
||||
self.assertCountEqual(decisions_update, (D.HME_OMIP_EN_COURS, D.HME_OMI_EN_COURS))
|
||||
|
||||
elif d == D.HME_PREPOSITIONNE and p == Profiles.HME:
|
||||
self.assertCountEqual(decisions_update, (D.HME_VALIDATION_EXPERT, D.HME_REFUS_EXPERT))
|
||||
|
||||
elif d == D.HME_POSITIONNE and p in (Profiles.PCP, Profiles.PCP_ACTUEL, Profiles.PCP_FUTUR):
|
||||
self.assertCountEqual(decisions_update, (D.HME_OMIP_EN_COURS, D.HME_OMI_EN_COURS, D.HME_FOREMP_EN_COURS))
|
||||
|
||||
elif d == D.HME_VALIDATION_EXPERT and p in (Profiles.PCP, Profiles.PCP_ACTUEL, Profiles.PCP_FUTUR):
|
||||
self.assertCountEqual(decisions_update, (D.HME_POSITIONNE,))
|
||||
|
||||
elif d == D.HME_REFUS_EXPERT and p in (Profiles.PCP, Profiles.PCP_ACTUEL, Profiles.PCP_FUTUR):
|
||||
self.assertCountEqual(decisions_update, (D.HME_PREPOSITIONNE, D.REMIS_A_DISPOSITION))
|
||||
|
||||
elif d == D.HME_OMIP_EN_COURS and p in (Profiles.PCP, Profiles.PCP_ACTUEL, Profiles.PCP_FUTUR):
|
||||
self.assertCountEqual(decisions_update, (D.HME_OMIP_TERMINE,))
|
||||
|
||||
elif d == D.HME_OMIP_TERMINE and p in (Profiles.PCP, Profiles.PCP_ACTUEL, Profiles.PCP_FUTUR):
|
||||
self.assertCountEqual(decisions_update, (D.HME_ATTENTE_AVIONAGE, D.HME_OMI_EN_COURS))
|
||||
|
||||
elif d == D.HME_ATTENTE_AVIONAGE and p in (Profiles.PCP, Profiles.PCP_ACTUEL, Profiles.PCP_FUTUR):
|
||||
self.assertCountEqual(decisions_update, (D.HME_OMI_EN_COURS,))
|
||||
|
||||
elif d == D.HME_OMI_EN_COURS and p in (Profiles.PCP, Profiles.PCP_ACTUEL, Profiles.PCP_FUTUR):
|
||||
self.assertCountEqual(decisions_update, (D.HME_OMI_ACTIVE,))
|
||||
|
||||
elif d == D.HME_OMI_ACTIVE and p in (Profiles.PCP, Profiles.PCP_ACTUEL, Profiles.PCP_FUTUR):
|
||||
self.assertCountEqual(decisions_update, ())
|
||||
|
||||
else:
|
||||
self.assertFalse(decisions_update)
|
||||
|
||||
self.__do_for_profiles(action, profiles=tuple(Profiles), decisions=(EX.EMPTY, *get_all_decisions()))
|
||||
85
backend-django/backend/tests/utils/decorators.py
Normal file
85
backend-django/backend/tests/utils/decorators.py
Normal file
@@ -0,0 +1,85 @@
|
||||
from .samples import MyClass
|
||||
from ...utils.decorators import class_logger, decorate_functions, CLASS_ATTR_LOGGER
|
||||
from ...utils.functions import find_class
|
||||
from ...utils.logging import get_logger_name
|
||||
from ...utils.predicates import func_name_is_in
|
||||
from django.test import SimpleTestCase
|
||||
from typing import Tuple
|
||||
import functools
|
||||
|
||||
|
||||
def double_result(func):
|
||||
""" décorateur pour doubler les résultats """
|
||||
@functools.wraps(func)
|
||||
def inner(*args, **kwargs):
|
||||
return 2 * func(*args, **kwargs)
|
||||
return inner
|
||||
|
||||
|
||||
class DecoratorTest(SimpleTestCase):
|
||||
|
||||
def test_decorate_functions(self):
|
||||
num = 5
|
||||
a = 1
|
||||
b = 2
|
||||
res = a + b
|
||||
res_x2 = res * 2
|
||||
|
||||
def given():
|
||||
msg = 'le résultat initial est bien celui attendu'
|
||||
self.assertEqual(MyClass.class_met(a, b), res, msg)
|
||||
self.assertEqual(MyClass.static_met(a, b), res, msg)
|
||||
self.assertEqual(MyClass(num).std_met(a, b), res, msg)
|
||||
given()
|
||||
|
||||
# tout est décoré
|
||||
Type = decorate_functions(double_result, lambda func: True)(MyClass)
|
||||
self.assertEqual(Type.class_met(a, b), res_x2)
|
||||
self.assertEqual(Type.static_met(a, b), res_x2)
|
||||
self.assertEqual(Type(num).std_met(a, b), res_x2)
|
||||
|
||||
# une seule méthode est décorée (1ère)
|
||||
Type = decorate_functions(double_result, func_name_is_in(MyClass.class_met.__name__,))(MyClass)
|
||||
self.assertEqual(Type.class_met(a, b), res_x2)
|
||||
self.assertEqual(Type.static_met(a, b), res)
|
||||
self.assertEqual(Type(num).std_met(a, b), res)
|
||||
|
||||
# une seule méthode est décorée (2ème)
|
||||
Type = decorate_functions(double_result, func_name_is_in(MyClass.static_met.__name__,))(MyClass)
|
||||
self.assertEqual(Type.class_met(a, b), res)
|
||||
self.assertEqual(Type.static_met(a, b), res_x2)
|
||||
self.assertEqual(Type(num).std_met(a, b), res)
|
||||
|
||||
# une seule méthode est décorée (3ème)
|
||||
Type = decorate_functions(double_result, func_name_is_in(MyClass.std_met.__name__,))(MyClass)
|
||||
self.assertEqual(Type.class_met(a, b), res)
|
||||
self.assertEqual(Type.static_met(a, b), res)
|
||||
self.assertEqual(Type(num).std_met(a, b), res_x2)
|
||||
|
||||
# une seule méthode est décorée deux fois (3ème)
|
||||
Type = decorate_functions(double_result, func_name_is_in(MyClass.std_met.__name__,))(Type)
|
||||
self.assertEqual(Type.class_met(a, b), res)
|
||||
self.assertEqual(Type.static_met(a, b), res)
|
||||
self.assertEqual(Type(num).std_met(a, b), 2 * res_x2)
|
||||
|
||||
# pas de changement au niveau de la classe d'origine
|
||||
self.assertEqual(MyClass.class_met(a, b), res)
|
||||
self.assertEqual(MyClass.static_met(a, b), res)
|
||||
self.assertEqual(MyClass(num).std_met(a, b), res)
|
||||
|
||||
def test_class_logger(self):
|
||||
def given():
|
||||
self.assertEqual(hasattr(MyClass, CLASS_ATTR_LOGGER), False, "la classe initiale n'a pas de logger")
|
||||
given()
|
||||
|
||||
Type = class_logger(MyClass)
|
||||
self.assertEqual(hasattr(Type, CLASS_ATTR_LOGGER), True)
|
||||
self.assertEqual(getattr(Type, CLASS_ATTR_LOGGER).name, get_logger_name(MyClass))
|
||||
|
||||
# 2ème décoration
|
||||
Type = class_logger(Type)
|
||||
self.assertEqual(hasattr(Type, CLASS_ATTR_LOGGER), True)
|
||||
self.assertEqual(getattr(Type, CLASS_ATTR_LOGGER).name, get_logger_name(MyClass))
|
||||
|
||||
# pas de changement au niveau de la classe d'origine
|
||||
self.assertEqual(hasattr(MyClass, CLASS_ATTR_LOGGER), False)
|
||||
30
backend-django/backend/tests/utils/functions.py
Normal file
30
backend-django/backend/tests/utils/functions.py
Normal file
@@ -0,0 +1,30 @@
|
||||
from .samples import my_func, MyClass
|
||||
from ...utils.functions import find_class
|
||||
from django.test import SimpleTestCase
|
||||
|
||||
|
||||
class FunctionsTest(SimpleTestCase):
|
||||
|
||||
def test_find_class(self):
|
||||
MainType = MyClass
|
||||
main_type = MainType(11)
|
||||
SubType = MyClass.MySubClass
|
||||
sub_type = SubType(13)
|
||||
|
||||
def local_func(a: int, b: int):
|
||||
return a + b
|
||||
|
||||
# fonction native : None
|
||||
self.assertIsNone(find_class(str.join))
|
||||
|
||||
# fonctions : None
|
||||
self.assertIsNone(find_class(local_func))
|
||||
self.assertIsNone(find_class(my_func))
|
||||
|
||||
# méthodes
|
||||
self.assertEqual(find_class(MainType.class_met), MainType)
|
||||
self.assertEqual(find_class(MainType.static_met), MainType)
|
||||
self.assertEqual(find_class(main_type.std_met), MainType)
|
||||
self.assertEqual(find_class(SubType.sub_class_met), SubType)
|
||||
self.assertEqual(find_class(SubType.sub_static_met), SubType)
|
||||
self.assertEqual(find_class(sub_type.sub_std_met), SubType)
|
||||
104
backend-django/backend/tests/utils/logging.py
Normal file
104
backend-django/backend/tests/utils/logging.py
Normal file
@@ -0,0 +1,104 @@
|
||||
import random
|
||||
import string
|
||||
from unittest import mock
|
||||
|
||||
from django.test import SimpleTestCase
|
||||
|
||||
from ...utils.logging import (TAG_DATA_FEED, TAG_PERF, get_logger,
|
||||
get_logger_name)
|
||||
from .samples import MyClass, my_func
|
||||
|
||||
|
||||
class LoggingTest(SimpleTestCase):
|
||||
|
||||
def test_get_logger_name(self):
|
||||
module_name = __name__
|
||||
ext_module_name = my_func.__module__
|
||||
|
||||
MainType = MyClass
|
||||
main_type = MainType(11)
|
||||
main_type_logger = f'{ext_module_name}.{MainType.__qualname__}'
|
||||
SubType = MyClass.MySubClass
|
||||
sub_type = SubType(13)
|
||||
sub_type_logger = f'{ext_module_name}.{SubType.__qualname__}'
|
||||
|
||||
def local_func(a: int, b: int):
|
||||
return a + b
|
||||
|
||||
# None
|
||||
self.assertIsNone(get_logger_name())
|
||||
self.assertIsNone(get_logger_name(None))
|
||||
|
||||
# classes natives
|
||||
self.assertIsNone(get_logger_name(str))
|
||||
self.assertIsNone(get_logger_name(int))
|
||||
self.assertIsNone(get_logger_name(dict))
|
||||
self.assertIsNone(get_logger_name(list))
|
||||
self.assertIsNone(get_logger_name(tuple))
|
||||
|
||||
# instances de classes natives (mais pas str)
|
||||
self.assertIsNone(get_logger_name(1))
|
||||
self.assertIsNone(get_logger_name({'a': 'b'}))
|
||||
self.assertIsNone(get_logger_name(['c']))
|
||||
self.assertIsNone(get_logger_name(('d',)))
|
||||
|
||||
# fonctions natives
|
||||
self.assertIsNone(get_logger_name(str.join))
|
||||
|
||||
# str
|
||||
self.assertEqual(get_logger_name('test'), 'test')
|
||||
self.assertEqual(get_logger_name(''), None)
|
||||
|
||||
# classes
|
||||
self.assertEqual(get_logger_name(MainType), main_type_logger)
|
||||
self.assertEqual(get_logger_name(SubType), sub_type_logger)
|
||||
|
||||
# instances de classes
|
||||
self.assertEqual(get_logger_name(main_type), main_type_logger)
|
||||
self.assertEqual(get_logger_name(sub_type), sub_type_logger)
|
||||
|
||||
# fonctions et méthodes
|
||||
self.assertEqual(get_logger_name(local_func), module_name)
|
||||
self.assertEqual(get_logger_name(my_func), ext_module_name)
|
||||
self.assertEqual(get_logger_name(MainType.class_met), main_type_logger)
|
||||
self.assertEqual(get_logger_name(MainType.static_met), main_type_logger)
|
||||
self.assertEqual(get_logger_name(main_type.std_met), main_type_logger)
|
||||
self.assertEqual(get_logger_name(SubType.sub_class_met), sub_type_logger)
|
||||
self.assertEqual(get_logger_name(SubType.sub_static_met), sub_type_logger)
|
||||
self.assertEqual(get_logger_name(sub_type.sub_std_met), sub_type_logger)
|
||||
|
||||
def test_get_logger_without_tags(self):
|
||||
func_1 = MyClass.class_met
|
||||
func_2 = MyClass.static_met
|
||||
|
||||
def given():
|
||||
self.assertEqual(get_logger_name(func_1), get_logger_name(func_2), 'le nom de logger doit être le même')
|
||||
given()
|
||||
|
||||
msg = "l'instance doit être la même"
|
||||
logger_name = ''.join(random.choice(string.ascii_lowercase) for i in range(10))
|
||||
self.assertIs(get_logger(logger_name), get_logger(logger_name), msg)
|
||||
self.assertIs(get_logger(func_1), get_logger(func_2), msg)
|
||||
|
||||
def test_get_logger_with_tags(self):
|
||||
func_1 = MyClass.class_met
|
||||
func_2 = MyClass.static_met
|
||||
|
||||
def given():
|
||||
self.assertEqual(get_logger_name(func_1), get_logger_name(func_2), 'le nom de logger doit être le même')
|
||||
given()
|
||||
|
||||
msg = "l'instance doit être la même"
|
||||
for tags in [TAG_PERF, TAG_DATA_FEED, ('1', '2'), ['3', '4'], set(['5', '6'])]:
|
||||
with self.subTest(tags=tags):
|
||||
logger_name = ''.join(random.choice(string.ascii_lowercase) for i in range(10))
|
||||
self.assertIs(get_logger(logger_name, tags), get_logger(logger_name, tags), msg)
|
||||
self.assertIs(get_logger(func_1, tags), get_logger(func_2, tags), msg)
|
||||
|
||||
prev_logger = None
|
||||
logger_name = ''.join(random.choice(string.ascii_lowercase) for i in range(10))
|
||||
for i, tags in enumerate([('1', '2', '3', '4'), ['3', '4', '1', '2'], set(['2', '1', '3', '4', '1'])]):
|
||||
curr_logger = get_logger(logger_name, tags)
|
||||
if i > 0:
|
||||
self.assertIs(curr_logger, prev_logger, msg)
|
||||
prev_logger = get_logger(logger_name, tags)
|
||||
127
backend-django/backend/tests/utils/predicates.py
Normal file
127
backend-django/backend/tests/utils/predicates.py
Normal file
@@ -0,0 +1,127 @@
|
||||
from .samples import my_func, _my_private_func, MyClass
|
||||
from ...utils.predicates import func_class_name_is_in, func_class_name_is_not_in, func_name_is_in, func_name_is_not_in, func_is_public
|
||||
from django.test import SimpleTestCase
|
||||
|
||||
|
||||
class PredicatesTest(SimpleTestCase):
|
||||
|
||||
def __test_func_class_name_is_in(self, negation: bool = False):
|
||||
""" teste func_class_name_is_in et func_class_name_is_not_in """
|
||||
|
||||
func = func_class_name_is_not_in if negation else func_class_name_is_in
|
||||
result = negation is not True
|
||||
|
||||
own_name = self.__class__.__name__
|
||||
MainType = MyClass
|
||||
main_type = MainType(11)
|
||||
main_type_name = MainType.__name__
|
||||
SubType = MyClass.MySubClass
|
||||
sub_type = SubType(13)
|
||||
sub_type_name = SubType.__name__
|
||||
|
||||
def local_func(a: int, b: int):
|
||||
return a + b
|
||||
|
||||
# fonction native : None
|
||||
self.assertEqual(func(str.__name__)(str.join), False)
|
||||
|
||||
# fonction locale : None
|
||||
self.assertEqual(func(own_name)(local_func), False)
|
||||
|
||||
# méthodes
|
||||
predicate = func(main_type_name)
|
||||
self.assertEqual(predicate(MainType.class_met), result)
|
||||
self.assertEqual(predicate(MainType.static_met), result)
|
||||
self.assertEqual(predicate(main_type.std_met), result)
|
||||
self.assertEqual(predicate(SubType.sub_class_met), not result)
|
||||
self.assertEqual(predicate(SubType.sub_static_met), not result)
|
||||
self.assertEqual(predicate(sub_type.sub_std_met), not result)
|
||||
|
||||
predicate = func(sub_type_name)
|
||||
self.assertEqual(predicate(MainType.class_met), not result)
|
||||
self.assertEqual(predicate(MainType.static_met), not result)
|
||||
self.assertEqual(predicate(main_type.std_met), not result)
|
||||
self.assertEqual(predicate(SubType.sub_class_met), result)
|
||||
self.assertEqual(predicate(SubType.sub_static_met), result)
|
||||
self.assertEqual(predicate(sub_type.sub_std_met), result)
|
||||
|
||||
def __test_func_name_is_in(self, negation: bool = False):
|
||||
""" teste func_name_is_in et func_name_is_not_in """
|
||||
|
||||
func = func_name_is_not_in if negation else func_name_is_in
|
||||
result = negation is not True
|
||||
|
||||
MainType = MyClass
|
||||
main_type = MainType(11)
|
||||
SubType = MyClass.MySubClass
|
||||
sub_type = SubType(13)
|
||||
|
||||
def local_func(a: int, b: int):
|
||||
return a + b
|
||||
|
||||
# fonction native
|
||||
self.assertEqual(func('join')(str.join), result)
|
||||
self.assertEqual(func('other', 'join')(str.join), result)
|
||||
|
||||
# autre fonction, fonction locale
|
||||
self.assertEqual(func('local_func')(local_func), result)
|
||||
self.assertEqual(func('other', 'local_func')(local_func), result)
|
||||
self.assertEqual(func('my_func')(my_func), result)
|
||||
self.assertEqual(func('other', 'my_func')(my_func), result)
|
||||
|
||||
|
||||
# méthodes
|
||||
predicate = func('class_met', 'std_met', 'sub_static_met')
|
||||
self.assertEqual(predicate(MainType.class_met), result)
|
||||
self.assertEqual(predicate(MainType.static_met), not result)
|
||||
self.assertEqual(predicate(main_type.std_met), result)
|
||||
self.assertEqual(predicate(SubType.sub_class_met), not result)
|
||||
self.assertEqual(predicate(SubType.sub_static_met), result)
|
||||
self.assertEqual(predicate(sub_type.sub_std_met), not result)
|
||||
|
||||
predicate = func('static_met', 'sub_class_met', 'sub_std_met')
|
||||
self.assertEqual(predicate(MainType.class_met), not result)
|
||||
self.assertEqual(predicate(MainType.static_met), result)
|
||||
self.assertEqual(predicate(main_type.std_met), not result)
|
||||
self.assertEqual(predicate(SubType.sub_class_met), result)
|
||||
self.assertEqual(predicate(SubType.sub_static_met), not result)
|
||||
self.assertEqual(predicate(sub_type.sub_std_met), result)
|
||||
|
||||
|
||||
def test_func_class_name_is_in(self):
|
||||
self.__test_func_class_name_is_in()
|
||||
|
||||
def test_func_class_name_is_not_in(self):
|
||||
self.__test_func_class_name_is_in(negation=True)
|
||||
|
||||
def test_func_name_is_in(self):
|
||||
self.__test_func_name_is_in()
|
||||
|
||||
def test_func_name_is_not_in(self):
|
||||
self.__test_func_name_is_in(negation=True)
|
||||
|
||||
def test_func_is_public(self):
|
||||
MainType = MyClass
|
||||
main_type = MainType(11)
|
||||
SubType = MyClass.MySubClass
|
||||
sub_type = SubType(13)
|
||||
|
||||
def local_func(a: int, b: int):
|
||||
return a + b
|
||||
|
||||
# fonction native
|
||||
self.assertEqual(func_is_public(str.join), True)
|
||||
|
||||
# autre fonction, fonction locale
|
||||
self.assertEqual(func_is_public(local_func), True)
|
||||
self.assertEqual(func_is_public(my_func), True)
|
||||
self.assertEqual(func_is_public(_my_private_func), False)
|
||||
|
||||
# méthodes
|
||||
self.assertEqual(func_is_public(MainType._protected_met), False)
|
||||
self.assertEqual(func_is_public(MainType.class_met), True)
|
||||
self.assertEqual(func_is_public(MainType.static_met), True)
|
||||
self.assertEqual(func_is_public(main_type.std_met), True)
|
||||
self.assertEqual(func_is_public(SubType.sub_class_met), True)
|
||||
self.assertEqual(func_is_public(SubType.sub_static_met), True)
|
||||
self.assertEqual(func_is_public(sub_type.sub_std_met), True)
|
||||
58
backend-django/backend/tests/utils/samples.py
Normal file
58
backend-django/backend/tests/utils/samples.py
Normal file
@@ -0,0 +1,58 @@
|
||||
# quelques définitions pour les tests ==>
|
||||
|
||||
def my_func(a: int, b: int):
|
||||
""" fonction sans classe """
|
||||
return a + b
|
||||
|
||||
|
||||
def _my_private_func(a: int, b: int):
|
||||
""" fonction sans classe (non importée par défaut avec import *) """
|
||||
return a + b
|
||||
|
||||
|
||||
class MyClass():
|
||||
""" classe pour tests """
|
||||
num = None
|
||||
|
||||
def __init__(self, num):
|
||||
""" la classe est paramétrée """
|
||||
self.num = num
|
||||
|
||||
def _protected_met(self, a: int, b: int):
|
||||
""" méthode standard (protected par convention) """
|
||||
return a + b
|
||||
|
||||
class MySubClass():
|
||||
sub_num = None
|
||||
|
||||
def __init__(self, num):
|
||||
""" la classe est paramétrée """
|
||||
self.sub_num = num
|
||||
|
||||
@classmethod
|
||||
def sub_class_met(cls):
|
||||
""" méthode de classe """
|
||||
return True
|
||||
|
||||
@staticmethod
|
||||
def sub_static_met():
|
||||
""" méthode statique """
|
||||
return True
|
||||
|
||||
def sub_std_met():
|
||||
""" méthode standard """
|
||||
return True
|
||||
|
||||
@classmethod
|
||||
def class_met(cls, a: int, b: int):
|
||||
""" méthode de classe """
|
||||
return a + b
|
||||
|
||||
@staticmethod
|
||||
def static_met(a: int, b: int):
|
||||
""" méthode statique """
|
||||
return a + b
|
||||
|
||||
def std_met(self, a: int, b: int):
|
||||
""" méthode standard """
|
||||
return a + b
|
||||
Reference in New Issue
Block a user