Disons que j'ai un cours comme celui-ci.
class SomeProductionProcess(CustomCachedSingleTon):
def loaddata():
"""
Uses an iterator over a large file in Production for the Data pipeline.
"""
pass
Maintenant, au moment du test, je souhaite modifier la logique de la méthode loaddata()
. Ce serait une simple logique personnalisée qui ne traite pas de grandes données.
Comment pouvons-nous fournir une implémentation personnalisée de loaddata()
lors du test à l'aide de la structure Python Mock UnitTest?
Voici un moyen simple de le faire en utilisant mock
import mock
def new_loaddata(cls, *args, **kwargs):
# Your custom testing override
return 1
def test_SomeProductionProcess():
with mock.patch.object(SomeProductionProcess, 'loaddata', new=new_loaddata):
obj = SomeProductionProcess()
obj.loaddata() # This will call your mock method
Je vous recommande d'utiliser pytest
au lieu du module unittest
si vous en êtes capable. Cela rend votre code de test beaucoup plus propre et réduit considérablement le nombre de tests obtenus avec les tests de style unittest.TestCase
-.
Pour simuler facilement une méthode de classe avec une valeur retournée structurée, vous pouvez utiliser unittest.mock.Mock
.
from unittest.mock import Mock
mockObject = SomeProductionProcess
mockObject.loaddata = Mock(return_value=True)
MODIFIER:
Puisque vous voulez simuler la méthode avec une implémentation personnalisée, vous pouvez simplement créer un objet de méthode simulé et échanger la méthode d'origine lors du test de l'exécution.
def custom_method(*args, **kwargs):
# do custom implementation
SomeProductionProcess.loaddata = custom_method
Disons que vous avez un module nommé awesome.py et que vous y aviez:
import time
class SomeProductionProcess(CustomCachedSingleTon):
def loaddata(self):
time.sleep(30) # simulating a long running process
return 2
Dans ce cas, votre plus-part où vous vous moquez de loaddata
pourrait ressembler à ceci:
import unittest
import awesome # your application module
class TestSomeProductionProcess(unittest.TestCase):
"""Example of direct monkey patching"""
def test_loaddata(self):
some_prod_proc = awesome.SomeProductionProcess()
some_prod_proc.loaddata = lambda x: 2 # will return 2 every time called
output = some_prod_proc.loaddata()
expected = 2
self.assertEqual(output, expected)
Ou cela pourrait ressembler à ceci:
import unittest
from mock import patch
import awesome # your application module
class TestSomeProductionProcess(unittest.TestCase):
"""Example of using the mock.patch function"""
@patch.object(awesome.SomeProductionProcess, 'loaddata')
def test_loaddata(self, fake_loaddata):
fake_loaddata.return_value = 2
some_prod_proc = awesome.SomeProductionProcess()
output = some_prod_proc.loaddata()
expected = 2
self.assertEqual(output, expected)
Désormais, lorsque vous exécuterez votre test, loaddata
ne prendra pas 30 secondes pour ces cas de test.