Pular para o conteúdo
Engenharia de Software

Safety-Critical Systems: Como Testar Software

Quando seu SaaS cai, o usuario reclama no Twitter. Quando software de aviacao cai, 300 pessoas morrem. Esse artigo mostra como a industria testa software que nao pode

Software que protege vidas

Safety-Critical Systems: Como Testar Software. Quando seu SaaS cai, o usuario reclama no Twitter. Quando software de aviacao cai, 300 pessoas morrem. Esse artigo mostra como a industria testa software que nao pode falhar — e o que voce pode copiar.

Galera, imagina o seguinte cenario: voce da deploy numa sexta-feira e o sistema cai. O que acontece? O usuario reclama, voce faz rollback, conserta na segunda. Agora imagina que em vez de um SaaS, voce ta deployando o software de freio de um carro a 120 km/h. Rollback nao e opcao.

E exatamente essa a diferenca entre software comum e safety-critical software. Quando falha, nao e ticket no Jira — e pessoa no hospital. E por isso que industrias como aviacao, medicina e automotivo desenvolvem software de um jeito radicalmente diferente.

Nesse artigo vou explicar o que sao safety-critical systems, as normas que regem cada industria, as tecnicas de teste que usam e — mais importante — o que voce pode copiar pra melhorar seu software comum.

O que sao safety-critical systems

Safety-critical system e qualquer sistema cuja falha pode resultar em morte, lesao grave, dano ambiental significativo ou perda economica catastrofica. A classificacao nao depende da complexidade do software — depende da consequencia da falha.

Cada industria tem sua escala de criticidade. Os nomes mudam mas o conceito e o mesmo: quanto mais grave a consequencia da falha, mais rigoroso o processo de desenvolvimento.

  1. SIL (Safety Integrity Level): padrao IEC 61508, usado em industria geral. Vai de SIL 1 (menos critico) a SIL 4 (mais critico — reatores nucleares, trens)
  2. DAL (Design Assurance Level): padrao DO-178C, usado em aviacao. Vai de DAL E (sem impacto) a DAL A (catastrofico — queda do aviao)
  3. ASIL (Automotive Safety Integrity Level): padrao ISO 26262, usado em automotivo. Vai de ASIL A (menos critico) a ASIL D (mais critico — freio, direcao)

O nivel de criticidade define tudo: quantos testes precisa, que tipo de cobertura, quantos revisores independentes, se precisa verificacao formal. Software DAL A (aviacao) pode custar ate 100x mais por linha de codigo que software comercial.

As normas que regem cada industria

Cada dominio tem sua norma regulatoria. Nao sao opcionais — se voce quer colocar software dentro de um aviao, dispositivo medico ou carro, precisa seguir a norma correspondente. Sem certificacao, sem produto no mercado.

DO-178C (Aviacao)

Padrao da RTCA reconhecido pela FAA (EUA) e EASA (Europa). Rege todo software embarcado em aeronaves.

+ Prós

  • • 5 niveis de criticidade (DAL A-E) com requisitos proporcionais
  • • MC/DC coverage obrigatorio no nivel mais critico
  • • Rastreabilidade completa: requisito -> design -> codigo -> teste
  • • Suplementos pra model-based dev (DO-331) e verificacao formal (DO-333)

− Contras

  • • Custo de certificacao extremamente alto
  • • Processo longo — anos pra certificar software complexo
  • • Documentacao extensa obrigatoria em todos os niveis
  • • Mudancas apos certificacao exigem re-certificacao

IEC 62304 (Medicina)

Padrao pra software de dispositivos medicos. Reconhecido pela FDA (EUA) e CE (Europa).

+ Prós

  • • 3 classes de risco (A, B, C) com requisitos escalados
  • • Integracao com processo de gestao de riscos (ISO 14971)
  • • Aceita software SOUP (de prateleira) com analise de risco adequada
  • • Menos rigido que DO-178C — mais acessivel pra startups medtech

− Contras

  • • Requer sistema de gestao de qualidade (ISO 13485)
  • • Rastreabilidade de bug tracking e obrigatoria
  • • Atualizacoes de software exigem re-validacao
  • • Recall e possivel se bug for descoberto apos lancamento

ISO 26262 (Automotivo)

Padrao pra seguranca funcional em veiculos. Obrigatorio pra todos os fabricantes de automoveis.

+ Prós

  • • 4 niveis ASIL (A-D) com requisitos proporcionais
  • • Cobre todo o ciclo de vida: conceito, desenvolvimento, producao, operacao
  • • Aceita decomposicao de ASIL (dividir requisitos entre componentes)
  • • Forte enfase em analise de falhas (FMEA, FTA)

