Verificação, validação e testes

Evidência estática e dinâmica, revisões, níveis de teste, casos, fronteiras, cobertura e defeitos.

TLDR

Perguntar sobre esta página

ChatGPTClaudePerplexityGrokGeminiCopiar e abrirDeepSeekCopiar e abrir

A aplicação confirma reservas conforme a especificação, mas Ana engana-se no horário e descobre que não pode cancelar. Passar os cenários escritos não resolve uma necessidade que ficou fora do documento.

Verificação e validação

Verificação avalia a conformidade de um artefacto com a sua especificação. Validação avalia se o sistema responde ao uso e às necessidades pretendidas.

Podemos verificar código, modelos e requisitos. Também podemos validar requisitos ou um protótipo com utilizadores antes de existir o produto final. A distinção está no objetivo da avaliação, não numa divisão rígida entre “revisão” e “teste”.

Outra distinção diz respeito à execução:

  • As técnicas estáticas analisam representações sem executar o sistema: revisões, inspeções, análise estática e verificação formal.
  • As técnicas dinâmicas executam o sistema ou um modelo: testes e simulações.

As duas complementam-se. Uma revisão pode encontrar uma regra contraditória; um teste pode mostrar como a implementação reage a um caso concreto.

Revisões e inspeções

Uma revisão analisa um artefacto para descobrir problemas e avaliar qualidade. Uma inspeção é uma revisão mais estruturada, com preparação, papéis, critérios e registo de defeitos. Um walkthrough percorre o artefacto ou cenário com outras pessoas.

Para rever um caso de uso de reservas, podemos perguntar:

  • Estão definidos ator, pré-condições e resultado?
  • O sistema trata sala ocupada, intervalo inválido e indisponibilidade?
  • A regra contradiz outro requisito?
  • Conseguimos derivar exemplos de aceitação?

A checklist deve nascer de problemas relevantes e do histórico da equipa. Não substitui o raciocínio. Preparar a revisão e permitir leitura individual pode encontrar defeitos que uma apresentação rápida não revela.

Ferramentas de análise estática detetam certas classes de problemas, como código inatingível ou usos suspeitos de APIs. Podem ter falsos positivos e não conhecem automaticamente todas as regras do domínio. Compilar e passar o linter não valida o produto.

Caso de teste e oráculo

Um caso de teste define entradas, condições de execução e resultados esperados para um objetivo. O oráculo permite decidir se o comportamento observado é aceitável: pode ser uma regra, um resultado calculado independentemente ou uma expectativa acordada.

O resultado esperado precisa de uma justificação independente do código sob teste. Copiar a resposta da implementação para o teste pode conservar o mesmo defeito nos dois.

No caso de sobreposição, começamos com uma sala reservada das 14h às 15h. Pedimos das 14h30 às 15h30. Esperamos uma recusa e nenhuma nova reserva. Ver só uma mensagem de erro não chega se o sistema tiver criado a reserva na mesma.

Um script é a concretização dos passos, manual ou automatizada. O caso explica o que verificar; o script diz como fazê-lo no ambiente.

Níveis e objetivos

NívelO que avaliamosExemplo
Unidade ou componenteUma unidade isolada ou pequeno grupo relacionadoRegra de duração da reserva
IntegraçãoInterações entre componentes ou sistemasServiço de reservas com armazenamento real
SistemaSistema completo contra requisitosFluxo móvel e servidor com falha de rede
AceitaçãoCritérios que permitem ao cliente aceitar o resultadoEstudante reserva uma sala segundo o cenário acordado

O nível não determina a característica de qualidade. Podemos testar desempenho ou segurança em vários níveis. Também não determina uma pessoa obrigatória em todas as equipas; a independência e as responsabilidades dependem do contexto.

Em Flutter, um unit test avalia lógica; um widget test avalia um widget e a sua interação num ambiente de teste; um integration test percorre a aplicação completa ou uma parte ampla. Estes nomes de ferramentas não substituem o objetivo de aceitação: um cenário do cliente pode ser parcialmente exercitado num widget test, mas serviços simulados não provam a integração real.

Dependências reais e simuladas

Um test double substitui uma dependência durante o teste. Por exemplo, um serviço simulado devolve sempre «reserva confirmada» ao ecrã. Isso permite observar se o ecrã apresenta a confirmação e termina o estado de espera, sem depender de rede ou dados. Não demonstra que o servidor verifica disponibilidade nem que os dois lados concordam no formato das mensagens.

Se o servidor passa a devolver conflito onde o ecrã espera ocupada, ambos podem passar os testes isolados com os seus próprios substitutos e falhar quando são ligados. Um teste de integração tem de exercitar essa fronteira com os componentes relevantes reais ou verificar explicitamente o contrato partilhado. Escolhe a substituição pela dúvida que queres isolar e regista a parte que ficou por verificar. Os participantes e as mensagens desse cenário seguem um diagrama de sequência.

