Ir para o conteúdo

Hora de testes

A maior parte do desenvolvimento de software não envolve a gravação de novo código - é a modificação do código existente. Garantir que o código existente continua a funcionar da maneira esperada é uma parte fundamental do processo de desenvolvimento de software. Uma maneira de garantir o comportamento da nossa aplicação é com um conjunto de testes.

Executar a suite 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 da nossa aplicação; a pasta tests contém nosso conjunto de testes. Dentro da pasta tests há um ficheiro chamado test_app.py com o seguinte conteúdo:

def test_first():
    """Um teste inicial para a aplicação"""
    assert 1 + 1 == 2

Este é um Pytest caso de teste - um bloco de código que pode ser executado para verificar algum comportamento da sua aplicação. Nesse caso, o teste é um espaço reservado e não testa nada sobre a nossa aplicação, 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] A instalar pré-requisitos...
...
A instalar pré-requisitos de desenvolvimento... concluído

[helloworld] A executar 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
a recolher... 1 item recolhido

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

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

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

[helloworld] A executar 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
a recolher... 1 item recolhido

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

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

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

[helloworld] A executar 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
a recolher ... 1 item recolhido

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 que verifica 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, é mostrada uma saudação genérica"""

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

Isso define dois novos testes, verificar os dois comportamentos que esperamos ver: o resultado quando um nome é fornecido e o resultado quando o nome está vazio.

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

(beeware-venv) $ briefcase dev --test

[helloworld] A executar conjunto de testes no ambiente de desenvolvimento...
===========================================================================
============================= Início da sessão de testes ==============================
...
a recolher ... 2 itens recolhidos

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] A executar conjunto de testes no ambiente de desenvolvimento...
===========================================================================
============================= Início da sessão de testes ==============================
...
a recolher ... 2 itens recolhidos

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] A executar conjunto de testes no ambiente de desenvolvimento...
===========================================================================
============================= Início da sessão de testes ==============================
...
a recolher ... 2 itens recolhidos

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

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

Excelente! O nosso método utilitário greeting() está a funcionar como esperado.

Desenvolvimento orientado por testes

Agora que temos uma suite de testes, podemos usá-la para impulsionar o desenvolvimento de novos recursos. Vamos modificar a nossa aplicação para ter uma saudação especial para um determinado utilizador. Podemos começar por adicionar 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, é mostrada uma saudação especial"""

 assert greeting("Brutus") == "BeeWare as IDEs do Python!"

Depois, execute a suite de testes com este novo teste:

(beeware-venv) $ briefcase dev --test

[helloworld] A executar suite de testes no ambiente de desenvolvimento...
===========================================================================
============================= Início da sessão de testes ==============================
...
a recolher ... 3 itens recolhidos

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, é mostrada uma saudação especial"""

> assert greeting("Brutus") == "BeeWare os IDEs do Python!"
E AssertionError: assert 'Olá, Brutus' == 'BeeWare os IDEs do Python!'
E - BeeWare os IDEs do Python!
E + Olá, 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] A executar suite de testes no ambiente de desenvolvimento...
===========================================================================
============================= Início da sessão de testes ==============================
...
coletando... 3 itens recolhidos

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") == "BeeWare os IDEs do Python!"
E AssertionError: assert 'Hello, Brutus' == 'BeeWare os IDEs do Python!'
E - BeeWare os IDEs do Python!
E + Olá, 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] A executar suite de testes no ambiente de desenvolvimento...
===========================================================================
============================= início da sessão de testes ==============================
...
a recolher ... 3 itens recolhidos

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") == "BeeWare os IDEs do Python!"
E AssertionError: assert 'Olá, Brutus' == 'BeeWare os IDEs do Python!'
E - BeeWare os IDEs do Python!
E + Olá, 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 ==========================

Desta vez, vemos uma falha no teste - e o resultado explica a origem da falha: o teste está esperando a saída "BeeWare os IDEs do Python!", mas a nossa implementação de greeting() está a retornar "Olá, 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 "BeeWare os IDEs do Python!"
    else:
        return f"Olá, {name}"
    else:
        return "Olá, desconhecido"

Se executarmos os testes novamente, vamos ver que os nossos testes foram aprovados:

(beeware-venv) $ briefcase dev --test

[helloworld] A executar suite de testes no ambiente de desenvolvimento...
===========================================================================
============================= Início da sessão de testes ==============================
...
a recolher ... 3 itens recolhidos

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] A executar suite de testes no ambiente de desenvolvimento...
===========================================================================
============================= Início da sessão de testes ==============================
...
a recolher ... 3 itens recolhidos

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] A executar suite de testes no ambiente de desenvolvimento...
===========================================================================
============================= Início da sessão de testes ==============================
...
a recolher ... 3 itens recolhidos

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 em tempo de execução

Até o momento, estivemos a executar os testes no modo de desenvolvimento. Isso é especialmente útil quando se está a desenvolver 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, vai querer verificar se o seu código também é executado corretamente dentro do ambiente do pacote da aplicação.

As opções --test e -r também podem ser passadas para o comando run. Se usar briefcase run --test -r, o mesmo conjunto de testes será executado, mas vai correr dentro do bolo da aplicação empacotada, e não no seu ambiente de desenvolvimento:

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

[helloworld] A atualizar o código da aplicação...
A instalar src/helloworld... concluído
A instalar testes... concluído

[helloworld] A atualizar requisitos...
...
[helloworld] A compilar build/helloworld/macos/app/Hello World.app (modo de teste)

[helloworld] A iniciar conjunto de testes...
===========================================================================
A configurar Python isolado...
A pré-inicializaro 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
A configurar argc/argv...
A inicializar o tempo de execução do Python...
A instalar o manipulador NSLog do Python...
A executar o módulo da aplicação: tests.helloworld
---------------------------------------------------------------------------
============================= início da sessão de teste ==============================
...
a recolher ... 3 itens recolhidos

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] A finalizar a configuração da aplicação...
A selecionar o alvo ubuntu:jammy (base de fornecedor Debian)
A determinar a versão da glibc... concluído
A selecionar a glibc 2.35
A selecionar o Python 3.10

[helloworld] A atualizar o código da aplicação...
A instalar src/helloworld... concluído
A instalar testes... concluído

[helloworld] A atualizar requisitos...
...
[helloworld] A compilar build/helloworld/linux/ubuntu/jammy/helloworld-0.0.1/usr/bin/helloworld (modo de teste)

[helloworld] A iniciar conjunto de testes...
===========================================================================
============================= início da sessão de testes ==============================
...
a recolher ... 3 itens recolhidos

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] A atualizar o código da aplicação...
A instalar src/helloworld... concluído
A instalar testes... concluído

[helloworld] A atualizar os requisitos...
...
[helloworld] A compilar build\helloworld\windows\app\src\Hello World.exe (modo de teste)

===========================================================================
Registro iniciado: 02/12/2022 10:57:34Z
A pré-inicializaro 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
A configurar argc/argv...
A inicializar o tempo de execução do Python...
A executar o módulo da aplicação: tests.helloworld
---------------------------------------------------------------------------
============================= início da sessão de teste ==============================
...
a recolher ... 3 itens recolhidos

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 de briefcase dev --test, a opção -r só é necessária na primeira vez em que executa o conjunto de testes para garantir que as dependências de teste estejam presentes. Nas execuções subsequentes, pode omitir esta opção.

Também pode usar a opção --test em backends móveis: - para quebriefcase run iOS --test e briefcase run android --test funcionem ambos, correndo a suite de testes no dispositivo móvel que selecionar.