Simulação de teste unitário de Python

Resumo : neste tutorial, você aprenderá sobre a classe Mock mais unittest do Python e como usá-la para simular outras classes.

Introdução à classe Mock mais unittest do Python

As simulações simulam o comportamento de objetos reais. Para testar um objeto que depende de outros objetos de maneira isolada, você usa objetos simulados para simular os objetos reais.

Para simular objetos, você usa o unittest.mockmódulo. O unittest.mockmódulo fornece a Mockclasse que permite simular outros objetos.

Ele também fornece a MagicMockclasse que é uma subclasse da Mockclasse. Além dos métodos e propriedades da Mockclasse, a MagicMockclasse possui as implementações de todos os métodos dunder, por exemplo, __str__ e __repr__ .

Veja o exemplo a seguir:

from unittest.mock import Mock


# create a new mock object
mock = Mock()

# mock the api function
mock.api.return_value = {
    'id': 1,
    'message': 'hello'
}
# call the api function
print(mock.api())Linguagem de código:  Python  ( python )

Saída:

{'id': 1, 'message': 'hello'}Linguagem de código:  Python  ( python )

Como funciona.

Primeiro, importe a Mockclasse do unittest.mockmódulo:

from unittest.mock import MockLinguagem de código:  Python  ( python )

Segundo, crie uma nova instância da Mockclasse:

mock = Mock()Linguagem de código:  Python  ( python )

Terceiro, simule a api()função e atribua seu valor de retorno a um dicionário:

mock.api.return_value = {
    'id': 1,
    'message': 'hello'
}Linguagem de código:  Python  ( python )

Finalmente, chame o api()do objeto simulado. Ele retornará o valor atribuído:

print(mock.api())Linguagem de código:  Python  ( python )

Neste exemplo, temos dois objetos simulados: mock& mock.api.

Vamos adicionar a print()instrução ao programa para ver como funciona:

from unittest.mock import Mock


# create a new mock object
mock = Mock()
print(mock)

# mock the api function
mock.api.return_value = {
    'id': 1,
    'message': 'hello'
}
print(mock.api)

# call the api
print(mock.api())Linguagem de código:  Python  ( python )

Saída:

<Mock id='1830094470496'>
<Mock name='mock.api' id='1830100086416'>
{'id': 1, 'message': 'hello'}Linguagem de código:  Python  ( python )

A saída mostra dois Mockobjetos.

Resumindo, se você atribuir uma propriedade que não existe no Mockobjeto, o Python retornará um novo objeto simulado. Por causa dessa dinâmica, você pode usar a Mockclasse para simular qualquer objeto que desejar.

Quando usar simulação

Estes são os casos que você pode considerar usar mocks:

  • Chamadas do sistema
  • Rede
  • Operação de E/S
  • Relógios e hora, fusos horários
  • Ou outros casos cujos resultados são imprevisíveis

Por que usar simulações

A seguir estão os benefícios das simulações:

  • Acelere o teste
  • Excluir redundâncias externas
  • Torne previsíveis resultados imprevisíveis

Exemplo de simulação do Unittest Python

Suponha que você tenha um módulo chamado odometer.py:

from random import randint


def speed():
    return randint(40, 120)


def alert():
    s = speed()
    if s < 60 or s > 100:
        return True
    return FalseLinguagem de código:  Python  ( python )

No módulo sensor.py:

  • O speed()retorna a velocidade atual de um veículo. Ela retorna um valor aleatório entre 40 e 120. No mundo real, a função leria os dados do hodômetro.
  • A alert()função retorna verdadeiro se a velocidade atual for inferior a 60 km/e superior a 120 km/h. A alert()função usa a speed()função para obter a velocidade atual.

Será difícil testar a alert()função porque o valor retornado pela speed()função varia. Para resolver isso, você pode usar Mockclass.

O seguinte cria um test_odometer.pymódulo de teste que testa a alert()função:

test_alert_normal (test_odometer.TestOdometer) ... ok

----------------------------------------------------------------------
Ran 1 test in 0.000s

OKLinguagem de código:  Python  ( python )

Como funciona.

Primeiro, atribua um objeto Mock à odometer.speedfunção:

odometer.speed = Mock()Linguagem de código:  Python  ( python )

Segundo, defina o valor de retorno da speed()função como 70:

odometer.speed.return_value = 70Linguagem de código:  Python  ( python )

Terceiro, chame a alert()função e teste se ela retorna False. A alert()função chamará o objeto simulado em vez da speed()função real.

A imagem a seguir ilustra como o teste funciona com objetos simulados:

Execute o teste:

python -m unittest test_odometer.py -vLinguagem de código:  Python  ( python )

Saída:

test_alert_normal (test_odometer.TestOdometer) ... ok

----------------------------------------------------------------------
Ran 1 test in 0.000s

OKLinguagem de código:  Python  ( python )

O seguinte adiciona os casos de teste que estão acima e abaixo da velocidade:

import unittest
from unittest.mock import Mock
import odometer


class TestOdometer(unittest.TestCase):
    def test_alert_normal(self):
        odometer.speed = Mock()
        odometer.speed.return_value = 70
        self.assertFalse(odometer.alert())

    def test_alert_overspeed(self):
        odometer.speed = Mock()
        odometer.speed.return_value = 100
        self.assertFalse(odometer.alert())

    def test_alert_underspeed(self):
        odometer.speed = Mock()
        odometer.speed.return_value = 59
        self.assertTrue(odometer.alert())Linguagem de código:  Python  ( python )

Execute o teste:

python -m unittest test_odometer.py -vLinguagem de código:  Python  ( python )

Saída:

test_alert_normal (test_odometer.TestOdometer) ... ok
test_alert_overspeed (test_odometer.TestOdometer) ... ok
test_alert_underspeed (test_odometer.TestOdometer) ... ok

----------------------------------------------------------------------
Ran 3 tests in 0.001s

OKLinguagem de código:  Python  ( python )

Resumo

  • Use a Mockclasse da unittest.mockclasse para zombar de outros objetos.

Deixe um comentário

O seu endereço de email não será publicado. Campos obrigatórios marcados com *