Définissez les arguments mot-clés du constructeur sur les attributs fictifs en Python

Je teste en unité une classe qui utilise peewee pour ORM. J'ai utilisé mock pour le test et j'ai essayé de vérifier si la valeur correcte était définie pour l'attribut du modèle, mais ce que j'ai défini pour l'attribut dans le constructeur du modèle Lors du passage en argument avec un mot-clé, la classe mock.Mock n'a pas pu être testée correctement telle quelle, j'ai donc créé une simulation qui définit l'argument avec un mot-clé sur un attribut.

Je n'ai que deux mois en Python, et j'ai peut-être fait une grosse erreur, et il y a peut-être un moyen plus intelligent de le faire. Si quelqu'un connaît des erreurs ou de meilleures façons, il serait grandement apprécié que vous puissiez commenter.

PostScript 15/10/2016 Le code de cet article ne prend en charge que le cas où une seule maquette est créée. Dans le cas d'instanciations multiples, vous devez utiliser une méthode comme @ podhmo's Example code dans le commentaire.

environnement

Préparation

$ pip install peewee
$ pip install mock

Structure du répertoire

$ tree
.
├── src
│   ├── __init__.py
│   ├── model.py
│   └── service.py
└── test
    ├── __init__.py
    └── test_service.py

Code à tester

src/service.py


# -*- coding: utf-8 -*-

from model import HogeModel

class HogeService(object):
    def run(self):
        model = HogeModel(name='hoge name')
        model.desc = 'hoge desc'
        model.save()

src/model.py


# -*- coding: utf-8 -*-

from peewee import SqliteDatabase
from peewee import Model
from peewee import PrimaryKeyField
from peewee import CharField

db = SqliteDatabase('hoge.db')

class HogeModel(Model):
    id = PrimaryKeyField
    name = CharField()
    desc = CharField()

    class Meta:
        database = db

Code de test

test/test_service.py


# -*- coding: utf-8 -*-

import unittest
from mock import patch
from mock import Mock
from service import HogeService

class TestHogeService(unittest.TestCase):

    @patch('service.HogeModel')
    def test_run(self, mock_hoge_model):
        mock = Mock()
        mock_hoge_model.return_value = mock
        target = HogeService()
        target.run()
        self.assertEquals(1, mock.save.call_count)  # OK
        self.assertEquals('hoge desc', mock.desc)  # OK
        self.assertEquals('hoge name', mock.name)  # NG

if __name__ == '__main__':
    unittest.main()
$ PYTHONPATH=src python test/test_service.py 
F
======================================================================
FAIL: test_run (__main__.TestHogeService)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/Users/otti/.pyenv/versions/2.7.12/lib/python2.7/site-packages/mock/mock.py", line 1305, in patched
    return func(*args, **keywargs)
  File "test/test_service.py", line 18, in test_run
    self.assertEquals('hoge name', mock.name)  # NG
AssertionError: 'hoge name' != <Mock name='HogeModel().name' id='4454023888'>

----------------------------------------------------------------------
Ran 1 test in 0.001s

FAILED (failures=1)

Définissez l'argument mot-clé du constructeur sur l'attribut simulé

test/test_service.py


# -*- coding: utf-8 -*-

import unittest
from mock import Mock
from mock import patch
from service import HogeService

class TestHogeService(unittest.TestCase):

    def create_attr_set_mock(self, **kwargs):
        self.mock = Mock()
        #Définissez l'argument mot-clé passé dans le constructeur sur l'attribut
        for k, v in kwargs.items():
            self.mock.__dict__[k] = v
        return self.mock

    @patch('service.HogeModel')
    def test_run(self, mock_hoge_model):
        #Renvoie une simulation qui définit un attribut avec un argument de mot-clé dans le constructeur lors de l'instanciation de la classe cible
        mock_hoge_model.side_effect = lambda **kwargs: self.create_attr_set_mock(**kwargs)
        target = HogeService()
        target.run()
        self.assertEquals(1, self.mock.save.call_count) # OK
        self.assertEquals('hoge desc', self.mock.desc) # OK
        self.assertEquals('hoge name', self.mock.name) # OK

if __name__ == '__main__':
    unittest.main()
 PYTHONPATH=src python test/test_service.py 
.
----------------------------------------------------------------------
Ran 1 test in 0.001s

OK

Vous avez maintenant une maquette du modèle qui fonctionne comme prévu. C'était un peu déroutant car mock.Mock semble avoir un attribut appelé name en premier lieu, mais c'était la même chose même si je l'ai essayé avec des attributs autres que name.

référence

Recommended Posts

Définissez les arguments mot-clés du constructeur sur les attributs fictifs en Python
Comment recevoir des arguments de ligne de commande en Python
Comment spécifier des attributs avec Mock of Python
Je veux écrire en Python! (3) Utiliser des simulacres
Pour vider stdout en Python
Connectez-vous au site Web en Python
Recevoir des arguments d'exécution dans Python 2.7
Parler avec Python [synthèse vocale]
Comment développer en Python
Publier sur Slack en Python
Définir le test python dans jenkins
Comment importer la bibliothèque Python configurée dans EFS dans Lambda
Choses à surveiller lors de l'utilisation d'arguments par défaut en Python
[Python] Comment faire PCA avec Python
Comment passer des arguments à un script Python dans SPSS Modeler Batch
Notation inclusive dans l'argument de la fonction Python
Convertir Markdown en PDF en Python
Comment collecter des images en Python
Comment utiliser SQLite en Python
Dans la commande python, python pointe vers python3.8
Essayez de calculer Trace en Python
Comment utiliser Mysql avec python
Comment envelopper C en Python
Comment utiliser ChemSpider en Python
6 façons d'enchaîner des objets en Python
Comment utiliser PubChem avec Python
Transmettez des arguments à Task dans discord.py
Précautions lors de l'attribution de valeurs par défaut aux arguments dans les définitions de fonctions Python
Comment gérer le japonais avec Python
Une alternative à `pause` en Python
[Python] J'ai essayé de résumer le type collectif (ensemble) d'une manière facile à comprendre.
J'ai essayé d'implémenter PLSA en Python
[Introduction à Python] Comment utiliser la classe en Python?
Essayez de vous connecter à qiita avec Python
Installez Pyaudio pour lire des vagues en python
J'ai essayé d'implémenter la permutation en Python
Méthode pour créer un environnement Python dans Xcode 6
Comment définir dynamiquement des variables en Python
Comment faire R chartr () en Python
Épingler le répertoire actuel au répertoire de script en Python
[Itertools.permutations] Comment créer une séquence en Python
PUT gzip directement dans S3 en Python
Envoyer des e-mails à plusieurs destinataires avec Python (Python3)
Convertir un fichier psd en png en Python
Exemple de script pour piéger les signaux en Python
Decorator pour éviter UnicodeEncodeError dans Python 3 print ()
Comment utiliser BigQuery en Python
Associez l'ensemble de tables dans les modèles de python.py
Connectez-vous à Slack à l'aide de requêtes en Python
Comment obtenir stacktrace en python
Comment afficher la table quatre-vingt-dix-neuf en python
Un moyen simple d'utiliser Wikipedia avec Python
Comment extraire une zone de polygone en Python
Comment vérifier la version d'opencv avec python
J'ai essayé d'implémenter ADALINE en Python
[Python] pandas à bien comprendre en 10 minutes
Lancer le Webhook entrant vers Mattermost en Python
Module pour générer le mot N-gramme en Python
Pour référencer des variables d'environnement en Python dans Blender