Executando um caso de teste específico no Django quando seu aplicativo tiver um diretório de testes

165

A documentação do Django ( http://docs.djangoproject.com/en/1.3/topics/testing/#running-tests ) diz que você pode executar casos de teste individuais especificando-os:

$ ./manage.py test animals.AnimalTestCase

Isso pressupõe que você tenha seus testes em um arquivo tests.py no seu aplicativo Django. Se isso for verdade, esse comando funcionará como esperado.

Eu tenho meus testes para uma aplicação Django em um diretório de testes:

my_project/apps/my_app/
├── __init__.py
├── tests
   ├── __init__.py
   ├── field_tests.py
   ├── storage_tests.py
├── urls.py
├── utils.py
└── views.py

O tests/__init__.pyarquivo tem uma função suite ():

import unittest

from my_project.apps.my_app.tests import field_tests, storage_tests

def suite():
    tests_loader = unittest.TestLoader().loadTestsFromModule
    test_suites = []
    test_suites.append(tests_loader(field_tests))
    test_suites.append(tests_loader(storage_tests))
    return unittest.TestSuite(test_suites)

Para executar os testes que eu faço:

$ ./manage.py test my_app

Tentar especificar um caso de teste individual gera uma exceção:

$ ./manage.py test my_app.tests.storage_tests.StorageTestCase
...
ValueError: Test label 'my_app.tests.storage_tests.StorageTestCase' should be of the form app.TestCase or app.TestCase.test_method

Eu tentei fazer o que a mensagem de exceção dizia:

$ ./manage.py test my_app.StorageTestCase
...
ValueError: Test label 'my_app.StorageTestCase' does not refer to a test

Como especifico um caso de teste individual quando meus testes estão em vários arquivos?

hekevintran
fonte

Respostas:

156

Caixa django-nariz . Ele permite que você especifique testes para executar como:

python manage.py test another.test:TestCase.test_method

ou conforme observado nos comentários, use a sintaxe:

python manage.py test another.test.TestCase.test_method
Sam Dolan
fonte
Obrigado @sdolan. Encontrou o mesmo problema que o hekevintran. Mudou para o django-nose e corrigiu esse problema, também funciona muito melhor do que o executor de teste padrão do Django.
21811 LeeMobile
Isso executa um teste, mas como executar um TestCase inteiro?
jMyles
5
@jMyles:another.test:TestCase
Sam Dolan
4
Atenção, pessoas como eu, que colam cegamente do Stackoverflow: Isso irá ocorrer sem o plug-in mencionado, use a sintaxe descrita na outra resposta (. Em vez de :) que funciona no Django 1.6+.
Andy Smith
1
Eu diminuí a votação desta resposta porque ela realmente não responde à pergunta do OP, que era como fazer isso no Django. Pelo contrário, ela apenas sugere para mudar para Nosetest
Josh Brown
175

Desde o Django 1.6, você pode executar um caso de teste completo ou único teste, usando a notação de ponto completa para o elemento que deseja executar.

A descoberta automática de teste agora encontrará testes em qualquer arquivo que comece com teste no diretório de trabalho, portanto, resolva a questão de renomear seus arquivos, mas agora você pode mantê-los dentro do diretório que deseja. Se você quiser usar nomes de arquivos personalizados, poderá especificar um padrão (padrão Django test runner) com o sinalizador de opção --pattern="my_pattern_*.py".

Portanto, se você estiver no seu manage.pydiretório e quiser executar o teste test_adentro da TestCasesubclasse Adentro de um arquivo tests.pyno aplicativo / módulo example, faça:

python manage.py test example.tests.A.test_a

Se você não deseja incluir uma dependência e está no Django 1.6 ou posterior, é assim que você faz.

Veja a documentação do Django para mais informações

cristiano2lopes
fonte
É bom ver esse recurso incorporado no Django agora.
24414 hekevintran
Não consigo fazer isso funcionar: error: option --pattern not recognizedeinvalid command name
geoidesic
Isso funciona muito bem no Django v3!
Kirk
11

Eu estava tendo esse problema e encontrei essa pergunta, caso mais alguém aparecesse, aqui estava o que eu descobri. O DjangoTestSuiteRuner usa um método chamado build_test (label) que descobre quais casos de teste executar com base no rótulo. Analisando esse método, eles estão fazendo um getattr () no módulo "models" ou "test". Isso significa que, se você devolver um conjunto em que o executor de testes não está procurando seus casos de teste nesse conjunto, ele será exibido apenas em um desses módulos.

Uma solução rápida é usar __init__.pypara importar seus testes diretamente, em vez de definir um conjunto. Isso os faz parte do módulo "test" e, portanto, o build_test (label) pode encontrá-los.

Para o seu exemplo acima, tests/__init__.pybasta conter:

from field_tests import *
from storage_tests import *

Isso não é muito elegante e, claro, se você está tentando fazer algo mais complicado com sua suíte, isso não funcionará, mas funcionaria nesse caso.

Chris T
fonte
11

Isso deve funcionar

python manage.py test my_app.tests.storage_tests
Swapnil Patel
fonte
3

Coloque esse código no seu __init__.py e ele importará todas as classes de teste no pacote e nos subpacotes. Isso permitirá que você execute testes específicos sem importar manualmente todos os arquivos.

import pkgutil
import unittest

for loader, module_name, is_pkg in pkgutil.walk_packages(__path__):
    module = loader.find_module(module_name).load_module(module_name)
    for name in dir(module):
        obj = getattr(module, name)
        if isinstance(obj, type) and issubclass(obj, unittest.case.TestCase):
            exec ('%s = obj' % obj.__name__)

Da mesma forma, para o seu conjunto de testes, você pode simplesmente usar:

def suite():   
    return unittest.TestLoader().discover("appname.tests", pattern="*.py")

Agora, tudo o que você precisa fazer para novos testes é gravá-los e garantir que eles estejam na pasta de testes. Não há mais manutenção tediosa das importações!

Bryce Drennan
fonte