Ir para o conteúdo

Tutorial 9 - Hora dos Testes

A maior parte do desenvolvimento de software não envolve a gravação de um novo código, mas sim a modificação do código existente. Garantir que o código existente continue a funcionar da maneira esperada é uma parte fundamental do processo de desenvolvimento de software. Uma maneira de garantir o comportamento do nosso aplicativo é com um conjunto de testes.

Executar o conjunto de testes

Acontece que nosso projeto já tem um conjunto de testes! Quando geramos nosso projeto originalmente, foram gerados dois diretórios de nível superior: src e tests. A pasta src contém o código do nosso aplicativo; a pasta tests contém nosso conjunto de testes. Dentro da pasta tests há um arquivo chamado test_app.py com o seguinte conteúdo:

def test_first():
    """Um teste inicial para o aplicativo"""
    assert 1 + 1 == 2

Este é um Pytest caso de teste - um bloco de código que pode ser executado para verificar algum comportamento do seu aplicativo. Nesse caso, o teste é um espaço reservado e não testa nada sobre nosso aplicativo, mas é um teste que podemos executar.

Podemos executar esse conjunto de testes usando a opção --test do briefcase dev. Como esta é a primeira vez que estamos executando testes, também precisamos passar a opção -r para garantir que os requisitos de teste também sejam instalados:

(beeware-venv) $ briefcase dev --test -r

[helloworld] Instalando pré-requisitos...
...
Instalando pré-requisitos de desenvolvimento... concluído

[helloworld] Executando conjunto de testes no ambiente de desenvolvimento...
===========================================================================
============================= início da sessão de teste ==============================
plataforma darwin -- Python 3.11.0, pytest-7.2.0, pluggy-1.0.0 -- /Users/brutus/beeware-tutorial/beeware-venv/bin/python3.11
cachedir: /var/folders/b_/khqk71xd45d049kxc_59ltp80000gn/T/.pytest_cache
rootdir: /Users/brutus
plugins: anyio-3.6.2
coletando... coletado 1 item

tests/test_app.py::test_first APROVADO [100%]

============================== 1 aprovado em 0,01s ===============================
(beeware-venv) $ briefcase dev --test -r

[helloworld] Instalando os pré-requisitos...
...
Instalando requisitos de desenvolvimento... concluído

[helloworld] Executando conjunto de testes no ambiente de desenvolvimento...
===========================================================================
============================= início da sessão de testes ==============================
plataforma linux -- Python 3.11.0
pytest==7.2.0
py==1.11.0
pluggy==1.0.0
cachedir: /tmp/.pytest_cache
rootdir: /home/brutus
plugins: anyio-3.6.2
coletando... coletado 1 item

tests/test_app.py::test_first APROVADO [100%]

============================== 1 aprovado em 0,01s ===============================
(beeware-venv) C:\...>briefcase dev --test -r

[helloworld] Instalando pré-requisitos...
...
Instalando pré-requisitos de desenvolvimento... concluído

[helloworld] Executando conjunto de testes no ambiente de desenvolvimento...
===========================================================================
============================= início da sessão de testes ==============================
plataforma win32 -- Python 3.11.0
pytest==7.2.0
py==1.11.0
pluggy==1.0.0
cachedir: C:\Users\brutus\AppData\Local\Temp\.pytest_cache
rootdir: C:\Users\brutus
plugins: anyio-3.6.2
coletando ... 1 item coletado

tests/test_app.py::test_first APROVADO [100%]

============================== 1 aprovado em 0,01 s ===============================

Sucesso! Acabamos de executar um único teste que verifica se a matemática Python funciona da maneira esperada (que alívio!).

Vamos substituir esse teste de espaço reservado por um teste para verificar se o nosso método greeting() se comporta da maneira esperada. Substitua o conteúdo de test_app.py pelo seguinte:

from helloworld.app import greeting


def test_name():
    """Se um nome for fornecido, a saudação inclui o nome"""

 assert greeting("Alice") == "Olá, Alice"


def test_empty():
    """Se nenhum nome for fornecido, uma saudação genérica é exibida"""

 assert greeting("") == "Olá, desconhecido"

Isso define dois novos testes, verificando os dois comportamentos que esperamos ver: a saída quando um nome é fornecido e a saída quando o nome está vazio.

