Como Sistemas Criticos Sao Testados: Aviacao,
Na web, a gente faz deploy sexta à tarde e torce pro Sentry não apitar. Na aviação, cada linha de código passa por verificação formal antes de entrar
TL;DR
Como Sistemas Criticos Sao Testados: Aviacao,. Na web, a gente faz deploy sexta à tarde e torce pro Sentry não apitar. Na aviação, cada linha de código passa por verificação formal antes de entrar num avião com 200 pessoas. A diferença de rigor é absurda — e tem coisa que dá pra trazer pro nosso mundo.
Eu escrevo testes todo dia. Unit tests, integration tests, e2e com Playwright. Minha cobertura fica em torno de 70-80% na maioria dos projetos. E por muito tempo eu achava que era suficiente.
Aí eu fui estudar como a aviação testa software. O nível de rigor é de outro planeta. Não é 70% de cobertura — é 100% de MC/DC coverage, onde cada sub-condição de cada if precisa ser testada independentemente. Não é 'roda os testes no CI' — é verificação formal matemática provando que o código não tem certos tipos de bug. Não é 'hotfix em 5 minutos' — é um processo de meses para certificar cada mudança.
Esse artigo é o resultado da minha pesquisa sobre como três indústrias — aviação, medicina e finanças — testam software onde bugs têm consequências irreversíveis. E no final, o que a gente pode roubar dessas práticas pro nosso dia a dia.
Níveis de criticidade: SIL, DAL e ASIL
Antes de falar de testes, preciso explicar como a indústria classifica criticidade. Nem todo software num avião tem o mesmo nível de risco. O sistema de entretenimento (tela do passageiro) não precisa do mesmo rigor que o piloto automático. Faz sentido.
Cada indústria tem seu próprio sistema de classificação, mas a lógica é a mesma: quanto pior a consequência de uma falha, mais rigoroso o teste.
DAL (Design Assurance Level) — Aviação
Classificação DO-178C para software embarcado em aeronaves
+ Prós
- • DAL A (catastrófico): falha causa crash. Exige MC/DC coverage, verificação independente total
- • DAL B (perigoso/severo): falha causa dano sério. Exige decision coverage + independência
- • DAL C (major): falha causa desconforto ou aumento de carga de trabalho. Statement + decision coverage
- • DAL D (minor): falha é notada mas sem impacto significativo. Statement coverage
- • DAL E (sem efeito): sem impacto na segurança. Sem requisitos de software
ASIL (Automotive Safety Integrity Level) — Automotivo
Classificação ISO 26262 para software veicular
+ Prós
- • ASIL D (mais rigoroso): direção, frenagem — falha pode matar. Equivalente ao DAL A
- • ASIL C: airbags, ABS — falha causa ferimento sério
- • ASIL B: luzes externas — falha aumenta risco de acidente
- • ASIL A (menos rigoroso): ar condicionado, rádio — falha causa desconforto
- • QM (Quality Management): sem requisitos especiais de segurança
Aviação: DO-178C e o MC/DC coverage
O DO-178C é o padrão que define como software aeronáutico deve ser desenvolvido e verificado. Pra software nível A — o mais crítico — o DO-178C exige um tipo de cobertura de testes chamado MC/DC (Modified Condition/Decision Coverage).
Na web, a gente usa statement coverage (cada linha foi executada?) e branch coverage (cada branch de if/else foi testada?). MC/DC vai muito mais fundo. Ele exige que cada condição dentro de uma expressão booleana seja testada de forma que ela sozinha mude o resultado da decisão.
Exemplo: if (A && B || C)
Branch coverage: precisa testar true e false. 2 testes.
MC/DC coverage: precisa mostrar que CADA variável
independentemente afeta o resultado.
Teste 1: A=true, B=true, C=false → true
Teste 2: A=false, B=true, C=false → false
(mudar A sozinho muda o resultado: A tem efeito independente)
Teste 3: A=true, B=true, C=false → true
Teste 4: A=true, B=false, C=false → false
(mudar B sozinho muda o resultado: B tem efeito independente)
Teste 5: A=false, B=false, C=true → true
Teste 6: A=false, B=false, C=false → false
(mudar C sozinho muda o resultado: C tem efeito independente)
Mínimo: N+1 testes para N condições.Com MC/DC, você não consegue ter um if com 5 condições onde 3 nunca foram testadas de verdade. Cada condição precisa provar que faz diferença. É um nível de rigor que pega bugs em lógica booleana complexa que branch coverage simplesmente não detecta.
O custo do rigor
O custo de seguir DO-178C nível A é gigantesco. Estima-se que o custo por linha de código em software DAL A certificado fica entre 50 e 100 dólares. Pra comparação, software web comercial custa entre 5 e 20 dólares por linha. O rigor custa 5 a 10 vezes mais. Mas quando o software controla se um avião com 200 pessoas cai ou não, 100 dólares por linha é barato.
Verificação formal: provando matematicamente que o código é correto
Testes mostram que o código funciona em cenários específicos. Verificação formal prova matematicamente que o código funciona em todos os cenários possíveis. É a diferença entre testar que 2+2=4 e provar que a adição é comutativa pra todo par de números.
Ferramentas como o Polyspace da MathWorks analisam o código sem executá-lo e provam que certas categorias de bug não existem: divisão por zero, integer overflow, buffer overflow, null pointer dereference. Não é 'provavelmente não tem esse bug' — é 'matematicamente impossível que esse bug exista nesse código'.
Verificação formal não é prática pra a maioria dos projetos web. É caro, é lento e exige expertise especializada. Mas pra código que controla um marca-passos ou um sistema de frenagem, o custo é justificado. A diferença entre 99.9% de certeza e 100% de certeza é a diferença entre 'provavelmente funciona' e 'pacientes não vão morrer'.
Medicina: FDA, IEC 62304 e o peso da regulação
Software médico é regulado pela FDA nos EUA e por órgãos equivalentes no resto do mundo. O padrão técnico é o IEC 62304 (Medical device software — Software life cycle processes). Ele define três classes de segurança: A (sem risco), B (risco de ferimento) e C (risco de morte).
Pra classe C — software que pode matar se falhar, como um sistema de infusão de medicamentos ou um ventilador mecânico — o IEC 62304 exige documentação completa de arquitetura, design detalhado de cada módulo, testes de unidade, integração e sistema, análise de riscos e rastreabilidade completa de requisitos.
- Definir requisitos de software com rastreabilidade para requisitos do dispositivo
- Criar arquitetura de software documentada com análise de pontos de falha
- Design detalhado de cada módulo com interfaces claramente definidas
- Implementar usando padrões de codificação seguros (MISRA C para embarcado)
- Testes de unidade, integração e sistema com evidência rastreável
- Análise de riscos: para cada falha possível do software, documentar probabilidade e severidade
- Submeter documentação completa à FDA ou órgão regulador para aprovação
- Manter processo de gerenciamento de mudanças para qualquer update pós-aprovação
O detalhe que choca quem vem do mundo web: cada update de software num dispositivo médico aprovado pela FDA precisa de um novo processo de validação. Você não faz deploy toda segunda. Uma atualização pode levar meses pra ser aprovada. Isso muda completamente a forma de pensar em releases.
O caso do Therac-25 e como a regulação mudou
O Therac-25 — a máquina de radioterapia que matou pacientes por causa de uma race condition — é o motivo pelo qual a regulação de software médico ficou tão rigorosa. Antes do Therac-25, software em dispositivos médicos era tratado como algo secundário. Depois dos acidentes, a FDA criou todo um framework de regulação específico pra software.
Hoje, se você desenvolve software pra dispositivo médico, precisa de um QMS (Quality Management System) certificado ISO 13485, processo de desenvolvimento seguindo IEC 62304, análise de riscos seguindo ISO 14971, e documentação que prova que cada requisito foi implementado, testado e verificado. É burocrático? É. Mas as mortes do Therac-25 são o motivo. A burocracia existe porque pessoas morreram quando ela não existia.
Finanças: circuit breakers, halt rules e chaos engineering
O mercado financeiro tem uma relação diferente com falhas de software. Na aviação e medicina, o objetivo é zero defeitos. Em finanças, o objetivo é resiliência — assumir que vai falhar e garantir que a falha não cascateie.
Depois do flash crash de 2010 — quando o Dow Jones caiu 1000 pontos em 5 minutos por causa de algoritmos de trading em loop — as bolsas implementaram circuit breakers. Se o mercado cai mais de 7% em um dia, trading é pausado por 15 minutos. Se cai 13%, pausa de novo. Se cai 20%, trading é encerrado pro dia.
A lógica é simples: quando as coisas dão errado, a pior coisa que você pode fazer é continuar operando em velocidade máxima. Parar, avaliar e decidir conscientemente é melhor do que deixar algoritmos em pânico tomarem decisões em milissegundos.
Circuit breakers aplicados ao seu código
O padrão Circuit Breaker do Michael Nygard serve exatamente pra isso em microserviços.
Se um serviço downstream falha N vezes seguidas, o circuit breaker 'abre' e para de chamar por X segundos.
Evita que uma falha em um serviço cascade e derrube todo o sistema.
Bibliotecas: resilience4j (Java), Polly (.NET), opossum (Node.js).
Chaos engineering no mercado financeiro
Bolsas de valores como NYSE e NASDAQ fazem disaster recovery testing regularmente. Simulam falha de data centers inteiros, perda de conectividade entre exchanges e cenários de volume extremo (10x o volume normal). Se o sistema não aguenta, descobrem antes que aconteça de verdade.
A Netflix popularizou chaos engineering com o Chaos Monkey — um programa que mata instâncias aleatórias em produção pra garantir que o sistema se recupera. Bolsas de valores fazem algo parecido, mas com mais formalidade e menos aleatoriedade. Cada cenário de falha é planejado, executado e documentado.
O que devs web podem aprender com sistemas críticos
Não precisa implementar DO-178C no seu projeto React. Mas existem práticas de teste de sistemas críticos que são surpreendentemente fáceis de adotar e que melhoram muito a qualidade do software.
Práticas de sistemas críticos adaptadas pra web
- Mutation testing: ferramentas como Stryker modificam seu código e rodam seus testes — se os testes passam com código modificado, eles não estão testando de verdade
- Fault injection: simule falhas de dependências (banco fora, API lenta, disco cheio) nos testes de integração
- Canary deploy: mande a versão nova pra 1% dos usuários primeiro, monitore métricas, só depois escale
- Rollback automático: se error rate subir X% após deploy, reverta automaticamente em segundos
- Teste de load antes de lançamento: use k6 ou Artillery pra simular o tráfego esperado no dia do lançamento
- Chaos engineering light: mate um pod do Kubernetes aleatoriamente por semana e veja se o sistema se recupera
- Runbook de incidentes: documente passo a passo o que fazer quando cada tipo de falha acontecer
A filosofia por trás de tudo
A diferença entre como a aviação testa software e como a web testa software não é só técnica — é filosófica. Na aviação, a premissa é: o software VAI falhar, então a gente precisa provar que as falhas não matam. Na web, a premissa é: o software provavelmente funciona, e se não funcionar a gente corrige rápido.
As duas abordagens são válidas para seus contextos. Eu não quero esperar 6 meses pra certificar cada deploy do meu blog. Mas eu também não quero fazer deploy de código de cobrança sem load testing só porque 'é urgente'.
O ponto ideal pra maioria dos projetos web está no meio. Usar as técnicas da web para velocidade de iteração — CI/CD, feature flags, canary deploys — combinadas com a mentalidade de sistemas críticos para os componentes que realmente importam: pagamento, autenticação, dados de saúde, informações pessoais.
Ferramentas pra começar hoje
Stryker Mutator
Mutation testing para JS/TS. Modifica seu código automaticamente e verifica se os testes detectam. Se não detectam, seus testes são fracos.
k6 (Grafana)
Load testing em JavaScript. Simula milhares de usuários e mede latência, throughput e error rate. Integra com CI.
Chaos Toolkit
Framework open source para chaos engineering. Define experimentos em YAML e injeta falhas controladas no sistema.
Gremlin
Plataforma comercial de chaos engineering. Injeta falhas de rede, CPU, disco e DNS de forma controlada em produção.
Se quiser entender o contexto histórico de por que esses padrões de teste existem, o artigo sobre code review pra sistemas críticos mostra a parte de revisão humana que complementa os testes automatizados. E os maiores fracassos de engenharia de software mostram o que acontece quando nenhuma dessas práticas é seguida.