web-dev-qa-db-fra.com

Exécuter du code avant et après chaque test dans py.test?

Je souhaite exécuter des contrôles de configuration et de démontage supplémentaires avant et après chaque test dans ma suite de tests. J'ai regardé les matchs mais je ne suis pas sûr que ce soit la bonne approche. J'ai besoin d'exécuter le code d'installation avant chaque test et les contrôles de démontage après chaque test.

Mon cas d'utilisation vérifie le code qui ne nettoie pas correctement: il laisse des fichiers temporaires. Dans ma configuration, je vérifierai les fichiers et, lors du démontage, je vérifierai également les fichiers. S'il y a des fichiers supplémentaires, je veux que le test échoue.

27
edA-qa mort-ora-y

les montages py.test sont une méthode techniquement adéquate pour atteindre votre objectif.

Vous avez juste besoin de définir un fixture comme ça:

@pytest.fixture(autouse=True)
def run_around_tests():
    # Code that will run before your test, for example:
    files_before = # ... do something to check the existing files
    # A test function will be run at this point
    yield
    # Code that will run after your test, for example:
    files_after = # ... do something to check the existing files
    assert files_before == files_after

En déclarant votre appareil avec autouse=True, il sera automatiquement appelé pour chaque fonction de test définie dans le même module.

Cela dit, il y a une mise en garde. Affirmer lors de la configuration/du démontage est une pratique controversée. J'ai l'impression que les principaux auteurs de py.test ne l'aiment pas (je ne l'aime pas non plus, cela peut donc altérer ma propre perception), de sorte que vous risquez de rencontrer des problèmes ou des difficultés à mesure que vous avancez.

29
tawmas

Les montages sont exactement ce que vous voulez. C'est pour cela qu'ils sont conçus.

Que vous utilisiez les fixtures de style pytest ou setup et teardown (niveau module, classe ou méthode) xUnit, dépend des circonstances et de vos goûts personnels.

D'après ce que vous décrivez, il semble que vous pourriez utiliser pytest autouse fixtures .
Ou niveau de fonction de style xUnit setup_function ()/teardown_function () .

Pytest vous a complètement couvert. Si bien que c'est peut-être un tuyau d'information.

8
Okken

Vous pouvez utiliser la configuration au niveau du module/le démontage des appareils de Pytest.

Voici le lien

http://pytest.org/latest/xunit_setup.html

Cela fonctionne comme suit:

 def setup_module(module):
     """ setup any state specific to the execution of the given module."""

 def teardown_module(module):
     """ teardown any state that was previously setup with a setup_module
     method."""

 Test_Class():
        def test_01():
          #test 1 Code

Il appellera setup_module avant ce test et teardown_module après la fin du test.

Vous pouvez inclure cet appareil dans chaque script de test pour l'exécuter pour chaque test.

SI vous voulez utiliser quelque chose qui est commun à tous les tests d'un répertoire, vous pouvez utiliser les frameworks de paquet/directory level 

http://pythontesting.net/framework/nose/nose-fixture-reference/#package

Dans le fichier __init__.py du package, vous pouvez inclure les éléments suivants:

     def setup_package():
       '''Set up your environment for test package'''

     def teardown_package():
        '''revert the state '''
5
Arvind

Vous pouvez utiliser des décorateurs mais par programme, vous n'avez donc pas besoin de mettre le décorateur dans chaque méthode.

J'assume plusieurs choses dans le code suivant:

Les méthodes de test portent toutes le nom de "testXXX ()" Le décorateur est ajouté au même module que celui où les méthodes de test sont implémentées.

def test1():
    print ("Testing hello world")

def test2():
    print ("Testing hello world 2")

#This is the decorator
class TestChecker(object):
    def __init__(self, testfn, *args, **kwargs):
        self.testfn = testfn

    def pretest(self):
        print ('precheck %s' % str(self.testfn))
    def posttest(self):
        print ('postcheck %s' % str(self.testfn))
    def __call__(self):
        self.pretest()
        self.testfn()
        self.posttest()


for fn in dir() :
    if fn.startswith('test'):
        locals()[fn] = TestChecker(locals()[fn])

Maintenant, si vous appelez les méthodes de test ...

test1()
test2()

La sortie devrait être quelque chose comme:

precheck <function test1 at 0x10078cc20>
Testing hello world
postcheck <function test1 at 0x10078cc20>
precheck <function test2 at 0x10078ccb0>
Testing hello world 2
postcheck <function test2 at 0x10078ccb0>

Si vous avez des méthodes de test en tant que méthodes de classe, l'approche est également valide. Par exemple:

class TestClass(object):
    @classmethod
    def my_test(cls):
        print ("Testing from class method")

for fn in dir(TestClass) :
    if not fn.startswith('__'):
        setattr(TestClass, fn, TestChecker(getattr(TestClass, fn)))

L’appel à TestClass.my_test() imprimera:

precheck <bound method type.my_test of <class '__main__.TestClass'>>
Testing from class method 
postcheck <bound method type.my_test of <class '__main__.TestClass'>>
4
Roberto

Jetez un oeil à python décorators https://wiki.python.org/moin/PythonDecorators

0
venpa

Les projecteurs ont par défaut scope=function. Donc, si vous utilisez simplement une définition telle que

@pytest.fixture
def fixture_func(self)

La valeur par défaut est (scope = 'fonction'). 

Ainsi, toute finalisation dans la fonction fixture sera appelée après chaque test.

Réf: 1. http://programeveryday.com/post/pytest-creating-and-using-fixtures-for-streamlined-testing/

0
alpha_989