Estrutura UnitTest - Guia Rápido
O teste de unidade é um método de teste de software pelo qual unidades individuais de código-fonte, como funções, métodos e classes, são testadas para determinar se são adequadas para uso. Intuitivamente, pode-se ver uma unidade como a menor parte testável de um aplicativo. Os testes de unidade são fragmentos de código curtos criados por programadores durante o processo de desenvolvimento. Ele forma a base para o teste de componentes.
O teste de unidade pode ser feito das duas maneiras a seguir -
Teste Manual | Teste Automatizado |
---|---|
Executar os casos de teste manualmente sem qualquer suporte de ferramenta é conhecido como teste manual.
|
Ter suporte de ferramenta e executar os casos de teste usando a ferramenta de automação é conhecido como teste de automação.
|
JUnit é uma estrutura de teste de unidade para a linguagem de programação Java. JUnit tem sido importante no desenvolvimento de desenvolvimento orientado a testes e faz parte de uma família de estruturas de teste de unidade conhecidas coletivamente como xUnit que se originou com JUnit. Você pode descobrir o Tutorial JUnit aqui.
A estrutura de teste de unidade Python, às vezes referida como “PyUnit”, é uma versão da linguagem Python do JUnit desenvolvida por Kent Beck e Erich Gamma. PyUnit faz parte da Biblioteca Padrão do Python a partir da versão 2.1 do Python.
A estrutura de teste de unidade Python suporta automação de teste, compartilhamento de configuração e código de desligamento para testes, agregação de testes em coleções e independência dos testes da estrutura de relatório. O módulo unittest fornece classes que facilitam o suporte a essas qualidades para um conjunto de testes.
Este tutorial foi preparado para os iniciantes para ajudá-los a entender a funcionalidade básica da estrutura de teste Python. Depois de concluir este tutorial, você se encontrará com um nível moderado de experiência no uso da estrutura de teste Python, de onde poderá avançar para os próximos níveis.
Você deve ter experiência razoável em desenvolvimento de software usando a linguagem Python. Nosso tutorial Python é um bom lugar para começar a aprender Python. Conhecimento básico de teste de software também é desejável.
Configuração de ambiente
As classes necessárias para escrever testes podem ser encontradas no módulo 'teste de unidade'. Se você estiver usando versões mais antigas do Python (anteriores ao Python 2.1), o módulo pode ser baixado dehttp://pyunit.sourceforge.net/. No entanto, o módulo unittest agora faz parte da distribuição padrão do Python; portanto, não requer instalação separada.
'unittest' suporta automação de teste, compartilhamento de configuração e código de desligamento para testes, agregação de testes em coleções e independência dos testes da estrutura de relatório.
O módulo unittest fornece classes que facilitam o suporte a essas qualidades para um conjunto de testes.
Para conseguir isso, o unittest suporta os seguintes conceitos importantes -
test fixture- Isso representa a preparação necessária para realizar um ou mais testes e quaisquer ações de limpeza associadas. Isso pode envolver, por exemplo, a criação de bancos de dados temporários ou proxy, diretórios ou o início de um processo de servidor.
test case- Esta é a menor unidade de teste. Isso verifica se há uma resposta específica a um determinado conjunto de entradas. unittest fornece uma classe base,TestCase, que pode ser usado para criar novos casos de teste.
test suite- Esta é uma coleção de casos de teste, suítes de teste ou ambos. Isso é usado para agregar testes que devem ser executados juntos. As suítes de teste são implementadas pela classe TestSuite.
test runner- Este é um componente que orquestra a execução de testes e fornece o resultado para o usuário. O executor pode usar uma interface gráfica, uma interface textual ou retornar um valor especial para indicar os resultados da execução dos testes.
Criando um Teste de Unidade
As etapas a seguir estão envolvidas na escrita de um teste de unidade simples -
Step 1 - Importe o módulo unittest em seu programa.
Step 2- Defina uma função a ser testada. No exemplo a seguir, a função add () deve ser submetida a teste.
Step 3 - Crie um caso de teste subclassificando unittest.TestCase.
Step 4- Definir um teste como método dentro da classe. O nome do método deve começar com 'teste'.
Step 5- Cada chamada de teste declara a função da classe TestCase. Existem muitos tipos de afirmações. O exemplo a seguir chama a função assertEquals ().
Step 6 - a função assertEquals () compara o resultado da função add () com o argumento arg2 e lança assertionError se a comparação falhar.
Step 7 - Finalmente, chame o método main () do módulo unittest.
import unittest
def add(x,y):
return x + y
class SimpleTest(unittest.TestCase):
def testadd1(self):
self.assertEquals(add(4,5),9)
if __name__ == '__main__':
unittest.main()
Step 8 - Execute o script acima a partir da linha de comando.
C:\Python27>python SimpleTest.py
.
----------------------------------------------------------------------
Ran 1 test in 0.000s
OK
Step 9 - Os três seguintes podem ser os resultados possíveis de um teste -
Sr. Não | Mensagem e descrição |
---|---|
1 | OK O teste passa. 'A' é exibido no console. |
2 | FAIL O teste não passa e gera uma exceção AssertionError. 'F' é exibido no console. |
3 | ERROR O teste levanta uma exceção diferente de AssertionError. 'E' é exibido no console. |
Esses resultados são exibidos no console por '.', 'F' e 'E' respectivamente.
Interface da Linha de comando
O módulo unittest pode ser usado a partir da linha de comando para executar testes únicos ou múltiplos.
python -m unittest test1
python -m unittest test_module.TestClass
python -m unittest test_module.TestClass.test_method
unittest suporta as seguintes opções de linha de comando. Para obter uma lista de todas as opções de linha de comando, use o seguinte comando -
Python –m unittest -h
Sr. Não | Opção e descrição |
---|---|
1 | -h, --help Mostrar esta mensagem |
2 | v, --verbose Saída detalhada |
3 | -q, --quiet Saída mínima |
4 | -f, --failfast Pare na primeira falha |
5 | -c, --catch Pegue o controle-C e exiba os resultados |
6 | -b, --buffer Buffer stdout e stderr durante as execuções de teste |
Este capítulo discute as classes e métodos definidos no módulo unittest. Existem cinco classes principais neste módulo.
Classe TestCase
O objeto desta classe representa a menor unidade testável. Ele mantém as rotinas de teste e fornece ganchos para preparar cada rotina e para limpar depois.
Os seguintes métodos são definidos na classe TestCase -
Sr. Não | Método e Descrição |
---|---|
1 | setUp() Método chamado para preparar o dispositivo de teste. Isso é chamado imediatamente antes de chamar o método de teste |
2 | tearDown() Método chamado imediatamente após o método de teste ter sido chamado e o resultado registrado. Isso é chamado mesmo se o método de teste gerou uma exceção, |
3 | setUpClass() Um método de classe chamado antes dos testes em uma execução de classe individual. |
4 | tearDownClass() Um método de classe chamado após a execução de testes em uma classe individual. |
5 | run(result = None) Execute o teste, coletando o resultado no objeto de resultado de teste aprovado como resultado . |
6 | skipTest(reason) Chamar isso durante um método de teste ou setUp () ignora o teste atual. |
7 | debug() Execute o teste sem coletar o resultado. |
8 | shortDescription() Retorna uma descrição de uma linha do teste. |
Luminárias
Pode haver vários testes escritos dentro de uma classe TestCase. Esses métodos de teste podem precisar de conexão de banco de dados, arquivos temporários ou outros recursos para serem inicializados. Estes são chamados de acessórios. TestCase inclui um gancho especial para configurar e limpar quaisquer acessórios necessários para seus testes. Para configurar os aparelhos, substitua setUp (). Para limpar, substitua tearDown ().
No exemplo a seguir, dois testes são escritos dentro da classe TestCase. Eles testam o resultado da adição e subtração de dois valores. O método setup () inicializa os argumentos com base em shortDescription () de cada teste. O método teardown () será executado no final de cada teste.
import unittest
class simpleTest2(unittest.TestCase):
def setUp(self):
self.a = 10
self.b = 20
name = self.shortDescription()
if name == "Add":
self.a = 10
self.b = 20
print name, self.a, self.b
if name == "sub":
self.a = 50
self.b = 60
print name, self.a, self.b
def tearDown(self):
print '\nend of test',self.shortDescription()
def testadd(self):
"""Add"""
result = self.a+self.b
self.assertTrue(result == 100)
def testsub(self):
"""sub"""
result = self.a-self.b
self.assertTrue(result == -10)
if __name__ == '__main__':
unittest.main()
Execute o código acima na linha de comando. Ele dá a seguinte saída -
C:\Python27>python test2.py
Add 10 20
F
end of test Add
sub 50 60
end of test sub
.
================================================================
FAIL: testadd (__main__.simpleTest2)
Add
----------------------------------------------------------------------
Traceback (most recent call last):
File "test2.py", line 21, in testadd
self.assertTrue(result == 100)
AssertionError: False is not true
----------------------------------------------------------------------
Ran 2 tests in 0.015s
FAILED (failures = 1)
Fixture da classe
A classe TestCase tem um método setUpClass () que pode ser sobrescrito para ser executado antes da execução de testes individuais dentro de uma classe TestCase. Da mesma forma, o método tearDownClass () será executado após todos os testes da classe. Ambos os métodos são métodos de classe. Portanto, eles devem ser decorados com a diretiva @classmethod.
O exemplo a seguir demonstra o uso desses métodos de classe -
import unittest
class TestFixtures(unittest.TestCase):
@classmethod
def setUpClass(cls):
print 'called once before any tests in class'
@classmethod
def tearDownClass(cls):
print '\ncalled once after all tests in class'
def setUp(self):
self.a = 10
self.b = 20
name = self.shortDescription()
print '\n',name
def tearDown(self):
print '\nend of test',self.shortDescription()
def test1(self):
"""One"""
result = self.a+self.b
self.assertTrue(True)
def test2(self):
"""Two"""
result = self.a-self.b
self.assertTrue(False)
if __name__ == '__main__':
unittest.main()
Classe TestSuite
A estrutura de teste do Python fornece um mecanismo útil pelo qual as instâncias do caso de teste podem ser agrupadas de acordo com os recursos que testam. Este mecanismo é disponibilizado pela classe TestSuite no módulo unittest.
As etapas a seguir estão envolvidas na criação e execução de um conjunto de testes.
Step 1 - Crie uma instância da classe TestSuite.
suite = unittest.TestSuite()
Step 2 - Adicionar testes dentro de uma classe TestCase na suíte.
suite.addTest(testcase class)
Step 3 - Você também pode usar o método makeSuite () para adicionar testes de uma classe
suite = unittest.makeSuite(test case class)
Step 4 - Testes individuais também podem ser adicionados à suíte.
suite.addTest(testcaseclass(""testmethod")
Step 5 - Crie um objeto da classe TestTestRunner.
runner = unittest.TextTestRunner()
Step 6 - Chame o método run () para executar todos os testes no pacote
runner.run (suite)
Os seguintes métodos são definidos na classe TestSuite -
Sr. Não | Método e Descrição |
---|---|
1 | addTest() Adiciona um método de teste no conjunto de testes. |
2 | addTests() Adiciona testes de várias classes TestCase. |
3 | run() Executa os testes associados a este pacote, coletando o resultado no objeto de resultado do teste |
4 | debug() Executa os testes associados a este pacote sem coletar o resultado. |
5 | countTestCases() Retorna o número de testes representados por este objeto de teste |
O exemplo a seguir mostra como usar a classe TestSuite -
import unittest
class suiteTest(unittest.TestCase):
def setUp(self):
self.a = 10
self.b = 20
def testadd(self):
"""Add"""
result = self.a+self.b
self.assertTrue(result == 100)
def testsub(self):
"""sub"""
result = self.a-self.b
self.assertTrue(result == -10)
def suite():
suite = unittest.TestSuite()
## suite.addTest (simpleTest3("testadd"))
## suite.addTest (simpleTest3("testsub"))
suite.addTest(unittest.makeSuite(simpleTest3))
return suite
if __name__ == '__main__':
runner = unittest.TextTestRunner()
test_suite = suite()
runner.run (test_suite)
Você pode experimentar o método addTest () removendo o comentário das linhas e da instrução de comentário com o método makeSuite ().
Classe TestLoader
O pacote unittest possui a classe TestLoader que é usada para criar suítes de teste a partir de classes e módulos. Por padrão, a instância unittest.defaultTestLoader é criada automaticamente quando o método unittest.main (método 0 é chamado. Uma instância explícita, no entanto, permite a personalização de certas propriedades.
No código a seguir, os testes de duas classes são coletados em uma Lista usando o objeto TestLoader.
import unittest
testList = [Test1, Test2]
testLoad = unittest.TestLoader()
TestList = []
for testCase in testList:
testSuite = testLoad.loadTestsFromTestCase(testCase)
TestList.append(testSuite)
newSuite = unittest.TestSuite(TestList)
runner = unittest.TextTestRunner()
runner.run(newSuite)
A tabela a seguir mostra uma lista de métodos na classe TestLoader -
S.No | Método e Descrição |
---|---|
1 | loadTestsFromTestCase() Retorna um conjunto de todos os casos de teste contidos em uma classe TestCase |
2 | loadTestsFromModule() Retorne um conjunto de todos os casos de teste contidos no módulo fornecido. |
3 | loadTestsFromName() Retorna um conjunto de todos os casos de teste dado um especificador de string. |
4 | discover() Encontre todos os módulos de teste recorrendo aos subdiretórios do diretório inicial especificado e retorne um objeto TestSuite |
Classe TestResult
Esta classe é usada para compilar informações sobre os testes que tiveram sucesso e os testes que falharam. Um objeto TestResult armazena os resultados de um conjunto de testes. Uma instância de TestResult é retornada pelo método TestRunner.run ().
As instâncias de TestResult têm os seguintes atributos -
Sr. Não | Atributo e descrição |
---|---|
1 | Errors Uma lista contendo 2 tuplas de instâncias do TestCase e strings contendo tracebacks formatados. Cada tupla representa um teste que gerou uma exceção inesperada. |
2 | Failures Uma lista contendo 2 tuplas de instâncias do TestCase e strings contendo tracebacks formatados. Cada tupla representa um teste em que uma falha foi explicitamente sinalizada usando os métodos TestCase.assert * (). |
3 | Skipped Uma lista contendo 2 tuplas de instâncias do TestCase e strings contendo o motivo para pular o teste. |
4 | wasSuccessful() Retorna True se todos os testes executados até agora foram aprovados, caso contrário retorna False. |
5 | stop() Este método pode ser chamado para sinalizar que o conjunto de testes em execução deve ser abortado. |
6 | startTestRun() Chamado uma vez antes de qualquer teste ser executado. |
7 | stopTestRun() Chamado uma vez depois que todos os testes são executados. |
8 | testsRun O número total de testes executados até agora. |
9 | Buffer Se definido como verdadeiro, sys.stdout e sys.stderr será armazenado em buffer entre startTest () e stopTest () sendo chamado. |
O código a seguir executa um conjunto de testes -
if __name__ == '__main__':
runner = unittest.TextTestRunner()
test_suite = suite()
result = runner.run (test_suite)
print "---- START OF TEST RESULTS"
print result
print "result::errors"
print result.errors
print "result::failures"
print result.failures
print "result::skipped"
print result.skipped
print "result::successful"
print result.wasSuccessful()
print "result::test-run"
print result.testsRun
print "---- END OF TEST RESULTS"
O código quando executado exibe a seguinte saída -
---- START OF TEST RESULTS
<unittest.runner.TextTestResult run = 2 errors = 0 failures = 1>
result::errors
[]
result::failures
[(<__main__.suiteTest testMethod = testadd>, 'Traceback (most recent call last):\n
File "test3.py", line 10, in testadd\n
self.assertTrue(result == 100)\nAssert
ionError: False is not true\n')]
result::skipped
[]
result::successful
False
result::test-run
2
---- END OF TEST RESULTS
O framework de testes Python usa a função assert () embutida do Python, que testa uma condição particular. Se a declaração falhar, um AssertionError será gerado. A estrutura de teste irá então identificar o teste como Falha. Outras exceções são tratadas como Erro.
Os três conjuntos de funções de asserção a seguir são definidos no módulo unittest -
- Assertivos booleanos básicos
- Declarações Comparativas
- Afirmações para coleções
As funções de declaração básicas avaliam se o resultado de uma operação é Verdadeiro ou Falso. Todos os métodos de declaração aceitam ummsg argumento que, se especificado, é usado como mensagem de erro em caso de falha.
Sr. Não | Método e Descrição |
---|---|
1 | assertEqual(arg1, arg2, msg = None) Teste se arg1 e arg2 são iguais. Se os valores não forem iguais, o teste falhará. |
2 | assertNotEqual(arg1, arg2, msg = None) Teste se arg1 e arg2 não são iguais. Se os valores forem iguais, o teste falhará. |
3 | assertTrue(expr, msg = None) Teste se expr é verdadeiro. Se falso, o teste falha |
4 | assertFalse(expr, msg = None) Teste se expr é falso. Se verdadeiro, o teste falha |
5 | assertIs(arg1, arg2, msg = None) Teste se arg1 e arg2 são avaliados para o mesmo objeto. |
6 | assertIsNot(arg1, arg2, msg = None) Teste se arg1 e arg2 não são avaliados para o mesmo objeto. |
7 | assertIsNone(expr, msg = None) Teste se expr é Nenhum. Se não for nenhum, o teste falha |
8 | assertIsNotNone(expr, msg = None) Teste se expr não é Nenhum. Se nenhum, o teste falha |
9 | assertIn(arg1, arg2, msg = None) Teste se arg1 está em arg2 . |
10 | assertNotIn(arg1, arg2, msg = None) Teste se arg1 não está em arg2 . |
11 | assertIsInstance(obj, cls, msg = None) Teste se obj é uma instância de cls |
12 | assertNotIsInstance(obj, cls, msg = None) Teste se obj não é uma instância de cls |
Algumas das funções de asserção acima são implementadas no código a seguir -
import unittest
class SimpleTest(unittest.TestCase):
def test1(self):
self.assertEqual(4 + 5,9)
def test2(self):
self.assertNotEqual(5 * 2,10)
def test3(self):
self.assertTrue(4 + 5 == 9,"The result is False")
def test4(self):
self.assertTrue(4 + 5 == 10,"assertion fails")
def test5(self):
self.assertIn(3,[1,2,3])
def test6(self):
self.assertNotIn(3, range(5))
if __name__ == '__main__':
unittest.main()
Quando o script acima é executado, test2, test4 e test6 mostrarão falha e outros serão executados com sucesso.
FAIL: test2 (__main__.SimpleTest)
----------------------------------------------------------------------
Traceback (most recent call last):
File "C:\Python27\SimpleTest.py", line 9, in test2
self.assertNotEqual(5*2,10)
AssertionError: 10 == 10
FAIL: test4 (__main__.SimpleTest)
----------------------------------------------------------------------
Traceback (most recent call last):
File "C:\Python27\SimpleTest.py", line 13, in test4
self.assertTrue(4+5==10,"assertion fails")
AssertionError: assertion fails
FAIL: test6 (__main__.SimpleTest)
----------------------------------------------------------------------
Traceback (most recent call last):
File "C:\Python27\SimpleTest.py", line 17, in test6
self.assertNotIn(3, range(5))
AssertionError: 3 unexpectedly found in [0, 1, 2, 3, 4]
----------------------------------------------------------------------
Ran 6 tests in 0.001s
FAILED (failures = 3)
O segundo conjunto de funções de asserção são comparative asserts −
assertAlmostEqual (primeiro, segundo, casas = 7, msg = Nenhum, delta = Nenhum)
Teste que primeiro e segundo são aproximadamente (ou não aproximadamente) igual a pelo cálculo da diferença, o arredondamento para um dado número de decimais lugares (padrão 7),
assertNotAlmostEqual (primeiro, segundo, lugares, msg, delta)
Teste se o primeiro e o segundo não são aproximadamente iguais, calculando a diferença, arredondando para o número de casas decimais fornecido (padrão 7) e comparando com zero.
Em ambas as funções acima, se delta for fornecido em vez de lugares, então a diferença entre o primeiro e o segundo deve ser menor ou igual a (ou maior que) delta.
Fornecer delta e locais gera um TypeError.
assertGreater (primeiro, segundo, msg = Nenhum)
Teste se o primeiro é maior que o segundo, dependendo do nome do método. Caso contrário, o teste falhará.
assertGreaterEqual (primeiro, segundo, msg = Nenhum)
Teste se o primeiro é maior ou igual ao segundo, dependendo do nome do método. Caso contrário, o teste irá falhar
assertLess (primeiro, segundo, msg = Nenhum)
Teste se o primeiro é menor que o segundo, dependendo do nome do método. Caso contrário, o teste irá falhar
assertLessEqual (primeiro, segundo, msg = Nenhum)
Teste se o primeiro é menor ou igual ao segundo, dependendo do nome do método. Caso contrário, o teste falhará.
assertRegexpMatches (texto, regexp, msg = Nenhum)
Teste se uma pesquisa regexp corresponde ao texto. Em caso de falha, a mensagem de erro incluirá o padrão e o texto. regexp pode ser um objeto de expressão regular ou uma string contendo uma expressão regular adequada para uso porre.search().
assertNotRegexpMatches (texto, regexp, msg = Nenhum)
Verifica se uma pesquisa regexp não corresponde ao texto . Falha com uma mensagem de erro incluindo o padrão e a parte do texto correspondente. regexp pode ser um objeto de expressão regular ou uma string contendo uma expressão regular adequada para uso porre.search().
As funções de asserção são implementadas no exemplo a seguir -
import unittest
import math
import re
class SimpleTest(unittest.TestCase):
def test1(self):
self.assertAlmostEqual(22.0/7,3.14)
def test2(self):
self.assertNotAlmostEqual(10.0/3,3)
def test3(self):
self.assertGreater(math.pi,3)
def test4(self):
self.assertNotRegexpMatches("Tutorials Point (I) Private Limited","Point")
if __name__ == '__main__':
unittest.main()
O script acima relata test1 e test4 como falha. No teste 1, a divisão de 22/7 não está dentro de 7 casas decimais de 3,14. Da mesma forma, como o segundo argumento corresponde ao texto no primeiro argumento, test4 resulta em AssertionError.
=====================================================FAIL: test1 (__main__.SimpleTest)
----------------------------------------------------------------------
Traceback (most recent call last):
File "asserttest.py", line 7, in test1
self.assertAlmostEqual(22.0/7,3.14)
AssertionError: 3.142857142857143 != 3.14 within 7 places
================================================================
FAIL: test4 (__main__.SimpleTest)
----------------------------------------------------------------------
Traceback (most recent call last):
File "asserttest.py", line 13, in test4
self.assertNotRegexpMatches("Tutorials Point (I) Private Limited","Point")
AssertionError: Regexp matched: 'Point' matches 'Point' in 'Tutorials Point (I)
Private Limited'
----------------------------------------------------------------------
Ran 4 tests in 0.001s
FAILED (failures = 2)
Afirmar para coleções
Esse conjunto de funções de declaração deve ser usado com tipos de dados de coleção em Python, como Lista, Tupla, Dicionário e Conjunto.
Sr. Não | Método e Descrição |
---|---|
1 | assertListEqual (list1, list2, msg = None) Testa se duas listas são iguais. Caso contrário, é construída uma mensagem de erro que mostra apenas as diferenças entre os dois. |
2 | assertTupleEqual (tuple1, tuple2, msg = None) Testa se duas tuplas são iguais. Caso contrário, é construída uma mensagem de erro que mostra apenas as diferenças entre os dois. |
3 | assertSetEqual (set1, set2, msg = None) Testa se dois conjuntos são iguais. Caso contrário, uma mensagem de erro é construída listando as diferenças entre os conjuntos. |
4 | assertDictEqual (expected, actual, msg = None) Teste se dois dicionários são iguais. Caso contrário, é construída uma mensagem de erro que mostra as diferenças nos dicionários. |
O exemplo a seguir implementa os métodos acima -
import unittest
class SimpleTest(unittest.TestCase):
def test1(self):
self.assertListEqual([2,3,4], [1,2,3,4,5])
def test2(self):
self.assertTupleEqual((1*2,2*2,3*2), (2,4,6))
def test3(self):
self.assertDictEqual({1:11,2:22},{3:33,2:22,1:11})
if __name__ == '__main__':
unittest.main()
No exemplo acima, test1 e test3 mostram AssertionError. A mensagem de erro exibe as diferenças nos objetos Lista e Dicionário.
FAIL: test1 (__main__.SimpleTest)
----------------------------------------------------------------------
Traceback (most recent call last):
File "asserttest.py", line 5, in test1
self.assertListEqual([2,3,4], [1,2,3,4,5])
AssertionError: Lists differ: [2, 3, 4] != [1, 2, 3, 4, 5]
First differing element 0:
2
1
Second list contains 2 additional elements.
First extra element 3:
4
- [2, 3, 4]
+ [1, 2, 3, 4, 5]
? +++ +++
FAIL: test3 (__main__.SimpleTest)
----------------------------------------------------------------------
Traceback (most recent call last):
File "asserttest.py", line 9, in test3
self.assertDictEqual({1:11,2:22},{3:33,2:22,1:11})
AssertionError: {1: 11, 2: 22} != {1: 11, 2: 22, 3: 33}
- {1: 11, 2: 22}
+ {1: 11, 2: 22, 3: 33}
? +++++++
----------------------------------------------------------------------
Ran 3 tests in 0.001s
FAILED (failures = 2)
A classe TestLoader tem uma função discover (). A estrutura de teste Python usa isso para descoberta de teste simples. Para serem compatíveis, os módulos e pacotes contendo testes devem ser importáveis do diretório de nível superior.
A seguir está o uso básico da linha de comando da descoberta de teste -
Python –m unittest discover
O intérprete tenta carregar todos os módulos contendo teste do diretório atual e diretórios internos recursivamente. Outras opções de linha de comando são -
Sr. Não | Opções e descrição |
---|---|
1 | -v, --verbose Saída detalhada |
2 | -s, --start-directory diretório Diretório para iniciar a descoberta (. padrão) |
3 | -p, --pattern padrão Padrão para combinar arquivos de teste (teste * .py padrão) |
4 | -t, --top-level-directory diretório Diretório de nível superior do projeto (o padrão é o diretório inicial) |
Por exemplo, para descobrir os testes em módulos cujos nomes começam com 'assert' no diretório 'testes', a seguinte linha de comando é usada -
C:\python27>python –m unittest –v –s "c:\test" –p "assert*.py"
A descoberta de teste carrega os testes importando-os. Depois que a descoberta de teste encontrar todos os arquivos de teste do diretório inicial que você especificar, ela transforma os caminhos em nomes de pacotes a serem importados.
Se você fornecer o diretório inicial como um nome de pacote em vez de um caminho para um diretório, o discovery assume que o local de onde ele importa é o local pretendido, portanto, você não receberá o aviso.
O suporte para pular testes foi adicionado desde Python 2.7. É possível pular o método de teste individual ou classe TestCase, condicionalmente ou incondicionalmente. A estrutura permite que um determinado teste seja marcado como uma 'falha esperada'. Este teste 'falhará', mas não será contado como falha no TestResult.
Para pular um método incondicionalmente, o seguinte método de classe unittest.skip () pode ser usado -
import unittest
def add(x,y):
return x+y
class SimpleTest(unittest.TestCase):
@unittest.skip("demonstrating skipping")
def testadd1(self):
self.assertEquals(add(4,5),9)
if __name__ == '__main__':
unittest.main()
Como skip () é um método de classe, ele é prefixado por @ token. O método tem um argumento: uma mensagem de log que descreve o motivo do salto.
Quando o script acima é executado, o seguinte resultado é exibido no console -
C:\Python27>python skiptest.py
s
----------------------------------------------------------------------
Ran 1 test in 0.000s
OK (skipped = 1)
O caractere 's' indica que um teste foi ignorado.
A sintaxe alternativa para pular o teste é usar o método de instância skipTest () dentro da função de teste.
def testadd2(self):
self.skipTest("another method for skipping")
self.assertTrue(add(4 + 5) == 10)
Os decoradores a seguir implementam o salto de teste e as falhas esperadas -
Sr. Não | Método e Descrição |
---|---|
1 | unittest.skip(reason) Ignore incondicionalmente o teste decorado. motivo deve descrever por que o teste está sendo ignorado. |
2 | unittest.skipIf(condition, reason) Pule o teste decorado se a condição for verdadeira. |
3 | unittest.skipUnless(condition, reason) Pule o teste decorado, a menos que a condição seja verdadeira. |
4 | unittest.expectedFailure() Marque o teste como uma falha esperada. Se o teste falhar ao ser executado, ele não será contado como uma falha. |
O exemplo a seguir demonstra o uso de salto condicional e falha esperada.
import unittest
class suiteTest(unittest.TestCase):
a = 50
b = 40
def testadd(self):
"""Add"""
result = self.a+self.b
self.assertEqual(result,100)
@unittest.skipIf(a>b, "Skip over this routine")
def testsub(self):
"""sub"""
result = self.a-self.b
self.assertTrue(result == -10)
@unittest.skipUnless(b == 0, "Skip over this routine")
def testdiv(self):
"""div"""
result = self.a/self.b
self.assertTrue(result == 1)
@unittest.expectedFailure
def testmul(self):
"""mul"""
result = self.a*self.b
self.assertEqual(result == 0)
if __name__ == '__main__':
unittest.main()
No exemplo acima, testsub () e testdiv () serão ignorados. No primeiro caso, a> b é verdadeiro, enquanto no segundo caso b == 0 não é verdadeiro. Por outro lado, testmul () foi marcado como falha esperada.
Quando o script acima é executado, dois testes ignorados mostram 's' e a falha esperada é exibida como 'x'.
C:\Python27>python skiptest.py
Fsxs
================================================================
FAIL: testadd (__main__.suiteTest)
Add
----------------------------------------------------------------------
Traceback (most recent call last):
File "skiptest.py", line 9, in testadd
self.assertEqual(result,100)
AssertionError: 90 != 100
----------------------------------------------------------------------
Ran 4 tests in 0.000s
FAILED (failures = 1, skipped = 2, expected failures = 1)
A estrutura de teste Python fornece os seguintes métodos de asserção para verificar se as exceções são levantadas.
assertRaises (exceção, chamável, * args, ** kwds)
Teste se uma exceção (primeiro argumento) é gerada quando uma função é chamada com quaisquer argumentos posicionais ou de palavra-chave. O teste passa se a exceção esperada é levantada, é um erro se outra exceção é levantada ou falha se nenhuma exceção é levantada. Para capturar qualquer um de um grupo de exceções, uma tupla contendo as classes de exceção pode ser passada como exceção.
No exemplo abaixo, uma função de teste é definida para verificar se ZeroDivisionError é gerado.
import unittest
def div(a,b):
return a/b
class raiseTest(unittest.TestCase):
def testraise(self):
self.assertRaises(ZeroDivisionError, div, 1,0)
if __name__ == '__main__':
unittest.main()
A função testraise () usa a função assertRaises () para ver se a divisão por zero ocorre quando a função div () é chamada. O código acima irá gerar uma exceção. Mas altera os argumentos para a função div () da seguinte maneira -
self.assertRaises(ZeroDivisionError, div, 1,1)
Quando um código é executado com essas alterações, o teste falha, pois ZeroDivisionError não ocorre.
F
================================================================
FAIL: testraise (__main__.raiseTest)
----------------------------------------------------------------------
Traceback (most recent call last):
File "raisetest.py", line 7, in testraise
self.assertRaises(ZeroDivisionError, div, 1,1)
AssertionError: ZeroDivisionError not raised
----------------------------------------------------------------------
Ran 1 test in 0.000s
FAILED (failures = 1)
assertRaisesRegexp (exceção, regexp, chamável, * args, ** kwds)
Testa se regexp corresponde à representação de string da exceção gerada. regexp pode ser um objeto de expressão regular ou uma string contendo uma expressão regular adequada para uso por re.search ().
O exemplo a seguir mostra como assertRaisesRegexp () é usado -
import unittest
import re
class raiseTest(unittest.TestCase):
def testraiseRegex(self):
self.assertRaisesRegexp(TypeError, "invalid", reg,"Point","TutorialsPoint")
if __name__ == '__main__':
unittest.main()
Aqui, o teste testraseRegex () não falha como primeiro argumento. "Point" é encontrado na segunda string de argumento.
================================================================
FAIL: testraiseRegex (__main__.raiseTest)
----------------------------------------------------------------------
Traceback (most recent call last):
File "C:/Python27/raiseTest.py", line 11, in testraiseRegex
self.assertRaisesRegexp(TypeError, "invalid", reg,"Point","TutorialsPoint")
AssertionError: TypeError not raised
----------------------------------------------------------------------
No entanto, a mudança é mostrada abaixo -
self.assertRaisesRegexp(TypeError, "invalid", reg,123,"TutorialsPoint")
Uma exceção TypeError será lançada. Portanto, o seguinte resultado será exibido -
================================================================
FAIL: testraiseRegex (__main__.raiseTest)
----------------------------------------------------------------------
Traceback (most recent call last):
File "raisetest.py", line 11, in testraiseRegex
self.assertRaisesRegexp(TypeError, "invalid", reg,123,"TutorialsPoint")
AssertionError: "invalid" does not match
"first argument must be string or compiled pattern"
----------------------------------------------------------------------
Junit, a estrutura de teste de unidade Java (Pyunit é uma implementação de JUnit) tem uma opção útil de tempo limite. Se um teste demorar mais do que o tempo especificado, ele será marcado como reprovado.
A estrutura de teste do Python não contém nenhum suporte para tempo limite. No entanto, um módulo de terceira parte chamado decorador de tempo limite pode fazer o trabalho.
Baixe e instale o módulo de -
https://pypi.python.org/packages/source/t/timeout-decorator/timeout-decorator-0.3.2.tar.gz
- Importar timeout_decorator no código
- Coloque o decorador de tempo limite antes do teste
- @timeout_decorator.timeout(10)
Se um método de teste abaixo desta linha demorar mais do que o tempo limite mencionado (10 minutos) aqui, um TimeOutError será gerado. Por exemplo -
import time
import timeout_decorator
class timeoutTest(unittest.TestCase):
@timeout_decorator.timeout(5)
def testtimeout(self):
print "Start"
for i in range(1,10):
time.sleep(1)
print "%d seconds have passed" % i
if __name__ == '__main__':
unittest.main()
unittest2 é um backport de recursos adicionais adicionados à estrutura de teste Python no Python 2.7 e posteriores. Ele foi testado para funcionar em Python 2.6, 2.7 e 3. *. A versão mais recente pode ser baixada dehttps://pypi.python.org/pypi/unittest2
Para usar unittest2 em vez de unittest, basta substituir import unittest por import unittest2.
As classes em unittest2 derivam das classes apropriadas em unittest, portanto, deve ser possível usar a infraestrutura de execução de teste unittest2 sem ter que alternar todos os seus testes para usar unittest2 imediatamente. Caso você pretenda implementar novos recursos, subclasse seu caso de teste deunittest2.TestCase em vez de unittest.TestCase
A seguir estão os novos recursos do unittest2 -
addCleanups para melhor gestão de recursos
Contém muitos novos métodos de declaração
assertRaises como gerenciador de contexto, com acesso à exceção posteriormente
Possui acessórios de nível de módulo, como setUpModule e tearDownModule
Inclui load_tests protocolo para carregar testes de módulos ou pacotes
startTestRun e stopTestRun métodos em TestResult
No Python 2.7, você invoca os recursos de linha de comando de teste de unidade (incluindo a descoberta de teste) com python -m unittest <args>.
Em vez disso, unittest2 vem com um script unit2.
unit2 discover
unit2 -v test_module
O manuseio mais eficiente de control-C durante uma execução de teste é fornecido pela opção de linha de comando -c / - catch para unittest, junto com o catchbreakparâmetro. Com o comportamento catch break habilitado, o control-C permitirá que o teste atualmente em execução seja concluído e a execução do teste será encerrada e relatará todos os resultados até o momento. Um segundo control-c disparará um KeyboardInterrupt da maneira usual.
Se o manipulador unittest for chamado, mas o manipulador signal.SIGINT não estiver instalado, ele chamará o manipulador padrão. Normalmente, esse será o comportamento esperado pelo código que substitui um manipulador instalado e o delega. Para testes individuais que precisam de manipulação de unittest control-c desabilitada, o decorador removeHandler () pode ser usado.
As funções de utilitário a seguir permitem a funcionalidade de manipulação de controle-c em estruturas de teste -
unittest.installHandler ()
Instale o manipulador control-c. Quando umsignal.SIGINT é recebido todos os resultados registrados têm TestResult.stop () chamado.
unittest.registerResult (resultado)
Registre um TestResultobjeto para manipulação de controle-c. Registrar um resultado armazena uma referência fraca a ele, portanto, não evita que o resultado seja coletado como lixo.
unittest.removeResult (resultado)
Remova um resultado registrado. Depois que um resultado for removido, TestResult.stop () não será mais chamado nesse objeto de resultado em resposta a um control-c.
unittest.removeHandler (function = None)
Quando chamada sem argumentos, esta função remove o manipulador control-c se ele tiver sido instalado. Esta função também pode ser usada como um decorador de teste para remover temporariamente o manipulador enquanto o teste está sendo executado.
GUI Test Runner
O módulo unittest é instalado para descobrir e executar testes interativamente. Este utilitário, um script Python 'inittestgui.py' usa o módulo Tkinter, que é uma porta Python para o kit de ferramentas gráficas TK. Ele fornece uma GUI fácil de usar para descoberta e execução de testes.
Python unittestgui.py
Clique no botão 'Descobrir testes'. Uma pequena caixa de diálogo aparece, onde você pode selecionar o diretório e os módulos a partir dos quais o teste deve ser executado.
Finalmente, clique no botão Iniciar. Os testes serão descobertos a partir do caminho selecionado e dos nomes dos módulos, e o painel de resultados exibirá os resultados.
Para ver os detalhes do teste individual, selecione e clique em teste na caixa de resultados -
Se você não encontrar esse utilitário na instalação do Python, pode obtê-lo na página do projeto http://pyunit.sourceforge.net/.
Similar, utilitário baseado no kit de ferramentas wxpython também está disponível lá.
A distribuição padrão do Python contém o módulo 'Doctest'. A funcionalidade deste módulo torna possível procurar por pedaços de texto que se parecem com sessões Python interativas e executa essas sessões para ver se elas funcionam exatamente como mostrado.
O Doctest pode ser muito útil nos seguintes cenários -
Para verificar se as docstrings de um módulo estão atualizadas, verificando se todos os exemplos interativos ainda funcionam conforme documentado.
Para realizar o teste de regressão, verificando se os exemplos interativos de um arquivo de teste ou um objeto de teste funcionam conforme o esperado.
Para escrever documentação de tutorial para um pacote, amplamente ilustrado com exemplos de entrada-saída
Em Python, uma 'docstring' é uma string literal que aparece como a primeira expressão em uma classe, função ou módulo. Ele é ignorado quando o pacote é executado, mas é reconhecido pelo compilador e colocado no__doc__atributo da classe, função ou módulo envolvente. Por estar disponível via introspecção, é o local canônico para a documentação do objeto.
É uma prática comum colocar o uso de exemplo de diferentes partes do código Python dentro da docstring. O módulo doctest permite verificar se essas docstrings estão atualizadas com as revisões intermitentes do código.
No código a seguir, uma função fatorial é definida intercalada com o uso de exemplo. Para verificar se o uso do exemplo está correto, chame a função testmod () no módulo doctest.
"""
This is the "example" module.
The example module supplies one function, factorial(). For example,
>>> factorial(5)
120
"""
def factorial(x):
"""Return the factorial of n, an exact integer >= 0.
>>> factorial(-1)
Traceback (most recent call last):
...
ValueError: x must be >= 0
"""
if not x >= 0:
raise ValueError("x must be >= 0")
f = 1
for i in range(1,x+1):
f = f*i
return f
if __name__ == "__main__":
import doctest
doctest.testmod()
Digite e salve o script acima como FactDocTest.py e tente executar este script a partir da linha de comando.
Python FactDocTest.py
Nenhuma saída será mostrada a menos que o exemplo falhe. Agora, altere a linha de comando para o seguinte -
Python FactDocTest.py –v
O console agora mostrará a seguinte saída -
C:\Python27>python FactDocTest.py -v
Trying:
factorial(5)
Expecting:
120
ok
Trying:
factorial(-1)
Expecting:
Traceback (most recent call last):
...
ValueError: x must be >= 0
ok
2 items passed all tests:
1 tests in __main__
1 tests in __main__.factorial
2 tests in 2 items.
2 passed and 0 failed.
Test passed.
Se, por outro lado, o código da função factorial () não der o resultado esperado em docstring, o resultado da falha será exibido. Por exemplo, altere f = 2 no lugar de f = 1 no script acima e execute o doctest novamente. O resultado será o seguinte -
Trying:
factorial(5)
Expecting:
120
**********************************************************************
File "docfacttest.py", line 6, in __main__
Failed example:
factorial(5)
Expected:
120
Got:
240
Trying:
factorial(-1)
Expecting:
Traceback (most recent call last):
...
ValueError: x must be >= 0
ok
1 items passed all tests:
1 tests in __main__.factorial
**********************************************************************
1 items had failures:
1 of 1 in __main__
2 tests in 2 items.
1 passed and 1 failed.
***Test Failed*** 1 failures.
Doctest: Verificando exemplos em um arquivo de texto
Outra aplicação simples do doctest é testar exemplos interativos em um arquivo de texto. Isso pode ser feito com a função testfile ().
O texto a seguir é armazenado em um arquivo de texto denominado 'example.txt'.
Using ''factorial''
-------------------
This is an example text file in reStructuredText format. First import
''factorial'' from the ''example'' module:
>>> from example import factorial
Now use it:
>>> factorial(5)
120
O conteúdo do arquivo é tratado como docstring. Para verificar os exemplos no arquivo de texto, use a função testfile () do módulo doctest.
def factorial(x):
if not x >= 0:
raise ValueError("x must be >= 0")
f = 1
for i in range(1,x+1):
f = f*i
return f
if __name__ == "__main__":
import doctest
doctest.testfile("example.txt")
Como acontece com testmod (), testfile () não exibirá nada, a menos que um exemplo falhe. Se um exemplo falhar, o (s) exemplo (s) com falha e a (s) causa (s) da (s) falha (s) são impressos no console, usando o mesmo formato de testmod ().
Na maioria dos casos, copiar e colar uma sessão de console interativo funciona bem, mas doctest não está tentando fazer uma emulação exata de qualquer shell Python específico.
Qualquer saída esperada deve seguir imediatamente a linha final '>>>' ou '...' que contém o código, e a saída esperada (se houver) se estende até a próxima linha '>>>' ou com todos os espaços em branco.
A saída esperada não pode conter uma linha totalmente em branco, uma vez que tal linha é usada para sinalizar o fim da saída esperada. Se a saída esperada contiver uma linha em branco, coloque <BLANKLINE> em seu exemplo de doctest, cada lugar em que uma linha em branco é esperada.
A API doctest gira em torno das duas classes de contêiner a seguir, usadas para armazenar exemplos interativos de docstrings -
Example - Uma única instrução Python, emparelhada com sua saída esperada.
DocTest - Uma coleção de exemplos, normalmente extraídos de uma única docstring ou de um arquivo de texto.
As seguintes classes de processamento adicionais são definidas para localizar, analisar, executar e verificar exemplos de doctest -
DocTestFinder - Encontra todas as docstrings em um determinado módulo e usa um DocTestParser para criar um DocTest de cada docstring que contém exemplos interativos.
DocTestParser - Cria um objeto doctest a partir de uma string (como a docstring de um objeto).
DocTestRunner - Executa os exemplos em um doctest e usa um OutputChecker para verificar sua saída.
OutputChecker - Compara a saída real de um exemplo doctest com a saída esperada e decide se eles correspondem.
Classe DocTestFinder
É uma classe de processamento usada para extrair os doctests que são relevantes para um determinado objeto, de sua docstring e das docstrings de seus objetos contidos. Atualmente, os doctests podem ser extraídos dos seguintes tipos de objeto - módulos, funções, classes, métodos, métodos estáticos, métodos de classe e propriedades.
Esta classe define o método find (). Ele retorna uma lista de DocTests que são definidos pela docstring do objeto ou por qualquer uma das docstrings de seus objetos contidos.
Classe DocTestParser
É uma classe de processamento usada para extrair exemplos interativos de uma string e usá-los para criar um objeto DocTest. Esta classe define os seguintes métodos -
get_doctest() - Extraia todos os exemplos de doctest da string fornecida e colete-os em um DocTest objeto.
get_examples(string[, name]) - Extraia todos os exemplos de doctest da string fornecida e retorne-os como uma lista de Exampleobjetos. Os números das linhas são baseados em 0. O nome do argumento opcional é um nome que identifica esta string e é usado apenas para mensagens de erro.
parse(string[, name]) - Divida a string fornecida em exemplos e texto intermediário e retorne-os como uma lista de Examplese cordas. Números de linha para oExamplessão baseados em 0. O nome do argumento opcional é um nome que identifica esta string e é usado apenas para mensagens de erro.
Classe DocTestRunner
Esta é uma classe de processamento usada para executar e verificar os exemplos interativos em um DocTest. Os seguintes métodos são definidos nele -
report_start ()
Relate que o executor de teste está prestes a processar o exemplo fornecido. Este método é fornecido para permitir subclasses deDocTestRunnerpara personalizar sua saída; não deve ser chamado diretamente
report_success ()
Relate que o exemplo fornecido foi executado com sucesso. Este método é fornecido para permitir que subclasses de DocTestRunner personalizem sua saída; ele não deve ser chamado diretamente.
report_failure ()
Relate que o exemplo fornecido falhou. Este método é fornecido para permitir subclasses deDocTestRunnerpara personalizar sua saída; ele não deve ser chamado diretamente.
report_unexpected_exception ()
Relate que o exemplo fornecido gerou uma exceção inesperada. Este método é fornecido para permitir que subclasses de DocTestRunner personalizem sua saída; ele não deve ser chamado diretamente.
teste de corrida)
Execute os exemplos em teste (um objeto DocTest) e exiba os resultados usando a função de gravação de saída .
resumir ([verbose])
Imprima um resumo de todos os casos de teste que foram executados por este DocTestRunner e retorne uma tupla nomeada TestResults (falhou, tentou). O argumento detalhado opcional controla o quão detalhado é o resumo. Se a verbosidade não for especificada, a verbosidade do DocTestRunner é usada.
Classe OutputChecker
Esta classe é usada para verificar se a saída real de um exemplo doctest corresponde à saída esperada.
Os seguintes métodos são definidos nesta classe -
check_output ()
Retorna Truese a saída real de um exemplo ( obtido ) corresponder à saída esperada ( desejado ). Essas strings são sempre consideradas correspondentes se forem idênticas; mas dependendo de quais sinalizadores de opção o executor de teste está usando, vários tipos de correspondência não exata também são possíveis. Consulte a seção Sinalizadores de opção e diretivas para obter mais informações sobre sinalizadores de opção.
output_difference ()
Retorne uma string que descreve as diferenças entre a saída esperada para um determinado exemplo ( exemplo ) e a saída real ( obtida ).
Integração DocTest com Unittest
O módulo doctest fornece duas funções que podem ser usadas para criar suites de teste de unidade a partir de módulos e arquivos de texto contendo doctests. Para integrar com a descoberta de teste unittest, inclua uma função load_tests () em seu módulo de teste -
import unittest
import doctest
import doctestexample
def load_tests(loader, tests, ignore):
tests.addTests(doctest.DocTestSuite(doctestexample))
return tests
Um TestSuite combinado de testes de unittest e doctest será formado e agora pode ser executado pelo método main () ou pelo método run () do módulo unittest.
A seguir estão as duas funções principais para criar unittest.TestSuite instâncias de arquivos de texto e módulos com os doctests -
doctest.DocFileSuite ()
É usado para converter testes doctest de um ou mais arquivos de texto para um unittest.TestSuite. O unittest.TestSuite retornado deve ser executado pela estrutura unittest e executa os exemplos interativos em cada arquivo. Se algum dos exemplos em um arquivo falhar, o teste de unidade sintetizado falhará e umfailureException exceção é levantada mostrando o nome do arquivo que contém o teste e um número de linha (às vezes aproximado).
doctest.DocTestSuite ()
É usado para converter testes doctest de um módulo em um unittest.TestSuite.
O unittest.TestSuite retornado deve ser executado pela estrutura unittest e executa cada doctest no módulo. Se algum dos testes de documentos falhar, o teste de unidade sintetizado falhará e umfailureException exceção é levantada mostrando o nome do arquivo que contém o teste e um número de linha (às vezes aproximado)
Nos bastidores, DocTestSuite () cria um unittest.TestSuite fora das instâncias doctest.DocTestCase, e DocTestCase é uma subclasse de unittest.TestCase.
Da mesma forma, DocFileSuite () cria um unittest.TestSuite a partir de instâncias doctest.DocFileCase e DocFileCase é uma subclasse de DocTestCase.
Portanto, as duas maneiras de criar um unittest.TestSuite executam instâncias de DocTestCase. Quando você mesmo executa as funções doctest, pode controlar as opções doctest em uso diretamente, passando sinalizadores de opção para funções doctest.
No entanto, se você está escrevendo uma estrutura de teste de unidade, o teste de unidade controla quando e como os testes são executados. O autor do framework normalmente deseja controlar as opções de relatório do doctest (talvez, por exemplo, especificadas por opções de linha de comando), mas não há como passar as opções de teste de unidade para executores de teste de doctest.
Foi em 2004 que Holger Krekel rebatizou seu stdpacote, cujo nome era frequentemente confundido com o da Biblioteca Padrão que acompanha o Python, com o nome (apenas um pouco menos confuso) 'py'. Embora o pacote contenha vários subpacotes, agora é conhecido quase inteiramente por sua estrutura py.test.
A estrutura py.test configurou um novo padrão para testes Python e se tornou muito popular entre muitos desenvolvedores hoje. As expressões elegantes e Pythônicas introduzidas para a escrita de teste tornaram possível que as suítes de teste fossem escritas em um estilo muito mais compacto.
py.test é uma alternativa não padronizada para o módulo unittest padrão do Python. Apesar de ser uma ferramenta de teste extensível e cheia de recursos, ela se orgulha de uma sintaxe simples. Criar um conjunto de testes é tão fácil quanto escrever um módulo com algumas funções.
py.test é executado em todos os sistemas operacionais POSIX e WINDOWS (XP / 7/8) com Python versões 2.6 e superiores.
Instalação
Use o código a seguir para carregar o módulo pytest na distribuição Python atual, bem como um utilitário py.test.exe. Os testes podem ser executados usando ambos.
pip install pytest
Uso
Você pode simplesmente usar a instrução assert para afirmar as expectativas de teste. a introspecção assert de pytest relatará de forma inteligente os valores intermediários da expressão assert, liberando você da necessidade de aprender os muitos nomes deJUnit legacy methods.
# content of test_sample.py
def func(x):
return x + 1
def test_answer():
assert func(3) == 5
Use a seguinte linha de comando para executar o teste acima. Depois que o teste é executado, o seguinte resultado é exibido no console -
C:\Python27>scripts\py.test -v test_sample.py
============================= test session starts =====================
platform win32 -- Python 2.7.9, pytest-2.9.1, py-1.4.31, pluggy-0.3.1 -- C:\Pyth
on27\python.exe
cachedir: .cache
rootdir: C:\Python27, inifile:
collected 1 items
test_sample.py::test_answer FAILED
================================== FAILURES =====================
_________________________________ test_answer _________________________________
def test_answer():
> assert func(3) == 5
E assert 4 == 5
E + where 4 = func(3)
test_sample.py:7: AssertionError
========================== 1 failed in 0.05 seconds ====================
O teste também pode ser executado a partir da linha de comando incluindo o módulo pytest usando a opção –m.
python -m pytest test_sample.py
Agrupando vários testes em uma classe
Depois que você começa a ter mais do que alguns testes, geralmente faz sentido agrupar os testes de forma lógica, em classes e módulos. Vamos escrever uma classe contendo dois testes -
class TestClass:
def test_one(self):
x = "this"
assert 'h' in x
def test_two(self):
x = "hello"
assert hasattr(x, 'check')
O seguinte resultado do teste será exibido -
C:\Python27>scripts\py.test -v test_class.py
============================= test session starts =====================
platform win32 -- Python 2.7.9, pytest-2.9.1, py-1.4.31, pluggy-0.3.1 -- C:\Pyt
on27\python.exe
cachedir: .cache
rootdir: C:\Python27, inifile:
collected 2 items
test_class.py::TestClass::test_one PASSED
test_class.py::TestClass::test_two FAILED
================================== FAILURES =====================
_____________________________ TestClass.test_two ______________________________
self = <test_class.TestClass instance at 0x01309DA0>
def test_two(self):
x = "hello"
> assert hasattr(x, 'check')
E assert hasattr('hello', 'check')
test_class.py:7: AssertionError
===================== 1 failed, 1 passed in 0.06 seconds ======================
O projeto do nariz foi lançado em 2005, um ano após py.testrecebeu sua aparência moderna. Ele foi escrito por Jason Pellerin para suportar os mesmos idiomas de teste que foram desenvolvidos pelo py.test, mas em um pacote mais fácil de instalar e manter.
o nose módulo pode ser instalado com a ajuda do utilitário pip
pip install nose
Isso instalará o módulo nariz na distribuição Python atual, bem como um nosetest.exe, o que significa que o teste pode ser executado usando este utilitário, bem como usando o switch –m.
C:\python>nosetests –v test_sample.py
Or
C:\python>python –m nose test_sample.py
nose coleta testes de unittest.TestCasesubclasses, é claro. Também podemos escrever funções de teste simples, bem como classes de teste que não são subclasses de unittest.TestCase. O nariz também fornece uma série de funções úteis para escrever testes cronometrados, testar exceções e outros casos de uso comuns.
nosecoleta testes automaticamente. Não há necessidade de coletar manualmente os casos de teste em suítes de teste. A execução de testes é responsiva, uma vez quenose começa a executar testes assim que o primeiro módulo de teste é carregado.
Tal como acontece com o módulo unittest, nose suporta fixtures no nível de pacote, módulo, classe e caso de teste, portanto, a inicialização cara pode ser feita com a menor freqüência possível.
Uso Básico
Vamos considerar o nosetest.py semelhante ao script usado anteriormente -
# content of nosetest.py
def func(x):
return x + 1
def test_answer():
assert func(3) == 5
Para executar o teste acima, use a seguinte sintaxe de linha de comando -
C:\python>nosetests –v nosetest.py
A saída exibida no console será a seguinte -
nosetest.test_answer ... FAIL
================================================================
FAIL: nosetest.test_answer
----------------------------------------------------------------------
Traceback (most recent call last):
File "C:\Python34\lib\site-packages\nose\case.py", line 198, in runTest
self.test(*self.arg)
File "C:\Python34\nosetest.py", line 6, in test_answer
assert func(3) == 5
AssertionError
----------------------------------------------------------------------
Ran 1 test in 0.000s
FAILED (failures = 1)
nose pode ser integrado com DocTest usando with-doctest opção em uma linha de comando anterior.
\nosetests --with-doctest -v nosetest.py
Você pode usar nose em um script de teste -
import nose
nose.main()
Se você não deseja que o script de teste saia com 0 em caso de sucesso e 1 em caso de falha (como unittest.main), use nose.run () ao invés -
import nose
result = nose.run()
O resultado será verdadeiro se a execução do teste for bem-sucedida ou falso se falhar ou gerar uma exceção não detectada.
nosesuporta fixtures (métodos de configuração e desmontagem) no nível de pacote, módulo, classe e teste. Tal como acontece com os acessórios py.test ou unittest, a configuração sempre é executada antes de qualquer teste (ou coleção de testes para pacotes e módulos de teste); A desmontagem é executada se a configuração for concluída com êxito, independentemente do status da execução do teste.
O módulo nose.tools fornece uma série de ajudas de teste que podem ser úteis, incluindo decoradores para restringir o tempo de execução de teste e testar exceções, e todos os mesmos métodos assertX encontrados em unittest.TestCase.
nose.tools.ok_(expr, msg = None) - Abreviação de assert.
nose.tools.eq_(a, b, msg = None) - Abreviação de 'assert a == b, “% r! =% R”% (a, b)
nose.tools.make_decorator(func) - Envolve um decorador de teste para replicar corretamente os metadados da função decorada, incluindo o material adicional do nariz (ou seja, configuração e desmontagem).
nose.tools.raises(*exceptions) - O teste deve gerar uma das exceções esperadas para passar.
nose.tools.timed(limit) - O teste deve terminar dentro do limite de tempo especificado para passar
nose.tools.istest(func) - Decorador para marcar uma função ou método como um teste
nose.tools.nottest(func) - Decorador para marcar uma função ou método como não um teste
Teste Parametrizado
A estrutura de teste do Python, unittest, não tem uma maneira simples de executar casos de teste parametrizados. Em outras palavras, você não pode facilmente passar argumentos para umunittest.TestCase de fora.
No entanto, as portas do módulo pytest testam a parametrização de várias maneiras bem integradas -
pytest.fixture() permite definir a parametrização no nível das funções do aparelho.
@pytest.mark.parametrizepermite definir a parametrização ao nível da função ou classe. Ele fornece vários conjuntos de argumentos / acessórios para uma função ou classe de teste específica.
pytest_generate_tests permite implementar seu próprio esquema ou extensões de parametrização dinâmica customizada.
Um módulo de terceiros 'parametrizado pelo nariz' permite o teste Parametrizado com qualquer estrutura de teste Python. Ele pode ser baixado deste link -https://github.com/wolever/nose-parameterized