Existe a possibilidade de escrever unittests do django sem configurar um db? Quero testar a lógica de negócios que não requer a instalação do banco de dados. E embora seja rápido configurar um banco de dados, eu realmente não preciso disso em algumas situações.
126
Respostas:
Você pode subclassificar DjangoTestSuiteRunner e substituir os métodos setup_databases e teardown_databases a serem aprovados.
Crie um novo arquivo de configurações e defina TEST_RUNNER para a nova classe que você acabou de criar. Então, quando você estiver executando seu teste, especifique seu novo arquivo de configurações com o sinalizador --settings.
Aqui está o que eu fiz:
Crie um corredor de traje de teste personalizado semelhante a este:
Crie configurações personalizadas:
Quando você estiver executando seus testes, execute-o da seguinte maneira com o sinalizador --settings definido no seu novo arquivo de configurações:
ATUALIZAÇÃO: abril / 2018
Desde o Django 1.8, o módulo foi movido para .
django.test.simple.DjangoTestSuiteRunner
'django.test.runner.DiscoverRunner'
Para mais informações, consulte a seção oficial do documento sobre corredores de teste personalizados.
fonte
--testrunner
opçãoGeralmente os testes em um aplicativo podem ser classificados em duas categorias
O Django suporta testes de unidade e integração.
Os testes de unidade não precisam configurar e desmontar o banco de dados e estes devemos herdar do SimpleTestCase .
Para casos de teste de integração herdados do TestCase, por sua vez, herda do TransactionTestCase e ele irá configurar e derrubar o banco de dados antes de executar cada teste.
Essa estratégia garantirá que o banco de dados seja criado e destruído apenas para os casos de teste que acessam o banco de dados e, portanto, os testes serão mais eficientes
fonte
De
django.test.simple
Então substitua em
DiscoverRunner
vez deDjangoTestSuiteRunner
.Use assim:
fonte
Eu escolhi herdar
django.test.runner.DiscoverRunner
e fazer algumas adições aorun_tests
método.Minha primeira adição verifica se é necessário configurar um banco de dados e permite que a
setup_databases
funcionalidade normal seja ativada se um banco de dados for necessário. Minha segunda adição permite que o normalteardown_databases
seja executado se osetup_databases
método tiver permissão para ser executado.Meu código pressupõe que qualquer TestCase que herda
django.test.TransactionTestCase
(e, portantodjango.test.TestCase
) exige que um banco de dados seja configurado. Eu fiz essa suposição porque os documentos do Django dizem:https://docs.djangoproject.com/en/1.6/topics/testing/tools/#django.test.SimpleTestCase
mysite / scripts / settings.py
Por fim, adicionei a seguinte linha ao arquivo settings.py do meu projeto.
mysite / settings.py
Agora, ao executar apenas testes não dependentes de banco de dados, minha suíte de testes executa uma ordem de magnitude mais rapidamente! :)
fonte
Atualizado: veja também esta resposta para usar uma ferramenta de terceiros
pytest
.@ Cesar está certo. Após a execução acidental
./manage.py test --settings=no_db_settings
, sem especificar o nome de um aplicativo, meu banco de dados de desenvolvimento foi eliminado.Para uma maneira mais segura, use o mesmo
NoDbTestRunner
, mas em conjunto com o seguintemysite/no_db_settings.py
:Você precisa criar um banco de dados chamado
_test_mysite_db
usando uma ferramenta de banco de dados externo. Em seguida, execute o seguinte comando para criar as tabelas correspondentes:Se você estiver usando o Sul, execute também o seguinte comando:
ESTÁ BEM!
Agora você pode executar testes de unidade incrivelmente rápidos (e seguros):
fonte
Como alternativa para modificar suas configurações para tornar o NoDbTestRunner "seguro", aqui está uma versão modificada do NoDbTestRunner que fecha a conexão atual do banco de dados e remove as informações de conexão das configurações e do objeto de conexão. Funciona para mim, teste-o no seu ambiente antes de confiar nele :)
fonte
__getitem__
mais. Useconnections._connections.default
para acessar o objeto.Outra solução seria ter sua classe de teste simplesmente herdada, em
unittest.TestCase
vez de qualquer uma das classes de teste do Django. Os documentos do Django ( https://docs.djangoproject.com/en/2.0/topics/testing/overview/#writing-tests ) contêm o seguinte aviso sobre isso:No entanto, se seu teste não usar o banco de dados, esse aviso não será necessário e você poderá colher os benefícios de não precisar executar cada caso de teste em uma transação.
fonte
As soluções acima também são boas. Mas a solução a seguir também reduzirá o tempo de criação do banco de dados se houver mais número de migrações. Durante o teste de unidade, executar o syncdb em vez de executar todas as migrações para o sul será muito mais rápido.
fonte
Meu host permite apenas a criação e remoção de bancos de dados a partir de sua GUI da Web, então eu estava recebendo o erro "Ocorreu um erro ao criar o banco de dados de teste: permissão negada" ao tentar executar
python manage.py test
.Eu esperava usar a opção --keepdb no django-admin.py, mas ela não parece mais ser suportada no Django 1.7.
O que acabei fazendo foi modificar o código do Django em ... / django / db / backends / creation.py, especificamente as funções _create_test_db e _destroy_test_db.
Pois
_create_test_db
eu comentei acursor.execute("CREATE DATABASE ...
linha e a substitui porpass
para que otry
bloco não estivesse vazio.Pois
_destroy_test_db
acabei de comentarcursor.execute("DROP DATABASE
- não precisei substituí-lo por nada, porque já havia outro comando no bloco (time.sleep(1)
).Depois disso, meus testes foram bem executados - embora eu tenha configurado uma versão test_ do meu banco de dados regular separadamente.
Esta não é uma ótima solução, é claro, porque ela quebrará se o Django for atualizado, mas eu tinha uma cópia local do Django devido ao uso do virtualenv, pelo menos tenho controle sobre quando / se atualizo para uma versão mais recente.
fonte
Outra solução não mencionada: foi fácil para mim implementar, porque eu já tenho vários arquivos de configurações (para local / teste / produção) que herdam de base.py. Portanto, diferente de outras pessoas, não precisei sobrescrever DATABASES ['padrão'], pois DATABASES não está definido em base.py
O SimpleTestCase ainda tentou se conectar ao meu banco de dados de teste e executar migrações. Quando criei um arquivo config / settings / test.py que não definiu DATABASES para nada, meus testes de unidade foram executados sem ele. Isso me permitiu usar modelos que tinham chave estrangeira e campos de restrição exclusivos. (A pesquisa inversa de chave estrangeira, que requer uma pesquisa de banco de dados, falha.)
(Django 2.0.6)
Snippets de código PS
fonte
Ao usar o corredor de teste do nariz (django-nose), você pode fazer algo assim:
my_project/lib/nodb_test_runner.py
:No seu
settings.py
você pode especificar o executor de teste lá, ou seja,TEST_RUNNER = 'lib.nodb_test_runner.NoDbTestRunner' . # Was 'django_nose.NoseTestSuiteRunner'
OU
Eu queria que ele executasse apenas testes específicos, então eu o executo da seguinte forma:
fonte