Uma experiência com utilizadores pergunta se a pessoa compreende «pedido enviado» e «reserva confirmada». A integração pode estar correta e a comunicação continuar inadequada. Aumentar a quantidade de testes isolados não responde automaticamente a essa pergunta de validação.

Caixa preta e caixa branca

No teste de caixa preta, derivamos casos da especificação externa; no teste de caixa branca, usamos a estrutura interna, como ramos e caminhos, para escolher casos. Não é a mesma distinção que manual e automático: um teste automatizado de uma função pode ser de caixa preta se as entradas vierem da regra, sem olhar para o código.

Uma sequência prática é começar pelos casos derivados da especificação e acrescentar depois casos a partir da estrutura do código. Os primeiros verificam exemplos do comportamento esperado. A cobertura ajuda a identificar instruções ou ramos que esses exemplos ainda não exercitaram.

As partições de equivalência agrupam entradas que esperamos tratar de modo semelhante. Para duração inteira em minutos, válida entre 30 e 120 inclusive, temos menos de 30, de 30 a 120 e mais de 120.

Os valores de fronteira procuram diferenças junto dos limites. Testamos 29, 30, 31, 119, 120 e 121. Se a entrada puder ser decimal, precisamos de adaptar os valores à precisão permitida; não podemos assumir que um minuto é sempre o menor passo.

Um exemplo com intervalos

Adotamos intervalos semiabertos: a reserva inclui o início e exclui o fim. Assim, 14h às 15h e 15h às 16h são adjacentes e não se sobrepõem.

Nesta comparação avaliamos apenas a sobreposição entre intervalos com duração positiva; a regra dos 30 a 120 minutos é testada separadamente, e o intervalo contido de 15 minutos serve aqui para isolar a relação temporal. Dois intervalos válidos, com inícios i1,i2i_1,i_2 e fins f1,f2f_1,f_2, sobrepõem-se quando

i1<f2ei2<f1.i_1 < f_2 \quad \text{e} \quad i_2 < f_1.

Testamos reserva anterior, seguinte, parcialmente sobreposta, totalmente contida e igual. Uma reserva 14h30 às 14h45 está contida e deve ser recusada. Uma reserva 15h às 16h não satisfaz a segunda desigualdade relativamente a 14h às 15h, porque 15<1515 < 15 é falso.

Adjacência e sobreposição de reservasA reserva existente ocupa das 14h às 15h, excluindo o fim. O pedido das 15h às 16h é adjacente e aceite. Os pedidos das 14h30 às 15h30 e das 14h30 às 14h45 sobrepõem-se e são recusados.AdjacenteExistentePedido14h15h16hAceite: sem sobreposiçãoParcialExistentePedido14h15h16hRecusada: 14h30 a 15hContidaExistentePedido14h15h16hRecusada: 14h30 a 14h45
As três comparações usam a mesma escala. Círculo cheio inclui o instante; círculo aberto exclui-o.

Na figura, o círculo aberto exclui o fim e o círculo cheio inclui o início. As reservas adjacentes não partilham nenhum instante; a reserva contida partilha tempo mesmo sem atravessar as pontas da primeira.

Também testamos duas criações concorrentes. Dois testes sequenciais não demonstram que a operação atómica impede uma corrida.

Cobertura calculada num exemplo

function aceitarDuracao(minutos: number): boolean {
  if (minutos < 30) return false;
  if (minutos > 120) return false;
  return true;
}

Cobertura de instruções conta que instruções foram executadas. Cobertura de ramos conta as saídas verdadeiro e falso de cada decisão. A função tem duas decisões, por isso quatro ramos: verdadeiro e falso do primeiro if, verdadeiro e falso do segundo if.

Com os testes 29, 60 e 121, cobrimos os quatro ramos:

  • O teste 29 segue o ramo verdadeiro do primeiro if e regressa sem chegar ao segundo.
  • O teste 60 segue o ramo falso do primeiro e o ramo falso do segundo, até ao retorno final.
  • O teste 121 segue o ramo falso do primeiro e o ramo verdadeiro do segundo.

A cobertura de instruções é total e a cobertura de ramos é 4/4.

Com apenas o teste 60, só vemos os dois ramos falsos, por isso a cobertura de ramos é 2/4. Ficam por executar os dois retornos de recusa. Mesmo com 4/4, um oráculo copiado do código não deteta nada. O resultado esperado vem da regra: 29 recusa, 30 aceita, 31 aceita, 119 aceita, 120 aceita, 121 recusa. Cobertura mede execução, não correção do oráculo.

