Unittest setUp / tearDown per diversi test


118

Esiste una funzione che viene attivata all'inizio / alla fine di uno scenario di test? Le funzioni setUp e tearDown vengono attivate prima / dopo ogni singolo test.

In genere mi piacerebbe avere questo:

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

Per ora, questi setUp e tearDown sono unit test e diffusi in tutti i miei scenari (contenenti molti test), uno è il primo test, l'altro è l'ultimo test.


6
Quale versione? Il modulo unittest è stato espanso per includere module_setup e module_teardown in Python 2.7.
S.Lott

3
2.7 ha anche introdotto i metodi di classe setUpClass () e tearDownClass (), che consentono di avere diverse classi nello stesso file con la propria configurazione e smontaggio per suite.
Secondo Fagrell il

Risposte:


132

A partire dalla versione 2.7 (secondo la documentazione ) ottieni setUpClasse tearDownClassquali vengono eseguiti prima e dopo l'esecuzione dei test in una data classe, rispettivamente. In alternativa, se ne hai un gruppo in un file, puoi usare setUpModulee tearDownModule( documentazione ).

Altrimenti la soluzione migliore sarà probabilmente creare la propria TestSuite derivata e sovrascriverla run(). Tutte le altre chiamate verrebbero gestite dal genitore e l'esecuzione chiamerebbe il tuo codice di configurazione e smontaggio attorno a una chiamata fino al runmetodo del genitore .


71

Ho lo stesso scenario, per me i metodi setUpClass e tearDownClass funzionano perfettamente

import unittest

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

    @classmethod
    def tearDownClass(cls):
        cls._connection.destroy()

6
Questa dovrebbe essere aggiornata per essere la risposta accettata perché mostra un esempio corretto e queste funzioni DEVONO essere metodi di classe per funzionare, cosa che non è menzionata nella risposta accettata.
NuclearPeon

1

Per python 2.5 e quando si lavora con pydev, è un po 'difficile. Sembra che pydev non utilizzi la suite di test, ma trova tutti i singoli casi di test e li esegue tutti separatamente.

La mia soluzione per questo stava usando una variabile di classe come questa:

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

Con questo trucco, quando erediti da questo TestCase(invece che dall'originale unittest.TestCase), erediterai anche il valore runCountdi 0. Quindi nel metodo run, il runCounttestcase figlio viene controllato e incrementato. Questo lascia la runCountvariabile per questa classe a 0.

Ciò significa che setUpClassverrà eseguito solo una volta per classe e non una volta per istanza.

Non ho ancora un tearDownClassmetodo, ma immagino che si potrebbe fare qualcosa usando quel contatore.


0

Ecco un esempio: 3 metodi di test accedono a una risorsa condivisa, che viene creata una volta, non per 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)
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.