Diário de testes embebidos #2: testes reproduzíveis
Um resultado de teste só tem significado se souber o que mudou entre duas execuções. Veja como funciona a reprodutibilidade nos testes de sistemas embebidos: reinícios, estado do dispositivo, isolamento da rede e impressões digitais de cada execução.

Um resultado de teste só tem significado se souber o que mudou entre duas execuções.
Se um teste passa uma vez e falha na seguinte com o mesmo firmware, a causa pode estar noutro lado: no host, na rede, na alimentação, no estado do dispositivo ou nas condições físicas à volta da bancada. Enquanto não for possível repor todo o setup num estado conhecido, uma falha não aponta com segurança para o firmware. Diz apenas que alguma coisa mudou.
É assim que testar se transforma em depurar o laboratório em vez do produto.
Nos sistemas embebidos, reprodutibilidade significa conseguir repor a mesma combinação de firmware, ambiente do host, rede, alimentação, estado físico e dados de entrada, e obter o mesmo veredicto. Se o verde passa a vermelho, deve conseguir identificar a variável que mudou.
A maior parte do trabalho está em controlar o que muda sem ninguém dar por isso entre execuções.
Reinicie só o necessário
Um reinício não é uma operação única. Pode ser um ciclo de alimentação, um reboot por software, uma reposição de fábrica, uma regravação completa do firmware ou um novo aprovisionamento completo do dispositivo.
Cada passo repõe mais estado, mas também torna a execução mais lenta. Regravar o firmware tem outro custo: a memória flash tem um número limitado de ciclos de escrita e apagamento, e as escritas desnecessárias encurtam a sua vida útil.
A escolha certa é o reinício mais barato que repõe as condições iniciais de que o teste precisa.
Numa frota de dispositivos, há uma regra que faz muita diferença: não grave o firmware num dispositivo que já tem a versão pretendida. Verifique primeiro a versão instalada e grave apenas quando for diferente. Se os hosts de teste arrancam a partir de cartões SD, como acontece muitas vezes em frotas de Raspberry Pi, trate esses cartões como mais um componente de vida limitada. O netboot ou um disco em RAM podem ser melhor opção, quando o setup o permite.
O firmware é só uma parte do estado do dispositivo
Uma reposição de fábrica só limpa o estado que o fabricante decidiu limpar. As variáveis que quebram a reprodutibilidade estão muitas vezes noutro lado:
Segredos e emparelhamento: as chaves de bonding BLE, as credenciais Wi-Fi guardadas e os certificados aprovisionados podem fazer a execução seguinte começar noutro estado.
Tempo: o relógio de tempo real e a sincronização NTP contam quando o comportamento depende de marcas temporais, de prazos de expiração ou de eventos agendados.
Carga e temperatura: o nível da bateria e o histórico térmico podem afetar a gestão de energia, o comportamento do rádio e a temporização.
Configuração persistente e calibração: a NVRAM, as partições de configuração e os dados de calibração podem sobreviver ao reinício que o teste usa.
O host também muda. Os dispositivos USB voltam a ser enumerados, por isso /dev/ttyUSB0 pode apontar para outra placa depois de um reboot. Identifique os dispositivos pelo número de série ou por outra identidade estável. O caminho que o sistema operativo atribuiu primeiro não serve.
Os processos também podem reter adaptadores ou bloqueios. As concessões DHCP, as caches ARP e as regras da firewall podem levar estado de uma execução para a seguinte. Reinstalar a imagem do host antes de cada teste raramente é prático. Mas o ambiente tem de repor as partes que podem afetar o resultado.
Mantenha uma via de recuperação por hardware
O controlo por software não chega quando o dispositivo ou o sistema operativo deixam de responder. Um interruptor de alimentação controlável para cada dispositivo dá uma via de recuperação por hardware e uma sequência de arranque conhecida. Em geral, é uma placa de relés ou uma PDU gerida.
A própria alimentação também precisa de controlo. Uma quebra de tensão durante uma escrita pode corromper a flash e criar falhas intermitentes difíceis de diagnosticar. Por isso, vale a pena ter alimentação estável e uma UPS. Ligar uma frota inteira de uma só vez também pode gerar uma corrente de arranque capaz de fazer cair a linha de alimentação. Ligar os dispositivos em sequência evita que o mecanismo de recuperação se torne mais uma fonte de falhas.
Controle a rede e a ordem de arranque
Uma rede partilhada traz tráfego e estado que não pertencem ao teste. Com uma LAN de teste isolada e endereços previsíveis, é mais fácil saber que pacotes, serviços e dispositivos estiveram presentes numa execução.
A ordem dos eventos conta tanto quanto a rede. Muitos testes aparentemente instáveis são, na verdade, corridas no setup: o dispositivo arranca antes de o host estar à escuta, ou o teste começa antes de o dispositivo terminar o arranque.
Os atrasos fixos escondem este problema, não o resolvem. Substitua sleep 30 por uma verificação real de prontidão. Espere até o host abrir a ligação, o dispositivo responder e o serviço necessário estar operacional. Não espere apenas o tempo que, em princípio, devia chegar.
Registe a impressão digital de cada execução
Cada execução precisa de uma impressão digital: versão ou build do firmware, imagem do host, número de série do dispositivo, configuração relevante, setup de rede, carga, temperatura e os dados de entrada exatos do teste.
Este registo faz parte do resultado do teste. Sem ele, reproduzir uma falha obriga a adivinhar como estava a bancada nesse momento. Com ele, pode repor o ambiente, comparar uma execução falhada com uma bem-sucedida e encontrar a variável que mudou.
Onde isto nos deixa
É trabalho comum: confirmação da versão, interruptores de alimentação, identidades estáveis dos dispositivos, redes isoladas, verificações de prontidão e metadados das execuções. Numa frota, são peças a mais para gerir à mão com fiabilidade.
Por isso, o ambiente de testes tem de gerir o setup à volta do teste, além de executar o script. Deve repor o estado do host e do dispositivo, coordenar o arranque, verificar a prontidão e registar o que de facto correu.
Quando uma execução falha, as evidências devem apontar para o produto. Não o devem mandar de volta ao laboratório para descobrir que parte da bancada mudou.