Agora podemos executar novamente o conjunto de testes. Dessa vez, não precisamos fornecer a opção -r, pois os requisitos de teste já foram instalados; precisamos apenas usar a opção --test:

(beeware-venv) $ briefcase dev --test

[helloworld] Executando conjunto de testes no ambiente de desenvolvimento...
===========================================================================
============================= Início da sessão de testes ==============================
...
coletando... 2 itens coletados

tests/test_app.py::test_name APROVADO [ 50%]
tests/test_app.py::test_empty APROVADO [100%]

============================== 2 aprovados em 0,11 s ===============================
(beeware-venv) $ briefcase dev --test

[helloworld] Executando conjunto de testes no ambiente de desenvolvimento...
===========================================================================
============================= Início da sessão de testes ==============================
...
coletando... 2 itens coletados

tests/test_app.py::test_name APROVADO [ 50%]
tests/test_app.py::test_empty APROVADO [100%]

============================== 2 aprovados em 0,11 s ===============================
(beeware-venv) C:\...>briefcase dev --test

[helloworld] Executando conjunto de testes no ambiente de desenvolvimento...
===========================================================================
============================= Início da sessão de testes ==============================
...
coletando... 2 itens coletados

tests/test_app.py::test_name APROVADO [ 50%]
tests/test_app.py::test_empty APROVADO [100%]

============================== 2 aprovados em 0,11 s ===============================

Excelente! Nosso método utilitário greeting() está funcionando como esperado.

Desenvolvimento orientado por testes

Agora que temos um conjunto de testes, podemos usá-lo para impulsionar o desenvolvimento de novos recursos. Vamos modificar nosso aplicativo para ter uma saudação especial para um determinado usuário. Podemos começar adicionando um caso de teste para o novo comportamento que gostaríamos de ver na parte inferior do test_app.py:

def test_brutus():
    """Se o nome for Brutus, é exibida uma saudação especial"""

 assert greeting("Brutus") == "Cuidado com os IDEs do Python!"

Em seguida, execute o conjunto de testes com esse novo teste:

(beeware-venv) $ briefcase dev --test

[helloworld] Executando conjunto de testes no ambiente de desenvolvimento...
===========================================================================
============================= Início da sessão de testes ==============================
...
coletando ... 3 itens coletados

tests/test_app.py::test_name APROVADO [ 33%]
tests/test_app.py::test_empty APROVADO [ 66%]
tests/test_app.py::test_brutus REPROVADO [100%]

=================================== FALHAS ===================================
_________________________________ test_brutus __________________________________

    def test_brutus():
 """Se o nome for Brutus, uma saudação especial é exibida"""

> assert greeting("Brutus") == "Cuidado com os IDEs do Python!"
E AssertionError: assert 'Olá, Brutus' == 'Cuidado com os IDEs do Python!'
E - Cuidado com os IDEs do Python!
E + Hello, Brutus

tests/test_app.py:19: AssertionError
=========================== breve resumo das informações do teste ============================
FALHA tests/test_app.py::test_brutus - AssertionError: assert 'Hello, Brutus...
========================= 1 falha, 2 aprovados em 0,14s ==========================
(beeware-venv) $ briefcase dev --test

[helloworld] Executando conjunto de testes no ambiente de desenvolvimento...
===========================================================================
============================= Início da sessão de testes ==============================
...
coletando... 3 itens coletados

tests/test_app.py::test_name APROVADO [ 33%]
tests/test_app.py::test_empty APROVADO [ 66%]
tests/test_app.py::test_brutus REPROVADO [100%]

=================================== FALHAS ===================================
_________________________________ test_brutus __________________________________

 def test_brutus():
 """Se o nome for Brutus, forneça uma saudação especial"""

> assert greeting("Brutus") == "Cuidado com os IDEs do Python!"
E AssertionError: assert 'Hello, Brutus' == 'Cuidado com os IDEs do Python!'
E - Cuidado com os IDEs do Python!
E + Hello, Brutus

tests/test_app.py:19: AssertionError
=========================== breve resumo do teste ============================
FALHA tests/test_app.py::test_brutus - AssertionError: assert 'Olá, Brutus...
========================= 1 falha, 2 aprovados em 0,14s ==========================

