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.