− Contras

  • • Ciclo de certificacao de 3-5 anos pra novo modelo
  • • Custo alto de ferramentas qualificadas
  • • Supply chain inteira precisa estar em conformidade
  • • Complexidade aumentou muito com software de conducao autonoma

MC/DC Coverage: o teste que ninguem faz

Voce provavelmente mede cobertura de testes por linhas (statement coverage) ou branches. Em software critico de aviacao, o padrao e MC/DC: Modified Condition/Decision Coverage.

MC/DC exige que cada condicao individual dentro de uma decisao demonstre, de forma independente, que pode afetar o resultado da decisao. Isso e muito mais rigoroso que branch coverage.

c
// Decisao: if (A && B || C)
// Branch coverage: 2 testes bastam (true e false)
// MC/DC precisa provar que CADA condicao afeta o resultado:
//
// Teste 1: A=true,  B=true,  C=false -> true  (baseline)
// Teste 2: A=false, B=true,  C=false -> false (A mudou resultado)
// Teste 3: A=true,  B=false, C=false -> false (B mudou resultado)
// Teste 4: A=false, B=false, C=true  -> true  (C mudou resultado)
//
// Precisa de N+1 testes onde N = numero de condicoes
// Pra uma decisao com 10 condicoes: 11 testes minimo
// Branch coverage: 2 testes. MC/DC: 11. Grande diferenca.

Na pratica, MC/DC forca voce a testar combinacoes que branch coverage ignora completamente. E justamente nessas combinacoes que os bugs criticos se escondem. O Boeing 737 MAX talvez tivesse pego o problema do MCAS se MC/DC tivesse sido aplicado com rigor na interacao entre sensor e atuador.

Verificacao Formal: prova matematica de que funciona

Testes provam a presenca de bugs — nunca a ausencia. Voce pode rodar um milhao de testes e ainda ter um caso de borda que nao testou. Verificacao formal e diferente: usa matematica pra provar que o software se comporta corretamente em TODOS os inputs possiveis.

Na pratica, verificacao formal e usada em componentes especificos, nao no sistema inteiro (seria caro demais). Exemplos: o microkernel seL4 foi formalmente verificado — provaram matematicamente que a implementacao C corresponde exatamente a especificacao. O driver de criptografia da Amazon s2n-tls usa verificacao formal com SAW.

  1. Model Checking: explora automaticamente todos os estados possiveis do sistema. Ferramentas: SPIN, CBMC, TLA+. Bom pra protocolos e maquinas de estado
  2. Theorem Proving: prova propriedades usando logica formal. Ferramentas: Coq, Isabelle/HOL, Lean. Mais poderoso mas exige especialista em logica formal
  3. SPARK/Ada: subconjunto de Ada com anotacoes de contrato que podem ser verificadas automaticamente. Usado em aviacao e defesa. O mais acessivel pra engenheiros que nao sao matematicos
  4. Abstract Interpretation: analisa o programa de forma aproximada mas sound — se diz que nao tem bug, realmente nao tem. Ferramentas: Astree (usado no Airbus A380), Polyspace

Voce pode usar TLA+ no seu projeto? Da pra sim. Leslie Lamport (criador do TLA+) projetou a linguagem pra engenheiros, nao pra matematicos. Amazon usa TLA+ pra modelar sistemas distribuidos como DynamoDB e S3. Nao precisa verificar formalmente cada linha de codigo — basta modelar os componentes mais criticos.

Mutation Testing: testando os testes

100% de code coverage nao significa que seus testes sao bons. Significa que cada linha foi executada — nao que cada linha foi verificada. Mutation testing resolve isso: ele modifica seu codigo de proposito e verifica se seus testes detectam a mudanca.

O conceito e simples: troque == por !=, + por -, true por false. Se nenhum teste falhar com essa mudanca, seus testes nao estao verificando aquele comportamento. A mutacao 'sobreviveu' — e sinal de gap nos testes.

javascript
// Codigo original
function desconto(preco, percentual) {
  if (percentual > 50) return preco; // limite de 50%
  return preco * (1 - percentual / 100);
}

// Mutacao 1: trocar > por >=
if (percentual >= 50) return preco;
// Se nenhum teste falha, voce nao testa o caso percentual === 50

// Mutacao 2: trocar - por +
return preco * (1 + percentual / 100);
// Se nenhum teste falha, voce nao verifica o resultado do calculo

// Mutacao 3: remover o if
return preco * (1 - percentual / 100);
// Se nenhum teste falha, voce nao testa o limite de 50%

