Unittest setUp / tearDown para vários testes


118

Existe uma função que é disparada no início / final de um cenário de testes? As funções setUp e tearDown são acionadas antes / depois de cada teste.

Normalmente, gostaria de ter isto:

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

Por enquanto, esses setUp e tearDown são testes de unidade e espalhados em todos os meus cenários (contendo muitos testes), um é o primeiro teste, o outro é o último teste.


6
Qual versão? O módulo unittest foi expandido para incluir um module_setup e um module_teardown no Python 2.7.
S.Lott

3
2.7 também introduziu os métodos de classe setUpClass () e tearDownClass (), que permitiriam que você tivesse várias classes no mesmo arquivo com sua própria configuração e desmontagem por suíte.
Por Fagrell

Respostas:


132

A partir de 2.7 (de acordo com a documentação ) você obtém setUpClasse tearDownClassexecuta antes e depois dos testes em uma determinada classe serem executados, respectivamente. Alternativamente, se você tiver um grupo deles em um arquivo, você pode usar setUpModulee tearDownModule( documentação ).

Caso contrário, sua melhor aposta provavelmente será criar seu próprio TestSuite derivado e substituir run(). Todas as outras chamadas seriam tratadas pelo pai, e a execução chamaria seu código de configuração e desmontagem em torno de uma chamada para o pairun método .


71

Eu tenho o mesmo cenário, para mim os métodos setUpClass e tearDownClass funcionam perfeitamente

import unittest

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

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

6
Esta deve ser atualizada para ser a resposta aceita porque mostra um exemplo correto e essas funções TÊM que ser métodos de classe para funcionar, o que não é mencionado na resposta aceita.
NuclearPeon

1

Para python 2.5 e ao trabalhar com pydev, é um pouco difícil. Parece que pydev não usa o conjunto de testes, mas encontra todos os casos de teste individuais e os executa separadamente.

Minha solução para isso foi usar uma variável de classe como esta:

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

Com esse truque, quando você herda disso TestCase(em vez de do original unittest.TestCase), também herdará o runCountde 0. Então, no método run, o runCountdo caso de teste filho é verificado e incrementado. Isso deixa orunCount variável para esta classe em 0.

Isso significa que setUpClass será executado apenas uma vez por classe e não uma vez por instância.

Ainda não tenho um tearDownClassmétodo, mas acho que algo poderia ser feito usando esse contador.


0

Aqui está um exemplo: 3 métodos de teste acessam um recurso compartilhado, que é criado uma vez, não por teste.

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)
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.