============================== 2 aprovados em 0,11s ===============================
(beeware-venv) C:\...>briefcase dev --test

[helloworld] Executando conjunto de testes no ambiente de desenvolvimento...
===========================================================================
============================= início da sessão de testes ==============================
...
coletando ... 3 itens coletados

tests/test_app.py::test_name APROVADO [ 33%]
tests/test_app.py::test_empty APROVADO [ 66%]
tests/test_app.py::test_brutus REPROVADO [100%]

=================================== FALHAS ===================================
_________________________________ test_brutus __________________________________

    def test_brutus():
 """Se o nome for Brutus, forneça uma saudação especial"""

> assert greeting("Brutus") == "Cuidado com os IDEs do Python!"
E AssertionError: assert 'Olá, Brutus' == 'Cuidado com os IDEs do Python!'
E - Cuidado com os IDEs do Python!
E + Hello, Brutus

tests/test_app.py:19: AssertionError
=========================== breve resumo das informações do teste ============================
FALHA tests/test_app.py::test_brutus - AssertionError: assert 'Hello, Brutus...
========================= 1 falha, 2 aprovados em 0,14s ==========================

Dessa vez, vemos uma falha no teste - e a saída explica a origem da falha: o teste está esperando a saída "BeeWare the IDEs of Python!", mas nossa implementação de greeting() está retornando "Hello, Brutus". Vamos modificar a implementação de greeting() em src/helloworld/app.py para obter o novo comportamento:

def greeting(name):
    if name:
    if name == "Brutus":
        return "Cuidado com os IDEs do Python!"
    else:
        return f"Olá, {name}"
    else:
        return "Olá, desconhecido"

Se executarmos os testes novamente, veremos que nossos testes foram aprovados:

(beeware-venv) $ briefcase dev --test

[helloworld] Executando conjunto de testes no ambiente de desenvolvimento...
===========================================================================
============================= Início da sessão de testes ==============================
...
coletando ... 3 itens coletados

tests/test_app.py::test_name APROVADO [ 33%]
tests/test_app.py::test_empty APROVADO [ 66%]
tests/test_app.py::test_brutus APROVADO [100%]

============================== 3 aprovados em 0,15 s ===============================
(beeware-venv) $ briefcase dev --test

[helloworld] Executando conjunto de testes no ambiente de desenvolvimento...
===========================================================================
============================= Início da sessão de testes ==============================
...
coletando ... 3 itens coletados

tests/test_app.py::test_name APROVADO [ 33%]
tests/test_app.py::test_empty APROVADO [ 66%]
tests/test_app.py::test_brutus APROVADO [100%]

============================== 3 aprovados em 0,15 s ===============================
(beeware-venv) C:\...>briefcase dev --test

[helloworld] Executando conjunto de testes no ambiente de desenvolvimento...
===========================================================================
============================= Início da sessão de testes ==============================
...
coletando ... 3 itens coletados

tests/test_app.py::test_name APROVADO [ 33%]
tests/test_app.py::test_empty APROVADO [ 66%]
tests/test_app.py::test_brutus APROVADO [100%]

============================== 3 aprovados em 0,15 s ===============================

Testes de tempo de execução

Até o momento, estamos executando os testes no modo de desenvolvimento. Isso é especialmente útil quando se está desenvolvendo novos recursos, pois é possível iterar rapidamente na adição de testes e na adição de código para que esses testes sejam aprovados. No entanto, em algum momento, você desejará verificar se o seu código também é executado corretamente no ambiente do aplicativo de pacote.

As opções --test e -r também podem ser passadas para o comando run. Se você usar briefcase run --test -r, o mesmo conjunto de testes será executado, mas dentro do pacote de aplicativos empacotados, e não no seu ambiente de desenvolvimento:

(beeware-venv) $ briefcase run --test -r

[helloworld] Atualizando o código do aplicativo...
Instalando src/helloworld... concluído
Instalando testes... concluído

[helloworld] Atualizando requisitos...
...
[helloworld] Compilado build/helloworld/macos/app/Hello World.app (modo de teste)