Em software critico, mutation testing e usado pra validar que a suite de testes e boa o suficiente. No seu projeto, vale rodar periodicamente pra encontrar gaps na cobertura que statement coverage nao revela.

Fault Injection: quebrando de proposito

Fault injection e a pratica de introduzir falhas no sistema de proposito pra ver como ele reage. E o oposto de teste funcional: em vez de verificar se funciona, verifica o que acontece quando nao funciona.

Na aviacao, fault injection e obrigatorio. O sistema precisa provar que consegue operar com falhas ativas — sensor defeituoso, link de comunicacao perdido, motor desligado. Em software comercial, Netflix popularizou o conceito com o Chaos Monkey (que desliga servidores aleatorios em producao).

  1. Fault injection de hardware: simula falha de sensor, memoria corrompida, perda de energia. Obrigatorio em aviacao e automotivo
  2. Fault injection de rede: latencia artificial, pacotes perdidos, conexao cortada. Ferramentas: tc (Linux), Toxiproxy, Chaos Monkey
  3. Fault injection de dependencia: API externa retorna erro 500, banco de dados fica lento, fila enche. Ferramentas: WireMock, LocalStack
  4. Fault injection de processo: kill no processo, OOM killer, disco cheio, CPU 100%. Ferramentas: stress-ng, Chaos Monkey, LitmusChaos

Da pra comecar simples: injete timeout na sua API externa e veja se o sistema reage de forma controlada. Se a resposta for 'nunca testamos isso', voce acabou de encontrar um ponto cego real do seu sistema.

Ferramentas de teste pra software critico

VectorCAST (Vector)

Suite completa de testes pra C/C++ e Ada. Geracao automatica de testes unitarios, MC/DC coverage, integracao com DO-178C e ISO 26262. Padrao na industria aeroespacial e automotiva.

LDRA Tool Suite

Analise estatica e dinamica pra software critico. Rastreabilidade de requisitos, cobertura MC/DC, certificada pra DO-178C, IEC 62304 e ISO 26262.

Polyspace (MathWorks)

Verificacao formal baseada em abstract interpretation. Prova ausencia de runtime errors em C/C++. Usado no Airbus e em sistemas automotivos.

TLA+ / PlusCal

Linguagem de especificacao formal criada por Leslie Lamport. Modela e verifica sistemas concorrentes. Usado pela Amazon pra DynamoDB, S3 e Lambda. Gratis e open-source.

Stryker / PIT / mutmut

Frameworks de mutation testing. Stryker (JS/TS/.NET), PIT (Java), mutmut (Python). Testam a qualidade dos seus testes. Open-source.

Chaos Monkey / LitmusChaos

Fault injection em producao e staging. Chaos Monkey (Netflix, AWS). LitmusChaos (Kubernetes-native, CNCF). Testam resiliencia real do sistema.

O custo de testar software critico

Tudo tem preco, e teste de software critico e caro. Muito caro. Mas a alternativa e mais cara ainda.

Custo por nivel de criticidade (aviacao)

DAL E (sem impacto): custo similar a software comercial. ~US$ 30-50 por linha de codigo

DAL D (menor): ~US$ 150-250 por linha. Testes basicos e documentacao

DAL C (maior): ~US$ 500-1.000 por linha. Statement coverage, revisao formal

DAL B (perigoso): ~US$ 2.000-5.000 por linha. Decision coverage, revisao independente

DAL A (catastrofico): ~US$ 5.000-25.000 por linha. MC/DC, verificacao formal, multiplos revisores independentes

Pra colocar em perspectiva: uma aplicacao DAL A com 100.000 linhas de codigo pode custar entre US$ 500 milhoes e US$ 2.5 bilhoes pra desenvolver e certificar. E por isso que a industria reutiliza codigo certificado sempre que possivel (e por isso que o Ariane 5 reutilizou codigo do Ariane 4 — so que sem re-validar as premissas).

O que devs comuns aprendem com safety-critical

Voce nao precisa certificar seu SaaS como DO-178C DAL A. Mas varias praticas de software critico melhoram qualquer projeto. Aqui vai o que faz sentido adotar:

