Exceção Python Assert

Neema Muganga 10 outubro 2023
  1. Usando o Gerenciador de Contexto para Apanhar a Exceção Python assert
  2. Utilizando Argumentos de Palavras-Chave para Apanhar a Exceção Python Assert
Exceção Python Assert

Este artigo traz uma compreensão de assert como uma unidade de teste, para testar se as funções podem lançar exceções (erros detectados durante a execução do código) sem necessariamente sair da execução. Em outras palavras, a exceção lançada é encapsulada.

Este teste será aprovado se uma exceção for levantada. Um erro é lançado se uma exceção diferente da esperada for lançada. Em uma instância em que não haja nenhuma exceção levantada, o teste falha.

Usando o Gerenciador de Contexto para Apanhar a Exceção Python assert

Semelhante ao modo como permite a alocação e liberação de recursos quando necessariamente exigidos no conceito geral do Python, o contexto aqui obtém o objeto de exceção real que está sendo lançado durante o teste.

Ele armazena esse atributo de exceção no objeto se houver necessidade de uma verificação de desempenho adicional na exceção gerada.

Para testar se uma função falha ou passa se uma exceção é lançada ou não, vamos empregar TestCase.assertRaises do módulo unittest.

Vamos ver um exemplo prático usando o gerenciador de contexto.

import unittest


class TestCase(unittest.TestCase):
    def test_nameerror(self):
        with self.assertRaises(Exception):
            100 * (someNumber / 5)


if __name__ == "__main__":
    unittest.main()

Resultado:

.
----------------------------------------------------------------------
Ran 1 test in 0.002s

OK

No código de exemplo, o teste é aprovado porque esperamos que uma exceção seja lançada. Estamos dividindo 5 por uma variável indefinida someNumber. Portanto, a função lança uma exceção NameError. Portanto, nosso teste passa conforme exibido pelo . na primeira linha da saída.

Vamos ver um exemplo em que o teste falha quando uma exceção não é lançada.

import unittest


class TestCase(unittest.TestCase):
    def test_nameerror(self):
        with self.assertRaises(Exception):
            someNumber = 10
            100 * (someNumber / 5)


if __name__ == "__main__":
    unittest.main()

Resultado:

F
======================================================================
FAIL: test_nameerror (__main__.MyTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):  File "c:\Users\Neema\Desktop\Article Requirement Spec and Example 
Articles\Article Requirement Spec 
and Example Articles\fah.py", line 106, in test_nameerror
    100 * (someNumber/5)
AssertionError: Exception not raised

----------------------------------------------------------------------
Ran 1 test in 0.002s

FAILED (failures=1)

Neste código de exemplo, definimos um valor para someNumber e então executamos a expressão aritmética com ele.

A saída nos mostra que o teste falha conforme o esperado. Não esperamos que nenhuma exceção NameError seja lançada desta vez, uma vez que existe um valor definido para someNumber.

Também podemos implementar o gerenciador de contexto usando exceções definidas pelo usuário, como no exemplo a seguir.

import unittest


def user_function():
    raise Exception("A user-defined exception")


class MyTestCase(unittest.TestCase):
    def test_userexception(self):
        with self.assertRaises(Exception) as context:
            user_function()

        self.assertTrue("A user-defined exception" in str(context.exception))


if __name__ == "__main__":
    unittest.main()

Resultado:

.
----------------------------------------------------------------------
Ran 1 test in 0.006s

OK

Lembre-se de usar str para incluir o context.exception para evitar a obtenção de um TypeError.

Apresentamos assertTrue, uma biblioteca unittest que compara um valor de teste com true em testes de unidade.

Você também pode optar por usar assertIn em vez de assertTrue.

Exemplo:

import unittest


def user_function():
    raise Exception("A use defined exception")


class MyTestCase(unittest.TestCase):
    def test_userexception(self):
        with self.assertRaises(Exception) as context:
            user_function()

        self.assertIn("A use defined exception", str(context.exception))


if __name__ == "__main__":
    unittest.main()

Vemos a mesma saída em que as aprovações no teste serão produzidas.

Utilizando Argumentos de Palavras-Chave para Apanhar a Exceção Python Assert

Ao contrário do gerenciador de contexto, onde apenas passamos a exceção para assertRaises(), também passamos a chamada de função e os parâmetros da função como argumentos de palavra-chave para evocar a exceção.

Sintaxe

assertRaises(exception, function, *args, **keywords)

Exemplo:

import unittest


class MyTestCase(unittest.TestCase):
    def test_division_by_error(self):
        import operator

        self.assertRaises(ZeroDivisionError, operator.floordiv, 55, 0)


if __name__ == "__main__":
    unittest.main()

Resultado:

.
----------------------------------------------------------------------
Ran 1 test in 0.002s

OK

O código de exemplo acima usou assertRaises() com argumentos de palavra-chave. Passamos a ele a exceção ZeroDivisionError esperada após tentar dividir um número por zero. Importamos a função do operador usada com a função do operador floordiv como o segundo argumento. Os valores dos parâmetros aqui são os terceiros parâmetros; 55 para dividir por 0.

A última aplicação de assert é quando passamos uma exceção diferente da esperada para assertRaises (). Em vez disso, é produzido um erro.

Usando o mesmo código de exemplo que acabamos de usar acima, vamos implementar isso.

import unittest


class MyTestCase(unittest.TestCase):
    def test_division_by_error(self):
        import operator

        self.assertRaises(TypeError, operator.floordiv, 55, 0)


if __name__ == "__main__":
    unittest.main()

Resultado:

E
======================================================================
ERROR: test_division_by_error (__main__.MyTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):  File "c:\Users\Neema\Desktop\Article Requirement Spec and Example 
Articles\user.py", line 16, in test_division_by_error
    self.assertRaises(TypeError, operator.floordiv, 55, 0)
  File "C:\Users\Neema\AppData\Local\Programs\Python\Python39\lib\unittest\case.py", line 733, in assertRaises
    return context.handle('assertRaises', args, kwargs)
  File "C:\Users\Neema\AppData\Local\Programs\Python\Python39\lib\unittest\case.py", line 201, in handle
    callable_obj(*args, **kwargs) 
ZeroDivisionError: integer division or modulo by zero

----------------------------------------------------------------------
Ran 1 test in 0.031s

FAILED (errors=1)

A partir da saída, um rastreamento de erro é produzido. Esperamos uma exceção ZeroDivisionError ao dividir um número por zero. Em vez disso, passamos uma exceção TypeError aplicada ao realizar uma operação aritmética entre diferentes tipos de dados, digamos uma string e um inteiro.

Artigo relacionado - Python Exception