[PYTHON] Comment faire un test unitaire Part.1 Modèle de conception pour l'introduction

Cliquez ici pour la partie 2

Afin d'exécuter le test unitaire, il est nécessaire de remplacer / d'éliminer les éléments dépendant de l'environnement tels que les périphériques. Si ces manipulations ne sont pas soigneusement conçues, les tests unitaires ne seront pas possibles. Dans une série d'articles de ce titre, nous examinerons les implémentations pour les tests et la production, en utilisant des modèles de conception. Dans cet article, nous examinerons comment gérer les données conservées en mémoire, mais il en va de même pour les appareils tels que les réseaux.

En fin de compte, l'accent est mis sur la façon de remplacer le module de test. Cette idée est appelée injection de dépendance (DI). En DI, le degré de couplage entre les modules est réduit via l'interface.

L'exemple de programme est écrit en C ++, mais C # et Python seront également écrits.

modifier l'historique

2015-04-26 Ajout de l'exemple de code Python

Données dépendant de l'environnement

Les données peuvent être tout ce qui détermine le comportement de l'application ou transmet le résultat du comportement. Vous pouvez le faire localement, mais il y a des moments où vous voulez vraiment l'utiliser globalement. Comment doit-il être conservé?

L'exemple suivant suppose une fonction qui change son comportement en fonction de la version du module externe.

//Avant l'introduction (non testable ou difficile)
void func() {
    //Obtenir la version
    int version = SomeModule::getMajorVersion();
    if (version > 10) {
        //Quelque chose à voir avec la version spécifiée
    }
}

Ici, on suppose que SomeModule :: getMajorVersion () ne peut être utilisé que dans un environnement spécifique, ou il est difficile de changer d'état. Avec un tel code, il est difficile de tester l'instruction if suivante.

Utilisation du modèle Proxy

Ici, créez une classe factice qui remplace SomeModule, préparez une entité et un proxy qui accède au mannequin et rendez-le testable. Tout d'abord, à partir de la classe Proxy Interface, qui est le point de contact.

class ModuleProxy {
	virtual int getMajorVersion_() const = 0;
protected:
	ModuleProxy() {}
public:
	virtual ~ModuleProxy() {};
	int getMajorVersion() const {
		return this->getMajorVersion_();
	}
};

Vient ensuite la classe réelle et la classe factice. Ici, le SomeModule d'origine est également masqué et la classe d'utilisation est créée.

//Classe qui appelle réellement le module externe
class SomeModuleImpl : public ModuleProxy {
	virtual int getMajorVersion_() const override {
		return SomeModule::getMajorVersion();
	}
};

//Classe factice pour les tests
class ModuleDummy : public ModuleProxy {
	virtual int getMajorVersion_() const override {
		return major_;
	}
public:
	ModuleDummy(int ver = 0)
		: major_(ver)
	{}
	int major_;
};

La fonction func et le code de test sont les suivants.

void func(ModuleProxy& module) {
    //Obtenir la version
    int version = module.getMajorVersion();
    if (version > 10) {
    }
}

void XXXTest::funcTest() {
   	ModuleDummy dummy(10);
    {
        func(dummy);
    }
    {
    	dummy.major_ = 11;
        func(dummy);
    }
}

Utilisation du modèle Monostate

Une autre façon de l'implémenter consiste à utiliser le modèle Monostate. Ici, la fonction membre est également statique, mais cela peut être une fonction normale.

class Data {
    static int majorVersion;
public:
    static int getMajorVersion() const {
        return majorVersion;
    }

    friend class XXXTest;
};
int Data::majorVersion = 1;

L'implémentation d'application qui l'utilise est la suivante.

void func() {
    if (Data::getMajorVersion() > 10) {
    }
}

Le côté test ressemble à ceci.

void XXXTest::funcTest() {
    {
        Data::majorVersion = 10;
        func();
    }
    {
        Data::majorVersion = 11;
        func();
    }
}

Le modèle Monostate est simple, mais vous devez penser à l'initialisation de la valeur. Lorsqu'il est référencé par d'autres éléments statiques, il faut prendre soin de l'ordre d'initialisation.

Exemple de code (Python)

La version Python du modèle Monostate est illustrée ci-dessous. La méthode de classe a été spécifiée pour la méthode.

class Data:
    _majorVersion = 1

    @classmethod
    def getMajorVersion(cls) -> int:
        return cls._majorVersion

Le côté test ressemble à ceci:

import unittest

class Test_testSample(unittest.TestCase):
    def test_version(self):
        Monostate.Data._majorVersion = 10
        self.assertFalse(Target.func())
        Monostate.Data._majorVersion = 11
        self.assertTrue(Target.func())