Praticas de safety-critical que voce pode copiar

  • Mutation testing periodico: rode Stryker ou PIT uma vez por sprint pra encontrar gaps nos testes
  • Fault injection basica: teste o que acontece quando a API externa retorna erro ou timeout
  • Fail-safe design: quando seu sistema falha, ele falha de forma segura ou perigosa?
  • Rastreabilidade: cada teste deve mapear pra um requisito. Se nao sabe por que o teste existe, ele provavelmente nao testa nada util
  • Checklist de review sistematico: pare de fazer review intuitivo. Use checklist. Todo item, todo PR
  • Margem de seguranca nos tipos: use int64 onde int32 'bastaria'. Use timeout generoso. A margem e o que te salva quando a premissa esta errada
  • Teste de borda: 0, -1, null, MAX, string vazia, lista vazia, timestamp zero. Se voce nao testa, nao funciona
  • Post-mortem sem culpa: quando algo quebra, investigue o processo, nao a pessoa. O objetivo e que o mesmo bug nao aconteca de novo

Nenhuma dessas praticas e cara ou complicada. O dificil e ter a disciplina de fazer sempre. Mas se a industria que protege vidas usa essas praticas, provavelmente fazem sentido pro seu projeto tambem.

Perguntas frequentes

Preciso de certificacao pra vender software medico?

Sim. Nos EUA, a FDA regula software de dispositivo medico sob a IEC 62304. Na Europa, precisa de marcacao CE. A classificacao de risco (Classe I, II ou III) determina o rigor do processo. Software que faz diagnostico ou controla tratamento e Classe II ou III e exige aprovacao pre-mercado.

TLA+ e viavel pra time pequeno?

Sim. TLA+ nao e pra verificar todo o codigo — e pra modelar a parte mais critica do sistema. Um protocolo de consenso, uma maquina de estados complexa, uma logica de deploy. Amazon usa TLA+ com times de 2-4 pessoas modelando componentes especificos. O investimento de aprendizado e de umas 2-4 semanas.

Chaos engineering vale a pena pra startup?

Depende. Se seus clientes toleram downtime, talvez nao seja prioridade. Se seu sistema precisa de alta disponibilidade (fintech, saude, infraestrutura), comecar com fault injection basica cedo evita surpresas depois. Comece simples: teste o que acontece quando o banco cai e quando a API de pagamento retorna timeout.

Perguntas frequentes

O que e um safety-critical system?

E qualquer sistema cuja falha pode causar morte, lesao grave, dano ambiental significativo ou perda financeira catastrofica. Exemplos incluem software de aviacao, dispositivos medicos, sistemas automotivos (freios, airbags), usinas nucleares e sistemas de defesa. Cada dominio tem normas regulatorias especificas.

O que e MC/DC coverage?

Modified Condition/Decision Coverage (MC/DC) e uma metrica de teste que exige que cada condicao individual dentro de uma decisao demonstre afetar o resultado da decisao de forma independente. E obrigatorio para software de aviacao no nivel mais critico (DAL A) segundo o DO-178C. E muito mais rigoroso que statement ou branch coverage.

Quanto custa desenvolver software safety-critical?

O custo varia enormemente por nivel de criticidade. Software DAL A (aviacao, mais critico) pode custar ate 100x mais por linha de codigo que software comercial. Software DAL C pode custar 20x mais. A maior parte do custo extra vem de documentacao, verificacao, testes exaustivos e processos de certificacao.

O que um dev comum pode aprender com safety-critical systems?

Varias praticas se aplicam a software comercial: testes de mutacao pra medir qualidade dos testes, fault injection pra testar resiliencia, checklist de review sistematico, rastreabilidade entre requisitos e testes, e fail-safe design (seu sistema falha de forma segura ou perigosa?). Nao precisa aplicar tudo — mas cada pratica adotada melhora a confiabilidade.

O que sao safety-critical systems

Safety-critical system e qualquer sistema cuja falha pode resultar em morte, lesao grave, dano ambiental significativo ou perda economica catastrofica. A classificacao nao depende da complexidade do software — depende da consequencia da falha. Cada industria tem sua escala de criticidade. Os nomes mudam mas o conceito e o mesmo: quanto mais grave a consequencia da falha, mais rigoroso o processo de desenvolvimento. O nivel de criticidade define tudo: quantos testes precisa, que tipo de cobertura, quantos revisores independentes, se precisa verificacao formal. Software DAL A (aviacao) pode custar ate 100x mais por linha de codigo que software comercial.

O que devs comuns aprendem com safety-critical

Voce nao precisa certificar seu SaaS como DO-178C DAL A. Mas varias praticas de software critico melhoram qualquer projeto. Aqui vai o que faz sentido adotar: Nenhuma dessas praticas e cara ou complicada. O dificil e ter a disciplina de fazer sempre. Mas se a industria que protege vidas usa essas praticas, provavelmente fazem sentido pro seu projeto tambem.