Cobertura e limites

Mesmo os testes 29, 60 e 121, que percorrem todos os ramos, não distinguem o limite correto minutos > 120 do defeito minutos >= 120. Nenhum deles testa 120. Acrescentar esse caso, com aceitação esperada, deteta a diferença. Cobertura mede execução; as fronteiras e os oráculos continuam a vir do contrato.

Testes mostram falhas em situações exercitadas e aumentam a confiança. Em geral, não provam a ausência de defeitos. A automação é útil para repetir verificações estáveis; testes instáveis precisam de diagnóstico, porque um sinal que muda sem alteração do produto deixa de orientar decisões.

Defeitos e regressão

Um defeito é um problema num artefacto. Uma falha é um comportamento observado que viola o esperado. Um defeito pode existir sem se manifestar em todas as execuções.

Um registo de defeito deve permitir reproduzir.

CampoExemplo
Versão e ambientebuild 1.4.2, Android 14, dados de teste salas-2026
Estado inicialsala A livre 14h30-15h30
Passosdois pedidos 14h30-15h30 em simultâneo
Esperadouma confirmação e uma recusa, uma reserva nos dados
Observadoduas confirmações, duas reservas sobrepostas

Distingue severidade, impacto da falha, de prioridade, urgência de resolução. Depois da correção, executamos o caso que demonstrava a falha e os testes relevantes para efeitos colaterais; os testes de regressão procuram comportamentos que antes funcionavam e deixaram de funcionar. O processo de teste inclui planear, analisar condições, desenhar casos, preparar execução, correr, acompanhar resultados e fechar com evidência.

Exercícios

Casos junto dos limites

Adota a convenção de três pontos por fronteira inteira: o limite e os inteiros imediatamente ao lado. A duração é um inteiro em minutos entre 30 e 120 inclusive. Propõe valores de fronteira e resultados esperados.

Pista

Olha para cada limite e para os valores inteiros imediatamente ao lado.

Solução

29 é recusado; 30 e 31 são aceites. 119 e 120 são aceites; 121 é recusado. A checklist pede estes seis valores porque segue a convenção de três pontos por fronteira. Também podemos testar um valor interior e entradas de outro tipo conforme o contrato.

Confere a tua resposta:

  • Incluí 29, 30 e 31.
  • Incluí 119, 120 e 121.
  • Recusei 29 e 121, aceitando os restantes.

Erros frequentes

Não recuses 30 ou 120. Não uses a mesma distância de fronteira se a entrada admitir outra precisão.

Voltar à explicação
Adjacência, contenção e intervalo inválido

A sala tem uma reserva das 14h às 15h. Os intervalos são semiabertos e uma reserva válida exige início anterior ao fim. Avalia os pedidos 15h–16h, 14h30–15h30, 14h30–14h45 e 15h–15h. Para cada um, justifica aceitação ou recusa pela validade e pela sobreposição. Ignora outras restrições de duração.

Pista

Aplica as duas desigualdades ao mesmo par de intervalos.

Solução

Para 15h–16h, 14 < 16 é verdadeiro mas 15 < 15 é falso: aceita-se. Para 14h30–15h30, ambas as desigualdades são verdadeiras: recusa-se. Para 14h30–14h45 também são verdadeiras, pois 14 < 14,75 e 14,5 < 15: estar contido é uma forma de sobreposição. Para 15h–15h, a duração é zero, logo o intervalo é inválido antes de testar conflitos. A condição de sobreposição pressupõe intervalos válidos.

Confere a tua resposta:

  • Aceitei 15h–16h por adjacência.
  • Recusei 14h30–15h30 e 14h30–14h45 por sobreposição.
  • Recusei 15h–15h por não ter início anterior ao fim.
  • Apliquei as duas desigualdades apenas a intervalos válidos.

Erros frequentes

Não uses menor ou igual para este contrato. Essa alteração faria recusar intervalos adjacentes.

Voltar à explicação
Cobertura total e um limite errado

A regra aceita minutos inteiros entre 30 e 120 inclusive. A função recusa primeiro valores menores que 30, depois valores maiores que 120, e aceita os restantes. Os testes 29, 60 e 121 verificam, respetivamente, recusa, aceitação e recusa. Que ramos percorrem? Detetam trocar a segunda condição por minutos maiores ou iguais a 120? Propõe um caso que detete esse defeito.

Pista

Compara os resultados nos limites, além dos ramos percorridos.

Solução

29 percorre o primeiro ramo verdadeiro e termina. 60 percorre os dois ramos falsos. 121 percorre o primeiro falso e o segundo verdadeiro. A união cobre os quatro ramos, 4/4. A condição alterada devolve os mesmos resultados nestas três entradas, por isso o defeito passa. O teste 120 deve esperar aceitação, derivada do limite inclusivo, e falha na versão com maior ou igual. Cobertura total não substitui casos derivados da especificação.

