Unittest setUp / tearDown pour plusieurs tests

119

Existe-t-il une fonction déclenchée au début / à la fin d'un scénario de tests? Les fonctions setUp et tearDown sont déclenchées avant / après chaque test.

Je voudrais généralement avoir ceci:

class TestSequenceFunctions(unittest.TestCase):

    def setUpScenario(self):
        start() #launched at the beginning, once

    def test_choice(self):
        element = random.choice(self.seq)
        self.assertTrue(element in self.seq)

    def test_sample(self):
        with self.assertRaises(ValueError):
            random.sample(self.seq, 20)
        for element in random.sample(self.seq, 5):
            self.assertTrue(element in self.seq)

    def tearDownScenario(self):
        end() #launched at the end, once

Pour l'instant, ces setUp et tearDown sont des tests unitaires et se répandent dans tous mes scénarios (contenant de nombreux tests), l'un est le premier test, l'autre est le dernier test.

cygne
la source
6
Quelle version? Le module unittest a été développé pour inclure un module_setup et un module_teardown dans Python 2.7.
S.Lott
3
2.7 a également introduit les méthodes de classe setUpClass () et tearDownClass (), qui vous permettraient d'avoir plusieurs classes dans le même fichier avec leur propre configuration et démontage par suite.
Per Fagrell

Réponses:

132

À partir de 2.7 (selon la documentation ), vous obtenez setUpClasset tearDownClassqui s'exécutent avant et après l'exécution des tests dans une classe donnée, respectivement. Sinon, si vous en avez un groupe dans un seul fichier, vous pouvez utiliser setUpModuleet tearDownModule( documentation ).

Sinon, votre meilleur pari sera probablement de créer votre propre TestSuite dérivé et de le remplacer run(). Tous les autres appels seraient gérés par le parent, et run appellerait votre code de configuration et de démontage autour d'un appel à la runméthode du parent .

David H. Clements
la source
72

J'ai le même scénario, pour moi les méthodes setUpClass et tearDownClass fonctionnent parfaitement

import unittest

class Test(unittest.TestCase):
    @classmethod
    def setUpClass(cls):
        cls._connection = createExpensiveConnectionObject()

    @classmethod
    def tearDownClass(cls):
        cls._connection.destroy()
V.Gupta
la source
6
Cela devrait être mis à jour pour être la réponse acceptée car il montre un exemple correct et ces fonctions DOIVENT être des méthodes de classe pour fonctionner, ce qui n'est pas mentionné dans la réponse acceptée.
NuclearPeon
1

Pour python 2.5 et lorsque vous travaillez avec pydev, c'est un peu difficile. Il semble que pydev n'utilise pas la suite de tests, mais trouve tous les cas de test individuels et les exécute tous séparément.

Ma solution pour cela utilisait une variable de classe comme celle-ci:

class TestCase(unittest.TestCase):
    runCount = 0

    def setUpClass(self):
        pass # overridden in actual testcases

    def run(self, result=None):
        if type(self).runCount == 0:
            self.setUpClass()

        super(TestCase, self).run(result)
        type(self).runCount += 1

Avec cette astuce, lorsque vous héritez de ceci TestCase(au lieu de celui de l'original unittest.TestCase), vous hériterez également de la valeur runCountde 0. Ensuite, dans la méthode run, le runCounttestcase enfant est vérifié et incrémenté. Cela laisse la runCountvariable de cette classe à 0.

Cela signifie que le setUpClassne sera exécuté qu'une fois par classe et pas une fois par instance.

Je n'ai pas tearDownClassencore de méthode, mais je suppose que quelque chose pourrait être fait avec l'utilisation de ce compteur.

sanderd17
la source
0

Voici un exemple: 3 méthodes de test accèdent à une ressource partagée, qui est créée une fois, pas par test.

import unittest
import random

class TestSimulateLogistics(unittest.TestCase):

    shared_resource = None

    @classmethod
    def setUpClass(cls):
        cls.shared_resource = random.randint(1, 100)

    @classmethod
    def tearDownClass(cls):
        cls.shared_resource = None

    def test_1(self):
        print('test 1:', self.shared_resource)

    def test_2(self):
        print('test 2:', self.shared_resource)

    def test_3(self):
        print('test 3:', self.shared_resource)
kadir malak
la source