Hallo,
ich habe ein Python Modul aaa mit (vereinfacht) einer Klasse AAA und einer globalen Variable.
In der Klasse wird ein anderes Modul benutzt. Z.B. pymqi, das oben importiert wird.
Will ich diese Klasse unit testen, dann schreibe ich eine Datei mit dem Unit-Test und importiere das Modul aaa.
Wie kann ich erreichen, dass für den Test pymqi nicht importiert wird? Denn es wird sonst knallen, wenn die shared libs fehlen.
Wie kann ich im Modul aaa die globale Variable (z.B. eine Konfiguration) setzen?
Was sind "best practices"?
Gruß Thomas
Bedingter Import für Unit-Tests
Das Stichwort dafür heißt dependency injection. Du kannst auf verschiedene Arten vorgehen:
- dein Modul aaa importiert pymqi NICHT. Sondern bekommt das Modul als Argument. Dadurch kannst du das mocken.
- du mocks das Modul durch ein pymqi-Mock-Modul das im sys.path vor dem original liegt, und dadurch zuerst (und alleinig) importiert wird.
- dein Modul aaa importiert pymqi NICHT. Sondern bekommt das Modul als Argument. Dadurch kannst du das mocken.
- du mocks das Modul durch ein pymqi-Mock-Modul das im sys.path vor dem original liegt, und dadurch zuerst (und alleinig) importiert wird.
Also, die zweite Methode ist das, was man normalerweise macht, ob jetzt über sys.path oder sys.modules, ist zweitrangig. Dafür gibt es normalerweise schon fertige Funktionen: https://docs.pytest.org/en/latest/monkeypatch.html
Globale Variablen sollte es in Modulen nicht geben. Für "Konstanten" die in komplexeren Funktionsaufrufen generiert werden, kann man genauso monkey-patching benutzen, in dem man die Funktion überschreibt:
im Test:
Hier muß man natürlich aufpassen, dass das Monkey-Patching schon vorher stattfindet, oder eben gleich das ganze Module `database` durch ein mockup erstetzen:
Globale Variablen sollte es in Modulen nicht geben. Für "Konstanten" die in komplexeren Funktionsaufrufen generiert werden, kann man genauso monkey-patching benutzen, in dem man die Funktion überschreibt:
Code: Alles auswählen
import database
configuration = database.get_config_from_database()
Code: Alles auswählen
import database
def test_get_config():
return {'abc': 5}
database.get_config_from_database = test_get_config
import module_to_test
Code: Alles auswählen
import sys
import mock_database
sys.modules['database'] = mock_database
Hi,
in thomastest.py
In thomas.py
Und wenn ich thomastest.py start bekomme ich diese Exception:
in thomastest.py
Code: Alles auswählen
#!/usr/bin/python
import sys
import unittest
import ttmock
sys.modules['springpython.jms.core'] = ttmock
import thomas
Code: Alles auswählen
#!/usr/bin/python
from springpython.jms.core import JmsTemplate
from springpython.jms.factory import WebSphereMQConnectionFactory
Code: Alles auswählen
Traceback (most recent call last):
File "thomastest.py", line 9, in <module>
import thomas
File "/cygdrive/e/Projekte/python/thomas.py", line 38, in <module>
from springpython.jms.core import JmsTemplate
ImportError: No module named springpython.jms.core