Confere a tua resposta:

  • Segui os ramos dos testes 29, 60 e 121 e obtive 4/4.
  • Expliquei por que trocar > 120 por >= 120 não é detetado por esses testes.
  • Acrescentei o caso 120 com aceitação esperada pela especificação.

Erros frequentes

Não apresentes 100% de cobertura como prova de correção. Não derives a expectativa copiando o resultado do código atual.

Voltar à explicação
Conforme, mas inadequado

O sistema passa todos os cenários de uma especificação que não inclui cancelamento. Numa revisão desse documento com estudantes, descobre-se que precisam de corrigir reservas feitas por engano. Que parte é verificação e que parte é validação? Esta revisão deixa de validar por não executar código?

Pista

Classifica pelo objetivo da avaliação, não pela ferramenta.

Mais uma pista

Um documento pode ser validado contra necessidades antes de haver implementação.

Solução

Comparar os resultados com a especificação dá evidência de verificação nos cenários executados. Descobrir com estudantes que falta cancelamento é validação dos requisitos contra as necessidades. A revisão é uma técnica estática e pode validar; não precisa de executar código. Passar os cenários escritos não demonstra que o produto resolve necessidades omitidas.

Confere a tua resposta:

  • Usei a comparação entre implementação e especificação como verificação.
  • Usei a necessidade de cancelamento como questão de validação.
  • Reconheci validação numa revisão de requisitos sem execução.

Erros frequentes

Não reduzas verificação a revisão e validação a execução. Não concluas que todas as necessidades estão satisfeitas porque todos os testes existentes passaram.

Voltar à explicação
Quatro experiências, quatro perguntas

Numa aplicação de bilhetes, A testa apenas a função que calcula o preço. B liga o componente de vendas ao serviço de pagamentos real num ambiente de teste. C mede o tempo de resposta da aplicação completa com 200 clientes. D percorre, com o cliente, os cenários acordados para decidir se aceita a entrega. Classifica o nível de cada experiência. Se B for substituída por um teste do ecrã com um serviço que devolve sempre sucesso, que risco deixa de ser observado? C torna-se teste de unidade por medir desempenho?

Solução

A é unidade: isola a regra de preço. B é integração: avalia a fronteira entre componentes reais. C é sistema: o objeto é a aplicação completa, embora a característica avaliada seja desempenho. D é aceitação: o objetivo é apoiar a decisão acordada de aceitar a entrega.

O substituto permite avaliar a apresentação do sucesso, mas pode esconder incompatibilidades de mensagens, autenticação e respostas de falha do serviço real. A medição de desempenho não fixa o nível de teste: podemos medir uma função isolada ou o sistema inteiro. O nível depende do objeto; a finalidade e a característica são outras dimensões.

Confere a tua resposta:

  • Classifiquei a regra isolada como unidade e a fronteira real como integração.
  • Classifiquei a medição do sistema completo como sistema.
  • Liguei o ensaio acordado com o cliente à aceitação.
  • Expliquei por que o teste do ecrã com serviço simulado não prova a fronteira real.
Voltar à explicação

À tua maneira

Aparência

Modo de cor
Tema
Cor de destaque

Leitura

Fonte de leitura

Álgebra, lógica e uma ideia de cada vez.

Código

Fonte do código

Navegação

Cursor de leitura, sem edição. h, j, k, l movem; / pesquisa nesta página. v seleciona caracteres; V seleciona linhas; y copia. Tab permite destacar ou comentar. Espaço ou Enter abre blocos recolhíveis. Nos cartões, h, j, k, l mudam o foco.

CSS personalizado

Ativa uma sugestão ou guarda o teu CSS. Só muda este navegador.

Usa --page, --text e --accent para acompanhar o tema.

Seletores e recuperação

.site-header, .prose, .course-card, [data-reading-history], [data-playground] e .page-actions.

Abre a aparência com a tecla vírgula ou no rodapé. Se o CSS esconder os controlos, abre esta página sem CSS personalizado.

Pesquisar

Escreve para pesquisar em todo o site.

para escolher · Enter para abrir · Esc para fechar

Copiar fórmula

A cópia automática não está disponível. Copia o LaTeX abaixo.

Pesquisar nesta página

Enter procura · n / N repetem · Esc cancela. Ctrl / Cmd K pesquisa todo o site.

Atalhos de teclado

Clica numa tecla para a mudar. Esc cancela. Backspace desativa.

PesquisarCtrl / Cmd K

Os atalhos não interferem enquanto escreves. Tab e Enter funcionam sempre.