Eu tenho um diretório que contém meus testes de unidade Python. Cada módulo de teste de unidade possui o formato test _ *. Py . Estou tentando criar um arquivo chamado all_test.py que, você adivinhou, executará todos os arquivos no formulário de teste mencionado acima e retornará o resultado. Eu tentei dois métodos até agora; ambos falharam. Vou mostrar os dois métodos e espero que alguém lá fora saiba como fazer isso corretamente.
Para minha primeira tentativa valente, pensei: "Se eu importar todos os meus módulos de teste no arquivo e chamar esse unittest.main()
doodad, ele funcionará, certo?" Bem, acontece que eu estava errado.
import glob
import unittest
testSuite = unittest.TestSuite()
test_file_strings = glob.glob('test_*.py')
module_strings = [str[0:len(str)-3] for str in test_file_strings]
if __name__ == "__main__":
unittest.main()
Isso não funcionou, o resultado que obtive foi:
$ python all_test.py
----------------------------------------------------------------------
Ran 0 tests in 0.000s
OK
Na minha segunda tentativa, eu acho que talvez eu tente fazer todo esse teste de uma maneira mais "manual". Então, tentei fazer isso abaixo:
import glob
import unittest
testSuite = unittest.TestSuite()
test_file_strings = glob.glob('test_*.py')
module_strings = [str[0:len(str)-3] for str in test_file_strings]
[__import__(str) for str in module_strings]
suites = [unittest.TestLoader().loadTestsFromName(str) for str in module_strings]
[testSuite.addTest(suite) for suite in suites]
print testSuite
result = unittest.TestResult()
testSuite.run(result)
print result
#Ok, at this point I have a result
#How do I display it as the normal unit test command line output?
if __name__ == "__main__":
unittest.main()
Isso também não funcionou, mas parece tão próximo!
$ python all_test.py
<unittest.TestSuite tests=[<unittest.TestSuite tests=[<unittest.TestSuite tests=[<test_main.TestMain testMethod=test_respondes_to_get>]>]>]>
<unittest.TestResult run=1 errors=0 failures=0>
----------------------------------------------------------------------
Ran 0 tests in 0.000s
OK
Parece que tenho algum tipo de suíte e posso executar o resultado. Estou um pouco preocupado com o fato de que ele diz que só tenho run=1
, parece que deveria ser run=2
, mas é progresso. Mas como passo e mostro o resultado para main? Ou como eu basicamente o faço funcionar para que eu possa executar este arquivo e, ao fazê-lo, executar todos os testes de unidade neste diretório?
fonte
Respostas:
Com o Python 2.7 e superior, você não precisa escrever um novo código ou usar ferramentas de terceiros para fazer isso; a execução recursiva do teste via linha de comando é incorporada. Coloque um
__init__.py
em seu diretório de teste e:Você pode ler mais na documentação unittest do python 2.7 ou python 3.x.
fonte
Você poderia usar um executor de teste que faria isso por você. nariz é muito bom, por exemplo. Quando executado, ele encontra testes na árvore atual e os executa.
Atualizada:
Aqui está um código dos meus dias anteriores ao nariz. Você provavelmente não deseja a lista explícita de nomes de módulos, mas talvez o restante seja útil para você.
fonte
No python 3, se você estiver usando
unittest.TestCase
:__init__.py
arquivo vazio (ou não) em seutest
diretório ( deve ser nomeadotest/
)test/
desse padrão correspondem ao padrãotest_*.py
. Eles podem estar dentro de um subdiretório emtest/
e esses subdiretórios podem ser nomeados como qualquer coisa.Em seguida, você pode executar todos os testes com:
Feito! Uma solução com menos de 100 linhas. Espero que outro iniciante em python economize tempo encontrando isso.
fonte
Agora isso é possível diretamente do unittest: unittest.TestLoader.discover .
fonte
.... ---------------------------------------------------------------------- Ran 4 tests in 0.000s OK
Por que? A diferença, de onde vem?python file.py
Bem, estudando o código acima um pouco (especificamente usando
TextTestRunner
edefaultTestLoader
), consegui me aproximar bastante. Eventualmente, eu corrigi meu código passando apenas todos os conjuntos de testes para um único construtor de conjuntos, em vez de adicioná-los "manualmente", o que corrigia meus outros problemas. Então aqui está a minha solução.Sim, provavelmente é mais fácil usar o nariz do que fazer isso, mas isso está além do ponto.
fonte
Se você deseja executar todos os testes de várias classes de casos de teste e pode especificá-los explicitamente, é possível fazer o seguinte:
onde
uclid
é meu projeto eTestSymbols
eTestPatterns
são subclasses deTestCase
.fonte
TestSuite
aceita um iterável como argumento, você pode construir o iterável em um loop para evitar repetiçõesloader.loadTestsFromTestCase
.Eu usei o
discover
método e uma sobrecarga deload_tests
para alcançar esse resultado em um número mínimo de linhas de código:Execução em cinco algo como
fonte
Tentei várias abordagens, mas todas parecem defeituosas ou tenho que criar algum código, isso é irritante. Mas há uma maneira conveniente no linux, que é simplesmente encontrar todos os testes através de determinado padrão e depois invocá-los um a um.
e o mais importante, definitivamente funciona.
fonte
No caso de uma biblioteca ou aplicativo empacotado , você não deseja fazê-lo.
setuptools
fará isso por você .Apenas diga onde está o seu pacote de teste raiz, como:
E corra
python setup.py test
.A descoberta baseada em arquivo pode ser problemática no Python 3, a menos que você evite importações relativas no seu conjunto de testes, porque
discover
usa a importação de arquivos. Embora ele suporte opcionaltop_level_dir
, mas eu tive alguns erros de recursão infinitos. Portanto, uma solução simples para um código não empacotado é colocar o seguinte em__init__.py
seu pacote de teste (consulte o protocolo load_tests ).fonte
Eu uso o PyDev / LiClipse e ainda não descobri como executar todos os testes de uma só vez a partir da GUI. (editar: você clica com o botão direito do mouse na pasta de teste raiz e escolhe
Run as -> Python unit-test
Esta é minha solução atual:
Eu coloquei esse código em um módulo chamado
all
no meu diretório de teste. Se eu executar este módulo como o mais unittest do LiClipse, todos os testes serão executados. Se eu pedir para repetir apenas testes específicos ou com falha, apenas esses testes serão executados. Também não interfere no meu executor de teste da linha de comando (testes nos) - é ignorado.Pode ser necessário alterar os argumentos para com
discover
base na configuração do seu projeto.fonte
Com base na resposta de Stephen Cagle , adicionei suporte para módulos de teste aninhados.
O código de pesquisa todos os subdiretórios
.
para*Tests.py
arquivos que são então carregados. Espera que cada*Tests.py
um contenha uma única classe*Tests(unittest.TestCase)
que é carregada por vez e executada uma após a outra.Isso funciona com o aninhamento profundo arbitrário de diretórios / módulos, mas cada diretório deve conter
__init__.py
pelo menos um arquivo vazio . Isso permite que o teste carregue os módulos aninhados substituindo barras (ou barras invertidas) por pontos (consultereplace_slash_by_dot
).fonte
Esta é uma pergunta antiga, mas o que funcionou para mim agora (em 2019) é:
Todos os meus arquivos de teste estão na mesma pasta que os arquivos de origem e terminam com
_test
.fonte
Como a descoberta de teste parece ser um assunto completo, há alguma estrutura dedicada para testar a descoberta:
Mais informações aqui: https://wiki.python.org/moin/PythonTestingToolsTaxonomy
fonte
Esse script BASH executará o diretório de teste python unittest de QUALQUER LUGAR no sistema de arquivos, independentemente do diretório de trabalho em que você esteja: seu diretório de trabalho sempre estará onde esse
test
diretório está localizado.TODOS OS TESTES, independentes $ PWD
O módulo Python mais unido é sensível ao seu diretório atual, a menos que você diga onde (usando a
discover -s
opção).Isso é útil ao permanecer no diretório
./src
ou no./example
trabalho e você precisa de um teste de unidade geral rápido:TESTES SELECIONADOS, $ PWD independentes
Eu nomeio este arquivo utilitário:
runone.py
e use-o assim:Não há necessidade de um
test/__init__.py
arquivo sobrecarregar seu pacote / sobrecarga de memória durante a produção.fonte
Aqui está minha abordagem criando um wrapper para executar testes na linha de comando:
Por uma questão de simplicidade, desculpe meus padrões de codificação não- PEP8 .
Em seguida, você pode criar a classe BaseTest para componentes comuns para todos os seus testes, para que cada um deles se pareça com:
Para executar, basta especificar testes como parte dos argumentos da linha de comando, por exemplo:
fonte