A estrutura de diretórios muito comum, mesmo para um módulo Python simples, parece separar os testes de unidade em seu próprio test
diretório:
new_project/
antigravity/
antigravity.py
test/
test_antigravity.py
setup.py
etc.
por exemplo, veja este tutorial do projeto Python .
Minha pergunta é simplesmente: Qual é a maneira usual de realmente executar os testes? Eu suspeito que isso seja óbvio para todos, exceto eu, mas você não pode simplesmente executar a python test_antigravity.py
partir do diretório de teste, pois import antigravity
isso falhará, pois o módulo não está no caminho.
Sei que poderia modificar o PYTHONPATH e outros truques relacionados ao caminho de pesquisa, mas não acredito que seja a maneira mais simples - tudo bem se você é o desenvolvedor, mas não é realista esperar que seus usuários usem se eles apenas quiserem verificar os testes. passagem.
A outra alternativa é apenas copiar o arquivo de teste para o outro diretório, mas parece um pouco idiota e perde o sentido de tê-los em um diretório separado para começar.
Então, se você tivesse baixado a fonte do meu novo projeto, como você executaria os testes de unidade? Prefiro uma resposta que me permita dizer aos meus usuários: "Para executar os testes de unidade, faça o X."
fonte
unittest
interface da linha de comandos, conforme descrito na minha resposta abaixo, para que você não precise adicionar o diretório ao caminho.Respostas:
A melhor solução, na minha opinião, é usar a
unittest
interface da linha de comandos que adicionará o diretório ao diretório parasys.path
que você não precise (feito naTestLoader
classe).Por exemplo, para uma estrutura de diretórios como esta:
Você pode simplesmente executar:
Para uma estrutura de diretórios como a sua:
E nos módulos de teste dentro do
test
pacote, você pode importar oantigravity
pacote e seus módulos como de costume:Executando um único módulo de teste:
Para executar um único módulo de teste, neste caso
test_antigravity.py
:Basta referenciar o módulo de teste da mesma maneira que você o importa.
Executando um único caso de teste ou método de teste:
Além disso, você pode executar um
TestCase
método de teste único ou único:Executando todos os testes:
Você também pode usar a descoberta de testes, que descobrirá e executará todos os testes para você; eles devem ser módulos ou pacotes nomeados
test*.py
(podem ser alterados com o-p, --pattern
sinalizador):Isso executará todos os
test*.py
módulos dentro dotest
pacote.fonte
python -m unittest discover
irá encontrar e executar testes notest
diretório se eles forem nomeadostest*.py
. Se você nomeou o subdiretóriotests
, usepython -m unittest discover -s tests
e se você nomeou os arquivos de testeantigravity_test.py
, usepython -m unittest discover -s tests -p '*test.py'
Nomes de arquivos podem usar sublinhados, mas não traços.ImportError: No module named 'test.test_antigravity'
devido a um conflito com o submódulo de teste da biblioteca mais unida. Talvez um especialista possa confirmar e alterar o nome do subdiretório de respostas para, por exemplo, 'testes' (plural).test_antigravity.py
ainda gera um erro de importação para ambosimport antigravity
efrom antigravity import antigravity
também. Eu tenho os dois__init_.py
arquivos e estou ligandopython3 -m unittest discover
donew project
diretório. O que mais pode estar errado?test/__init__.py
é crucial aqui, mesmo vaziostest
é especial ... mas apenas para o registro, não é. : Ppython -m unittest discover
trabalha com arquivos de testetests/
tão bem quantotest/
.A solução mais simples para seus usuários é fornecer um script executável (
runtests.py
ou algo parecido) que inicialize o ambiente de teste necessário, incluindo, se necessário, adicionandosys.path
temporariamente o diretório do projeto raiz . Isso não requer que os usuários definam variáveis de ambiente, algo assim funciona bem em um script de inicialização:Então, suas instruções para seus usuários podem ser tão simples quanto "
python runtests.py
".Obviamente, se o caminho que você realmente precisa é
os.path.dirname(__file__)
, você não precisa adicioná-losys.path
; O Python sempre coloca o diretório do script atualmente em execução no início desys.path
, portanto, dependendo da sua estrutura de diretórios, basta localizá-loruntests.py
no lugar certo.Além disso, o módulo mais unittest no Python 2.7+ (que é suportado como unittest2 para Python 2.6 e versões anteriores) agora possui a descoberta de teste incorporada; portanto, o nariz não é mais necessário se você desejar a descoberta automatizada de teste: suas instruções ao usuário podem ser tão simples quanto
python -m unittest discover
.fonte
python -m pdb tests\test_antigravity.py
. Dentro do pdb, executei osys.path.insert(0, "antigravity")
que permitia que a instrução de importação resolvesse como se estivesse executando o módulo.Geralmente, crio um script "executar testes" no diretório do projeto (aquele comum ao diretório de origem e
test
) que carrega meu conjunto "Todos os testes". Geralmente, esse é o código padrão, para que eu possa reutilizá-lo de um projeto para outro.run_tests.py:
test / all_tests.py (de Como executo todos os testes de unidade Python em um diretório? )
Com esta configuração, você pode realmente apenas
include antigravity
nos seus módulos de teste. A desvantagem é que você precisaria de mais código de suporte para executar um teste específico ... Eu apenas os executava o tempo todo.fonte
run tests
script no diretório do projeto e encontrei uma maneira muito mais limpa de fazer isso. Altamente recomendado.Do artigo ao qual você vinculou:
Talvez você deva olhar o nariz, como sugere?
fonte
Eu tive o mesmo problema, com uma pasta de testes de unidade separada. Das sugestões mencionadas, adiciono o caminho de origem absoluto para
sys.path
.O benefício da seguinte solução é que é possível executar o arquivo
test/test_yourmodule.py
sem primeiro alterar o diretório de teste:fonte
se você executar "python setup.py develop", o pacote estará no caminho. Mas você pode não querer fazer isso porque pode infectar a instalação do sistema python, e é por isso que existem ferramentas como virtualenv e buildout .
fonte
Solução / exemplo para o módulo unittest do Python
Dada a seguinte estrutura do projeto:
Você pode executar seu projeto a partir do diretório raiz com o
python project_name
que chamaProjectName/project_name/__main__.py
.Para executar seus testes
python test
, efetivamente executandoProjectName/test/__main__.py
, você precisa fazer o seguinte:1) Transforme seu
test/models
diretório em um pacote, adicionando um__init__.py
arquivo. Isso torna os casos de teste dentro do subdiretório acessíveis a partir dotest
diretório pai .2) Modifique o caminho do sistema
test/__main__.py
para incluir oproject_name
diretório.Agora você pode importar com sucesso itens de
project_name
seus testes.fonte
Use
setup.py develop
para tornar seu diretório de trabalho parte do ambiente Python instalado e, em seguida, execute os testes.fonte
invalid command 'develop'
e essa opção não é mencionada se eu pedirsetup.py --help-commands
. Precisa haver algo emsetup.py
si para que isso funcione?import setuptools
no meusetup.py
arquivo. Mas acho que isso mostra que isso não funcionará o tempo todo para os módulos de outras pessoas.pip install -e .
Da mesma forma, o pacote é adicionado ao ambiente Python sem copiar a fonte, permitindo que você continue editando o local onde está.pip install -e .
é exatamente a mesma coisa quepython setup.py develop
, apenas monitora o seusetup.py
para usar as ferramentas de configuração, mesmo que não funcione, de modo que funciona de qualquer maneira.Se você usa o VS Code e seus testes estão localizados no mesmo nível do seu projeto, a execução e a depuração do código não funcionam imediatamente. O que você pode fazer é alterar seu arquivo launch.json:
A linha principal aqui é envFile
Na raiz do seu projeto, adicione o arquivo .env
Dentro do seu arquivo .env, adicione o caminho à raiz do seu projeto. Isso adicionará temporariamente
caminho para o seu projeto e você poderá usar testes de unidade de depuração do VS Code
fonte
Notei que, se você executar a interface de linha de comando mais unida do diretório "src", as importações funcionarão corretamente sem modificações.
Se você deseja colocar isso em um arquivo em lotes no diretório do projeto, pode fazer o seguinte:
fonte
Eu tenho o mesmo problema há muito tempo. O que eu escolhi recentemente é a seguinte estrutura de diretórios:
e no
__init__.py
script da pasta de teste, escrevo o seguinte:Super importante para compartilhar o projeto é o Makefile, porque ele impõe a execução correta dos scripts. Aqui está o comando que eu coloquei no Makefile:
O Makefile é importante não apenas por causa do comando que é executado, mas também por causa de onde ele é executado . Se você cdasse os testes e fizesse
python -m unittest discover .
isso, não funcionaria porque o script init em unit_tests chama os.getcwd (), que apontaria para o caminho absoluto incorreto (que seria anexado ao sys.path e você estaria ausente sua pasta de origem). Os scripts seriam executados desde que o Discover encontre todos os testes, mas eles não seriam executados corretamente. Portanto, o Makefile está lá para evitar ter que se lembrar desse problema.Eu realmente gosto dessa abordagem porque não preciso tocar na minha pasta src, nos meus testes de unidade ou nas minhas variáveis de ambiente e tudo funciona sem problemas.
Deixe-me saber se vocês gostam.
Espero que ajude,
fonte
A seguir está a estrutura do meu projeto:
Achei melhor importar no método setUp ():
fonte
Eu uso o Python 3.6.2
Para instalar o pytest :
sudo pip install pytest
Não defini nenhuma variável de caminho e minhas importações não estão falhando com a mesma estrutura de projeto de "teste".
Eu comentei essas coisas:
if __name__ == '__main__'
assim:test_antigravity.py
fonte
É possível usar o wrapper que executa testes selecionados ou todos os testes.
Por exemplo:
ou para executar todos os testes, use recursivamente globbing (
tests/**/*.py
) (ativar porshopt -s globstar
).O wrapper pode basicamente usar
argparse
para analisar os argumentos como:Em seguida, carregue todos os testes:
adicione-os ao seu conjunto de testes (usando
inspect
):e execute-os:
Veja este exemplo para mais detalhes.
Consulte também: Como executar todos os testes de unidade Python em um diretório?
fonte
Python 3+
Adicionando a @Pierre
Usando uma
unittest
estrutura de diretórios como esta:Para executar o módulo de teste
test_antigravity.py
:Ou um único
TestCase
Obrigatório , não esqueça que,
__init__.py
mesmo que vazio, caso contrário não funcionará.fonte
Você não pode importar do diretório pai sem algum vodu. Aqui está outra maneira de trabalhar com pelo menos Python 3.6.
Primeiro, tenha um arquivo test / context.py com o seguinte conteúdo:
Em seguida, faça a seguinte importação no arquivo test / test_antigravity.py:
Observe que o motivo dessa cláusula try-except é que
Com esse truque, ambos trabalham.
Agora você pode executar todos os arquivos de teste no diretório de teste com:
ou execute um arquivo de teste individual com:
Ok, não é muito mais bonito do que ter o conteúdo de context.py em test_antigravity.py, mas talvez um pouco. Sugestões são bem vindas.
fonte
Se você tiver vários diretórios em seu diretório de teste, precisará adicionar a cada diretório um
__init__.py
arquivo.Em seguida, para executar todos os testes de uma vez, execute:
Fonte:
python -m unittest -h
fonte
Esse script BASH executará o diretório de teste unittest python de qualquer lugar do sistema de arquivos, independentemente do diretório de trabalho em que você esteja.
Isso é útil ao permanecer no diretório
./src
ou no./example
trabalho e você precisa de um teste de unidade rápido:Não há necessidade de um
test/__init__.py
arquivo sobrecarregar seu pacote / sobrecarga de memória durante a produção.fonte
Dessa forma, você poderá executar os scripts de teste de onde quiser, sem mexer nas variáveis do sistema na linha de comando.
Isso adiciona a pasta principal do projeto ao caminho do python, com o local encontrado em relação ao próprio script, não em relação ao diretório de trabalho atual.
Adicione isso ao topo de todos os seus scripts de teste. Isso adicionará a pasta principal do projeto ao caminho do sistema, para que qualquer módulo importado que trabalhe a partir daí agora funcione. E não importa de onde você executa os testes.
Obviamente, você pode alterar o arquivo project_path_hack para corresponder ao local da pasta principal do projeto.
fonte
Se você está procurando uma solução somente de linha de comando:
Com base na seguinte estrutura de diretórios (generalizada com um diretório de origem dedicado):
Windows : (pol
new_project
)Veja esta pergunta se você deseja usá-lo em um loop for batch.
Linux : (in
new_project
)Com essa abordagem, também é possível adicionar mais diretórios ao PYTHONPATH, se necessário.
fonte
Você realmente deve usar a ferramenta pip.
Use
pip install -e .
para instalar seu pacote no modo de desenvolvimento. Essa é uma prática muito boa, recomendada pelo pytest (consulte a documentação de boas práticas , onde você também pode encontrar dois layouts de projeto a seguir).fonte
pytest
é muito melhor executar testes, devido à saída do console que você obtém, em cores, com informações de rastreamento de pilha e informações detalhadas sobre erros de asserção.