🧰 CAPÍTULO 00: KIT DE SOBREVIVÊNCIA — ENGENHARIA DE SOFTWARE


📖 Pré-requisito

Este capítulo assume que você já passou pelo Capítulo 00 — Fundamentos Comuns (terminal, Git, POO em Python, JSON/HTTP). Se ainda não viu, comece por lá.

🎯 Objetivos de Aprendizagem

Estimativa de dedicação: 2 horas de estudo autoguiado. Ao final deste capítulo, você será capaz de:

  • 🔹 Ler (não desenhar) os três diagramas UML mais usados no curso: Casos de Uso, Classes e Sequência.
  • 🔹 Subir seu primeiro servidor Flask e responder a uma requisição real.
  • 🔹 Escrever e rodar seu primeiro teste automatizado com pytest.

🏢 Por que isso importa

A Atividade 05 já pede um Diagrama de Casos de Uso, a Atividade 06 já pede para rodar um servidor Flask real e testá-lo com curl, e a Atividade 09 já pede testes com pytest — tudo isso antes da teoria completa de cada tópico ter sido consolidada. Este capítulo adianta o mínimo necessário para você não travar nesses pontos.


🧠 1. Como Ler um Diagrama UML

Você não precisa saber desenhar UML perfeitamente ainda — precisa saber ler os três tipos que mais aparecem no curso.

📌 Caso de Uso: "o que o sistema faz, por quem"

Um boneco (ator) se conecta a ações (óvalos). Uma seta pontilhada com <<include>> significa "esse caso de uso sempre aciona o outro".

flowchart LR
    Cliente(("👤 Cliente"))
    UC1(["Rastrear Pacote"])
    UC2(["Cadastrar Pacote"])
    UC3(["Validar CEP"])

    Cliente --> UC1
    Cliente --> UC2
    UC2 -.->|"《include》"| UC3

    style Cliente fill:#e3f2fd,stroke:#1e88e5
    style UC3 fill:#fff8e1,stroke:#fbc02d

Leitura: o Cliente pode Rastrear ou Cadastrar um Pacote; cadastrar sempre inclui validar o CEP.

📌 Classes: "quais entidades existem e como se relacionam"

Cada caixa é uma classe (atributos em cima, métodos embaixo). O número perto da linha é a multiplicidade (quantos de cada lado).

classDiagram
    class Cliente {
        -nome: str
        -email: str
    }
    class Pacote {
        -codigo: str
        -peso_kg: float
        +calcular_frete() float
    }
    Cliente "1" --> "*" Pacote : envia

Leitura: 1 Cliente pode enviar * (zero ou muitos) Pacotes.

📌 Sequência: "quem chama quem, em que ordem, ao longo do tempo"

Cada linha vertical é um participante. As setas horizontais são mensagens, lidas de cima para baixo.

sequenceDiagram
    actor Cliente
    participant App as App Web
    participant API as API Flask

    Cliente->>App: Rastrear pacote BR123456
    App->>API: GET /api/pacotes/BR123456
    activate API
    API-->>App: 200 OK + status JSON
    deactivate API
    App-->>Cliente: Mostra status na tela

Leitura: o Cliente pede à tela, a tela pede à API, a API responde, a tela mostra o resultado — nessa ordem exata.

🎯 Ferramenta oficial de desenho

Para desenhar seus próprios diagramas (não só ler), o curso usa o draw.io (extensão hediet.vscode-drawio já no .vscode/extensions.json). O Mermaid acima é só para você aprender a ler rápido, direto no navegador.


🧠 2. Flask: Seu Primeiro "Hello World"

A partir da Atividade 06, você vai rodar um servidor Flask de verdade. Vamos fazer isso uma vez, com calma.

📋 Instalação

pip install flask

💻 Código Completo (app.py)

"""
Módulo: app.py
Primeiro servidor Flask da jornada TecProExpress.
Execução: python app.py
"""
from flask import Flask, request, jsonify

app = Flask(__name__)

@app.route("/")
def index():
    return "🚚 TecProExpress API no ar!"

@app.route("/api/saudacao", methods=["POST"])
def saudacao():
    dados = request.get_json() or {}
    nome = dados.get("nome", "visitante")
    return jsonify({"mensagem": f"Olá, {nome}! Bem-vindo à TecProExpress."}), 200

if __name__ == "__main__":
    print("🚀 Servidor Flask ativo em: http://127.0.0.1:5000")
    app.run(debug=True, port=5000)

🚀 Como Executar

python app.py

🌐 Testando com curl (em outro terminal)

curl -X POST http://127.0.0.1:5000/api/saudacao \
     -H "Content-Type: application/json" \
     -d "{\"nome\": \"Ana\"}"

🖥️ Resposta Esperada

{"mensagem": "Olá, Ana! Bem-vindo à TecProExpress."}

🧩 Alternativa ao curl: extensão de navegador

Se preferir uma interface gráfica em vez de digitar comandos no terminal, use a extensão Yet Another REST Client (YARC) no Chrome (yet-another-rest-client.com):

  1. Instale a extensão na Chrome Web Store e abra-a.
  2. Configure o método POST e a URL http://127.0.0.1:5000/api/saudacao.
  3. Na aba de corpo (Body), selecione JSON e cole {"nome": "Ana"}.
  4. Clique em Send e confira a mesma resposta mostrada acima.

