Maison > Article > développement back-end > Classes Python moqueuses
Dernièrement, j'ai dû écrire des tests unitaires en utilisant Pytest pour un module Python. Le module contient une classe où d'autres classes sont initialisées au sein de son constructeur.
Comme d'habitude, j'ai créé un dispositif pour cette classe afin de faciliter l'écriture d'un test pour chaque méthode de classe. À ce stade, j'ai rencontré quelques problèmes lorsque j'ai essayé de me moquer des différentes classes initiées dans le constructeur. Les moqueries n'ont pas fonctionné et des instances de ces classes étaient toujours en cours de création.
Après quelques recherches et en combinant quelques solutions différentes que j'ai trouvées en ligne, je souhaite partager comment j'ai réussi à me moquer des cours.
Voici un exemple de la classe dont j'ai essayé de me moquer :
class ClassA: def __init__(self): self.class_b = ClassB() self.class_c = ClassC() self.count = 0
Nous souhaitons définir une valeur pour chaque champ de cette classe lors des tests. Cette valeur peut être Aucune ou une classe simulée, mais nous ne voulons pas d'initiations des classes ClassB et ClassC.
Dans notre cas, décidons que self.class_b et self.class_c doivent être simulés :
@pytest.fixture def mock_class_b(): class_b = Mock(spec=ClassB) return class_b @pytest.fixture def mock_class_c(): class_c = Mock(spec=ClassC) return class_c
Donc, un montage pour cette classe qui sert notre objectif ressemble à ceci :
@pytest.fixture def class_a_mock(mock_class_b, mock_class_c): with patch.object(target=ClassA, attribute="__init__", return_value=None) as mock_init: class_a = ClassA() class_a.class_b = mock_class_b class_a.class_c = mock_class_c class_b.count = 0 return class_a
La partie importante est de savoir comment utiliser la fonction patch.object, qui provient du module unittest.mock en Python. Il est utilisé dans les tests pour remplacer temporairement un attribut d'un objet donné par une valeur fictive ou une autre valeur.
Arguments
De cette façon, nous pouvons créer des variables simulées dans notre luminaire.
En savoir plus sur patch.object
J'ai écrit ce tutoriel pour ce genre de cas où, pour une raison quelconque, on ne peut pas changer le code de la Classe A. Cependant, je recommande généralement de modifier le code si possible, non pas pour changer la logique, mais pour le rendre plus testable .
Voici quelques exemples de modifications de la classe A pour la rendre plus testable :
Option 1 : Passer les instances de classe B et de classe C comme paramètres.
De cette façon, lorsque nous écrivons le luminaire, nous pouvons transmettre des simulations au lieu d'instances.
class ClassA: def __init__(self, class_b_instance, class_c_instance): self.class_b = class_b_instance self.class_c = class_c_instance self.count = 0
Option 2 : Créez une variable booléenne qui indique le mode test.
De cette façon, nous pouvons décider quels champs de classe A obtiendront ou non une valeur lors de son initiation.
class ClassA: def __init__(self, test_mode=False): if not test_mode: self.class_b = ClassB() self.class_c = ClassC() self.count = 0
Option 3 : Effectuer des initiations de cours selon une méthode distincte.
Cette approche nous donne le choix d'éviter d'appeler set_class_variables dans le module de test.
class ClassA: def __init__(self): self.class_b = None self.class_c = None self.count = None def set_class_variables(self): self.class_b = ClassB() self.class_c = ClassC() self.count = 0
J'espère que cela vous aidera ! :)
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!