Testar IoT sem placa
O simulador que fala o mesmo protocolo — e como um projeto de hardware passa no CI.
Código de hardware costuma ser código sem teste, e a razão é sempre a mesma: o teste precisaria da placa, e o CI não tem placa. IoT.conectar_simulada resolve isso de um jeito específico — não é um dublê da API, é um dispositivo do outro lado do cabo.
adopt Arcane.IoT as IoT
placa := IoT.conectar_simulada("uno")
assert placa.info()["firmware"]["nome"] is "StandardFirmata.ino"
assert placa.info()["protocolo"] is "2.5"
placa.fechar()A diferença importa: o simulador recebe os bytes do Firmata e responde com os bytes que a placa responderia. O parser, a máquina de estados, a partição em sete bits, o sysex — tudo isso é exercitado. Um dublê que só implementasse escrever(pino, valor) não provaria nada sobre o protocolo, que é justamente onde estão os erros.
O simulador deixa PERGUNTAR e deixa MENTIR#
| Para | Método |
|---|---|
| perguntar o estado de um pino | placa.simulador.pino(13) |
| perguntar o modo declarado | placa.simulador.modo_do_pino(9) |
| perguntar a posição de um servo | placa.simulador.servo(3) |
| fingir um sensor | placa.simulador.definir_analogico(0, 733) |
| fingir um botão | placa.simulador.definir_digital(2, 1) |
| fingir um dispositivo I²C | placa.simulador.definir_i2c(0x68, 0x3B, […]) |
fingir um Firmata.sendString | placa.simulador.mandar_texto("…") |
Um teste de verdade, com `crucible`#
adopt Arcane.IoT as IoT
adopt Arcane.Crucible as Crucible
crucible "o termostato":
trial "liga o aquecedor quando esfria":
placa := IoT.conectar_simulada("uno")
placa.modo(7, "saida")
placa.modo(14, "analogico")
placa.relatar_analogico(0)
aquecedor := IoT.histerese(18, 21)
placa.simulador.definir_analogico(0, 300) // frio
sleep(120)
placa.escrever(7, aquecedor(IoT.tmp36(placa.analogico(0))))
expect placa.simulador.pino(7) is 1
placa.fechar()
trial "e nao bate o rele na soleira":
termostato := IoT.histerese(30, 28)
expect termostato(31) is yes
expect termostato(29) is yes
expect termostato(27) is no
Crucible.run()O que o simulador NÃO prova#
- Tempo de subida de um sinal, ruído de sensor, corrente, queda de tensão.
- O cabo caindo no meio de um sysex — o defeito mais chato do mundo real.
- O bootloader, o driver USB, o
avrdude. - Que o seu sensor está ligado nos pinos certos.
Por isso tests/test_iot.py tem duas provas que o simulador não dá: a camada serial é testada contra um PTY de verdade (um dispositivo tty do sistema), e os sketches gerados são compilados pelo `arduino-cli` de verdade. E há um teste de hardware que só roda quando alguém aponta uma placa:
$ DATAFORGE_ARDUINO=/dev/cu.usbmodem1101 python3 -m pytest tests/test_iot.py -k verdade