Existe algum mecanismo simples para substituir as configurações do Django para um teste de unidade? Tenho um gerente em um de meus modelos que retorna um número específico dos objetos mais recentes. O número de objetos que ele retorna é definido por uma configuração NUM_LATEST.
Isso tem o potencial de fazer meus testes falharem se alguém alterar a configuração. Como posso substituir as configurações setUp()
e, posteriormente, restaurá-las tearDown()
? Se isso não for possível, há alguma maneira de fazer o monkey patch do método ou simular as configurações?
EDIT: Aqui está meu código de gerente:
class LatestManager(models.Manager):
"""
Returns a specific number of the most recent public Articles as defined by
the NEWS_LATEST_MAX setting.
"""
def get_query_set(self):
num_latest = getattr(settings, 'NEWS_NUM_LATEST', 10)
return super(LatestManager, self).get_query_set().filter(is_public=True)[:num_latest]
O gerente usa settings.NEWS_LATEST_MAX
para fatiar o queryset. O getattr()
é usado simplesmente para fornecer um padrão caso a configuração não exista.
django
settings
testing
django-managers
Soviut
fonte
fonte
Respostas:
EDITAR: Esta resposta se aplica se você deseja alterar as configurações de um pequeno número de testes específicos .
Desde Django 1.4, existem maneiras de substituir as configurações durante os testes: https://docs.djangoproject.com/en/dev/topics/testing/tools/#overriding-settings
TestCase terá um gerenciador de contexto self.settings e também um decorador @override_settings que pode ser aplicado a um método de teste ou a uma subclasse TestCase inteira.
Esses recursos ainda não existiam no Django 1.3.
Se você quiser alterar as configurações de todos os seus testes, deverá criar um arquivo de configurações separado para teste, que pode carregar e substituir as configurações do seu arquivo de configurações principal. Existem várias boas abordagens para isso nas outras respostas; Tenho visto variações bem-sucedidas nas abordagens de hspander e dmitrii .
fonte
self.settings().wrapped.MEDIA_ROOT
, mas isso é terrível.@modify_settings(MIDDLEWARE_CLASSES=...
(obrigado por esta resposta)Você pode fazer o que quiser com a
UnitTest
subclasse, incluindo definir e ler as propriedades da instância:Como os casos de teste do django são executados em um único thread, estou curioso para saber o que mais pode estar modificando o valor NUM_LATEST? Se esse "algo mais" for acionado por sua rotina de teste, não tenho certeza se qualquer quantidade de patching do macaco salvará o teste sem invalidar a veracidade dos próprios testes.
fonte
settings.TEMPLATE_LOADERS
... Então esse não é o jeito geral pelo menos, as configurações ou o Django não é recarregado ou qualquer coisa com esse truque.Embora a configuração das configurações de substituição no tempo de execução possa ajudar, na minha opinião, você deve criar um arquivo separado para teste. Isso economiza muitas configurações para teste e garantiria que você nunca faria algo irreversível (como limpar o banco de dados de teste).
Digamos que seu arquivo de teste exista em 'my_project / test_settings.py', adicione
em seu manage.py. Isso garantirá que, ao executar,
python manage.py test
use apenas test_settings. Se você estiver usando algum outro cliente de teste, como o pytest, pode facilmente adicioná-lo ao pytest.inifonte
Você pode passar na
--settings
opção ao executar testesfonte
Atualização : a solução abaixo só é necessária no Django 1.3.x e anteriores. Para> 1,4, veja a resposta de slinkp .
Se você alterar as configurações com frequência em seus testes e usar Python ≥2,5, isso também é útil:
Então você pode fazer:
fonte
yield
instrução, com a parte final da função contida nofinally
bloco, para que as configurações sejam sempre revertidas.@override_settings
é ótimo se você não tiver muitas diferenças entre as configurações do ambiente de produção e teste.Em outro caso, é melhor você apenas ter arquivos de configurações diferentes. Neste caso, seu projeto será semelhante a este:
Portanto, você precisa ter a maior parte de suas configurações em
base.py
e, em seguida, em outros arquivos, você precisa importar tudo de lá e substituir algumas opções. Estatest.py
será a aparência do seu arquivo:E então você precisa especificar a
--settings
opção como na resposta @MicroPyramid ou especificarDJANGO_SETTINGS_MODULE
a variável de ambiente e então você pode executar seus testes:fonte
Encontrei isto ao tentar corrigir alguns doctests ... Para completar, quero mencionar que se você for modificar as configurações ao usar doctests, você deve fazer isso antes de importar qualquer outra coisa ...
fonte
Para usuários pytest .
O maior problema é:
override_settings
não funciona com pytest.TestCase
fará com que funcione, mas você não pode usar fixtures pytest.A solução é usar o
settings
acessório documentado aqui .Exemplo
E no caso de você precisar atualizar vários campos
fonte
Você pode substituir a configuração mesmo para uma única função de teste.
ou você pode substituir a configuração de cada função na classe.
fonte
Estou usando o pytest.
Consegui resolver isso da seguinte maneira:
fonte
Você pode substituir as configurações no teste desta maneira:
E se você precisar dessas mesmas configurações em outro arquivo, basta importar diretamente
test_settings
.fonte
Se você tiver vários arquivos de teste colocados em um subdiretório (pacote python), você pode substituir as configurações de todos esses arquivos com base na condição de presença da string de 'teste' em sys.argv
__init__.py:
Não é a melhor abordagem. Usei-o para mudar o corretor de Celery de Redis para Memória.
fonte
Eu criei um novo arquivo settings_test.py que importaria tudo do arquivo settings.py e modificaria o que fosse diferente para fins de teste. No meu caso, eu queria usar um intervalo de armazenamento em nuvem diferente ao testar.
settings_test.py:
manage.py:
fonte