[helloworld] Iniciando conjunto de testes...
===========================================================================
Configurando Python isolado...
Pré-inicializando o runtime do Python...
PythonHome: /Users/brutus/beeware-tutorial/helloworld/macOS/app/Hello World/Hello World.app/Contents/Resources/support/python-stdlib
PYTHONPATH:
- /Users/brutus/beeware-tutorial/helloworld/macOS/app/Hello World/Hello World.app/Contents/Resources/support/python311.zip
- /Users/brutus/beeware-tutorial/helloworld/macOS/app/Hello World/Hello World.app/Contents/Resources/support/python-stdlib
- /Users/brutus/beeware-tutorial/helloworld/macOS/app/Hello World/Hello World.app/Contents/Resources/support/python-stdlib/lib-dynload
- /Users/brutus/beeware-tutorial/helloworld/macOS/app/Hello World/Hello World.app/Contents/Resources/app_packages
- /Users/brutus/beeware-tutorial/helloworld/macOS/app/Hello World/Hello World.app/Contents/Resources/app
Configurando argc/argv...
Inicializando o tempo de execução do Python...
Instalando o manipulador NSLog do Python...
Executando o módulo do aplicativo: tests.helloworld
---------------------------------------------------------------------------
============================= início da sessão de teste ==============================
...
coletando... 3 itens coletados

tests/test_app.py::test_name APROVADO [ 33%]
tests/test_app.py::test_empty APROVADO [ 66%]
tests/test_app.py::test_brutus APROVADO [100%]

============================== 3 aprovados em 0,21 s ===============================

[helloworld] Conjunto de testes aprovado!
(beeware-venv) $ briefcase run --test -r

[helloworld] Finalizando a configuração do aplicativo...
Selecionando o alvo ubuntu:jammy (base Debian do fornecedor)
Determinando a versão da glibc... concluído
Selecionando a glibc 2.35
Selecionando o Python 3.10

[helloworld] Atualizando o código do aplicativo...
Instalando src/helloworld... concluído
Instalando testes... concluído

[helloworld] Atualizando requisitos...
...
[helloworld] Compilado build/helloworld/linux/ubuntu/jammy/helloworld-0.0.1/usr/bin/helloworld (modo de teste)

[helloworld] Iniciando conjunto de testes...
===========================================================================
============================= início da sessão de testes ==============================
...
coletando... 3 itens coletados

tests/test_app.py::test_name APROVADO [ 33%]
tests/test_app.py::test_empty APROVADO [ 66%]
tests/test_app.py::test_brutus APROVADO [100%]

============================== 3 aprovados em 0,21 s ===============================
(beeware-venv) C:\...>briefcase run --test -r

[helloworld] Atualizando o código do aplicativo...
Instalando src/helloworld... concluído
Instalando testes... concluído

[helloworld] Atualizando os requisitos...
...
[helloworld] Compilado build\helloworld\windows\app\src\Hello World.exe (modo de teste)

===========================================================================
Registro iniciado: 02/12/2022 10:57:34Z
Pré-inicializando o runtime do Python...
PythonHome: C:\Users\brutus\beeware-tutorial\helloworld\windows\app\Hello World\src
PYTHONPATH:
- C:\Users\brutus\beeware-tutorial\helloworld\windows\app\Hello World\src\python311.zip
- C:\Users\brutus\beeware-tutorial\helloworld\windows\app\Hello World\src
- C:\Users\brutus\beeware-tutorial\helloworld\windows\app\Hello World\src\app_packages
- C:\Users\brutus\beeware-tutorial\helloworld\windows\app\Hello World\src\app
Configurando argc/argv...
Inicializando o tempo de execução do Python...
Executando o módulo da aplicação: tests.helloworld
---------------------------------------------------------------------------
============================= início da sessão de teste ==============================
...
coletando ... 3 itens coletados

tests/test_app.py::test_name APROVADO [ 33%]
tests/test_app.py::test_empty APROVADO [ 66%]
tests/test_app.py::test_brutus APROVADO [100%]

============================== 3 aprovados em 0,21 s ===============================

Como no caso do briefcase dev --test, a opção -r só é necessária na primeira vez em que você executa o conjunto de testes para garantir que as dependências de teste estejam presentes. Nas execuções subsequentes, você pode omitir essa opção.

Você também pode usar a opção --test em back-ends móveis: - assim, briefcase run iOS --test e briefcase run android --test funcionarão, executando o conjunto de testes no dispositivo móvel que você selecionar.