Funciona tão bem quanto o curl — use o que for mais confortável para você.

🔍 Detalhamento do Código:

  • @app.route("/api/saudacao", methods=["POST"]): registra a rota e o verbo HTTP aceito.
  • request.get_json(): lê o corpo JSON enviado no -d do curl.
  • jsonify(...): converte o dicionário Python de volta em uma resposta JSON válida.
  • app.run(debug=True, port=5000): debug=True recarrega o servidor sozinho a cada alteração salva — ótimo durante o desenvolvimento.

⚠️ Porta ocupada?

Se a porta 5000 já estiver em uso no seu computador, troque para app.run(debug=True, port=5001) — e lembre de usar a mesma porta no curl. É exatamente esse tipo de divergência (porta do servidor ≠ porta do curl) que mais trava quem está começando.


🧠 3. pytest em 10 Minutos

📋 Instalação

pip install pytest

💻 Código Completo (test_saudacao.py)

Salve no mesmo diretório do app.py criado acima:

"""
Módulo: test_saudacao.py
Execução: pytest test_saudacao.py -v
"""
import pytest
from app import app


@pytest.fixture
def client():
    app.config["TESTING"] = True
    with app.test_client() as client:
        yield client


def test_saudacao_com_nome(client):
    resposta = client.post("/api/saudacao", json={"nome": "Ana"})
    assert resposta.status_code == 200
    assert "Ana" in resposta.get_json()["mensagem"]


def test_saudacao_sem_nome(client):
    resposta = client.post("/api/saudacao", json={})
    assert resposta.status_code == 200
    assert "visitante" in resposta.get_json()["mensagem"]

🚀 Como Executar

pytest test_saudacao.py -v

🖥️ Saída Esperada no Terminal

test_saudacao.py::test_saudacao_com_nome PASSED                        [ 50%]
test_saudacao.py::test_saudacao_sem_nome PASSED                        [100%]

============================== 2 passed in 0.08s ===============================

🔍 Detalhamento do Código:

  • @pytest.fixture: prepara algo reutilizável (aqui, um cliente de testes) para cada função de teste que o receber como parâmetro.
  • app.test_client(): simula requisições HTTP contra o Flask sem precisar subir o servidor de verdade — mais rápido e mais confiável.
  • assert: se a condição for falsa, o teste falha e o pytest mostra exatamente qual valor era esperado.

💡 Checkpoint de Lógica

Importante

Reflexão Profissional: Por que testar com app.test_client() é melhor do que abrir o navegador e clicar manualmente toda vez que você muda uma linha de código? (Resposta: um teste automatizado roda em milissegundos, não esquece nenhum caso, e pode rodar sozinho num pipeline de CI/CD a cada push — o que você fará na Atividade 16.) 🧠🛡️


🧪 Quiz de Fixação e Autoavaliação

🧪 Quiz de Autoavaliação — Capítulo 00 (Engenharia de Software)

1. No diagrama de classes, o que a multiplicidade "1" --> "*" entre Cliente e Pacote significa?

  • A) Todo Pacote pertence a exatamente 1 Cliente e todo Cliente tem exatamente 1 Pacote.
  • B) Um Cliente pode enviar zero ou muitos Pacotes.
  • C) Um Pacote pode ter muitos Clientes.
  • D) É um erro de sintaxe.
💡 Ver Resposta e Justificativa

Resposta Correta: B
Justificativa: "1" do lado de Cliente e "*" do lado de Pacote significa "1 Cliente para 0..N Pacotes" — a leitura sempre começa do lado com "1".


2. No Flask, qual função converte um dicionário Python em uma resposta JSON válida?

  • A) request.get_json()
  • B) jsonify()
  • C) app.route()
  • D) json.dumps() é obrigatório, jsonify() não existe no Flask.
💡 Ver Resposta e Justificativa

Resposta Correta: B
Justificativa: jsonify() é a função nativa do Flask para serializar dados Python em uma resposta HTTP com Content-Type: application/json correto.


3. Por que usar app.test_client() em vez de rodar o servidor de verdade nos testes?

  • A) É mais rápido e não depende de uma porta de rede estar livre.
  • B) É a única forma de testar rotas POST.
  • C) Não é possível testar Flask com pytest.
  • D) test_client() substitui o curl em produção.
💡 Ver Resposta e Justificativa

Resposta Correta: A
Justificativa: test_client() simula requisições HTTP em memória, sem abrir uma porta de rede real — os testes rodam em milissegundos e não conflitam entre si.


🛠️ Ponte para a Ação

🎯 Próximo Passo

Você está pronto para a jornada. Siga para: 👉 CAPÍTULO 01: INTRODUÇÃO E NATUREZA DO SOFTWARE 👉 ATIVIDADE 01: ESCOPO E PERSONAS


📌 Resumo Executivo & Key Takeaways

  • UML: Casos de Uso mostram quem faz o quê; Classes mostram quais entidades existem; Sequência mostra a ordem das chamadas ao longo do tempo.
  • Flask: uma rota é uma função decorada com @app.route; request.get_json() lê a entrada, jsonify() formata a saída.
  • pytest: app.test_client() testa rotas Flask sem precisar de um servidor real rodando — é assim que a Atividade 09 e o pipeline de CI/CD da Atividade 16 funcionam.