Il existe différents frameworks de test pour python, mais j'aime personnellement le framework appelé nose, alors j'aimerais le présenter.
$ pip install nose
Vous pouvez avoir besoin de sudo en fonction de votre environnement.
Supposons que vous ayez la fonction sum et la fonction is_even suivantes dans un module appelé hoge.
hoge.py
def sum(a, b):
return a + b
def is_even(n):
return (n % 2 == 0)
Créez le fichier test_hoge.py suivant qui hérite de unittest.TestCase.
Ici, ʻeq_ pour vérifier si la valeur est la même que la ** valeur attendue ** et ʻok_
pour vérifier si la valeur est ** true ** sont importés de nose.tools
et utilisés. Je vais.
En tant que mécanisme commun dans le cadre de test, «setUp» et «tearDown» sont fournis pour un traitement tel que l'initialisation / la libération des ressources avant et après le test, alors essayez d'insérer une instruction d'impression.
test_hoge.py
from unittest import TestCase
from nose.tools import ok_, eq_
from hoge import sum, is_even
class HogeTestCase(TestCase):
def setUp(self):
print 'before test'
def tearDown(self):
print 'after test'
def test_sum(self):
eq_(sum(1, 2), 3)
eq_(sum(5, 11), 16)
eq_(sum(0, 0), 0)
def test_is_even(self):
ok_(is_even(2))
ok_(not is_even(3))
nose est livré avec une commande de test runner appelée nosetests. (Le nez d'installation du pip l'installera) Si vous exécutez nos tests ici, ce sera comme suit.
$ nosetests
..
----------------------------------------------------------------------
Ran 2 tests in 0.003s
OK
Lorsque nosetests
est exécuté, il recherchera des fichiers de type test (y compris test dans le nom du fichier) dans le répertoire courant, et collectera et exécutera les classes qui héritent de ʻunittest.TestCase. Je n'ai pas reçu le message que j'aurais dû imprimer avec l'instruction d'impression, car par défaut, le nez capture la sortie vers la sortie standard. Vous pouvez voir la sortie telle quelle avec l'option
-s`.
$ nosetests -s
Ajoutez l'option -v
pour afficher le nom du cas de test en cours d'exécution par le nom de la méthode ainsi que par le point.
$ nosetests -v
Quand j'ai essayé de l'exécuter ensemble, c'est devenu comme suit.
$ nosetests -s -v
test_is_even (test_hoge.HogeTestCase) ... before test
after test
ok
test_sum (test_hoge.HogeTestCase) ... before test
after test
ok
----------------------------------------------------------------------
Ran 2 tests in 0.002s
OK
Vous pouvez également spécifier un nom de fichier pour que la commande nosetests exécute uniquement des tests sur des fichiers spécifiques. Ce serait pratique si le développement progressait et les tests augmentés.
$ nosetests ./test_hoge.py
Voici quelques autres outils de test pour ʻok_ et ʻeq_
. Voir la page des outils de test de nose (http://nose.readthedocs.org/en/latest/testing_tools.html) pour plus d'informations.
raises
Utilisez raises
comme décorateur pour les tests susceptibles de provoquer des exceptions.
Testez la fonction suivante div
où une exception est susceptible de se produire.
fuga.py
def div(n, m):
return n / m
Le cas de test est ci-dessous.
fuga_hoge.py
from unittest import TestCase
from nose.tools import eq_, raises
from fuga import div
class FugaTestCase(TestCase):
def test_div(self):
eq_(div(10, 5), 2)
eq_(div(10, 10), 1)
eq_(div(9, 3), 3)
@raises(ZeroDivisionError)
def test_div_zerodiv(self):
div(10, 0)
Vous pouvez maintenant vérifier si le scénario de test test_div_zerodiv
lance correctement l'exception ZeroDivisionError
.
timed
timed
est un décorateur qui vérifie si un cas de test se termine dans un laps de temps spécifié (spécifié en secondes).
Prenons un test qui vérifie qu'une fonction do_something
, dont le traitement prend environ 0,1 seconde, se termine en 0,2 seconde, comme ce qui suit.
moge.py
import time
def do_something():
time.sleep(0.1)
Le cas de test ressemble à ceci:
test_moge.py
from unittest import TestCase
from nose.tools import timed
from moge import do_something
class MogeTestCase(TestCase):
@timed(0.2)
def test_do_something(self):
do_something()
Pour les programmes qui utilisent gevent, il est recommandé d'utiliser les décorateurs suivants.
décorateur gtest
import gevent
def gtest(func):
def _gtest(*args, **kwargs):
gevent.spawn(func, *args, **kwargs).join()
_gtest.__name__ = func.__name__
return _gtest
Testons un programme comme celui ci-dessous. _tick
et _tacik
se déplacent alternativement, envoyant des chaînes de caractères numérotées telles que tick1, tack1, tick2, tack2 alternativement dans la file d'attente, et enfin aspirer tout le contenu de la file d'attente et le renvoyer sous forme de tableau Te donnera.
g.py
import gevent
import gevent.queue
def ticktack(n):
q = gevent.queue.Queue()
def _tick(_q, _n):
for i in range(_n):
_q.put('tick%d' % (i + 1))
gevent.sleep()
def _tack(_q, _n):
for i in range(_n):
_q.put('tack%d' % (i + 1))
gevent.sleep()
_tick_thread = gevent.spawn(_tick, q, n)
_tack_thread = gevent.spawn(_tack, q, n)
result = []
while len(result) < n * 2:
result.append(q.get())
return result
Puisque gevent effectue un changement décisif de greenlet lorsque gevent.sleep () est appelé, le _tick généré en premier et le _tack généré plus tard sont toujours appelés.
Testons cela avec le décorateur ci-dessus.
test_g.py
from unittest import TestCase
from nose.tools import eq_
import gevent
from g import ticktack
import gevent
def gtest(func):
def _gtest(*args, **kwargs):
gevent.spawn(func, *args, **kwargs).join()
_gtest.__name__ = func.__name__
return _gtest
class GTestCase(TestCase):
@gtest
def test_ticktack(self):
r1 = ticktack(1)
eq_(r1, ['tick1', 'tack1'])
r2 = ticktack(2)
eq_(r2, ['tick1', 'tack1', 'tick2', 'tack2'])
Vous vous sentiez bien?
--nose facilite et simplifie l'écriture de cas de test --nosetests a différentes options et peut être exécuté de manière flexible
J'espère que cela aide.
Recommended Posts