Résumé

Dans cet article, DI a été réalisé en utilisant le modèle Proxy. Nous avons également montré comment utiliser plus simplement le modèle Monostate.

Neta à partir de la prochaine fois

Il est important d'être conscient des contrats, même dans des langages tels que C ++ / C # / Python qui ne prennent pas en charge la fonctionnalité de contrat.

Puisque Monostate peut être utilisé de manière polymorphe, il est possible d'incorporer des modèles Proxy pour le rendre plus facile à utiliser.

Il est bon d'utiliser friend dans le test unitaire, mais cela ajoutera un ami à l'en-tête côté application, ce qui provoquera une recompilation. Réfléchissez à la façon d'y faire face.

Lors de l'implémentation de l'accès aux ressources avec shared_ptr, il peut être préférable d'utiliser low_ptr comme IF de Proxy. Essayez ces améliorations tout en restant testables.

Recommended Posts

Comment faire un test unitaire Part.1 Modèle de conception pour l'introduction
Comment faire un test unitaire Part.2 Conception de classe pour les tests
Spigot (Paper) Introduction à la création d'un plug-in pour 2020 # 01 (Construction de l'environnement)
Comment faire un jeu de tir avec toio (partie 1)
Comment créer un laboratoire de piratage - Kali Linux (2020.1) VirtualBox 64 bits Partie 2-
Comment rédiger un test de traitement utilisant BigQuery
Comment faire une traduction japonais-anglais
Comment créer un bot slack
Comment créer un robot - Avancé
Comment créer une fonction récursive
[Blender] Comment créer un plug-in Blender
Comment créer un robot - Basic
[Introduction à Python] Comment utiliser l'opérateur in dans l'instruction for?
[Python] Comment rendre une classe itérable
[Cocos2d-x] Comment créer une liaison de script (partie 2)
Comment créer un indicateur personnalisé Backtrader
Comment tester sur une page authentifiée par Django
Comment créer un plan de site Pelican
Créez un modèle d'échiquier pour l'étalonnage de la caméra
[Cocos2d-x] Comment créer une liaison de script (partie 1)
Comment faire un modèle pour la détection d'objets avec YOLO en 3 heures
Comment créer un système de dialogue dédié aux débutants
Comment créer un dictionnaire avec une structure hiérarchique.
Comment créer un plug-in QGIS (génération de package)
Comment écrire une instruction ShellScript Bash for
J'ai lu "Comment créer un laboratoire de piratage"
Comment créer le plugin Python de Substance Painter (Introduction)
Comment rendre le Python des débutants plus rapide [numpy]
[Introduction à Python] Comment obtenir l'index des données avec l'instruction for
Conseils aux débutants en Python pour utiliser l'exemple Scikit-image pour eux-mêmes 7 Comment créer un module
[Go] Comment créer une erreur personnalisée pour Sentry
[Introduction à python] Introduction rapide à Python pour les programmeurs C ++ occupés
Comment tester unitaire une fonction contenant l'heure actuelle à l'aide de Freezegun en Python
Comment créer un package Python à l'aide de VS Code
Introduction à PyQt4 Partie 1
Comment créer un référentiel local pour le système d'exploitation Linux
Comment créer un environnement de développement pour TensorFlow (1.0.0) (Mac)
Bases de PyTorch (2) -Comment créer un réseau de neurones-
Écrire du code dans UnitTest une application Web Python
[Introduction à Python] Comment écrire des instructions répétitives à l'aide d'instructions for
Comment créer un BOT Cisco Webex Teams à l'aide de Flask
[Python] Comment créer une liste de chaînes de caractères caractère par caractère
Comment mélanger une partie de la liste Python (au hasard.shuffle)
Comment créer un jeu d'action multijoueur en ligne avec Slack
Expérimentez pour créer un PDF indépendant pour Kindle avec Python
Comment définir plusieurs variables dans une instruction Python for
Comment créer un laboratoire de piratage - Kali Linux (2020.1) VirtualBox 64-bit edition -
Comment faire un simple jeu Flappy Bird avec Pygame
Comment remplacer une valeur numérique pour une correspondance partielle (Remarque 1)
[Introduction à Tensorflow] Comprendre correctement Tensorflow et essayer de créer un modèle
Créer un backend Blueqat ~ Partie 1
Créer un backend Blueqat ~ Partie 2
J'ai écrit un test unitaire pour différentes langues
Donner les paramètres de nettoyage pytest pour le test unitaire du flacon
Test unitaire Python
Comment faire un test unitaire Part.2 Conception de classe pour les tests
Une super introduction à Linux
Comment appeler une fonction
Comment pirater un terminal