Algo está te incomodando?
(antithesis.com)- A Antithesis aplica o teste autônomo determinístico que funcionou na FoundationDB a software em geral, com a proposta de transformar bugs difíceis de reproduzir em sistemas distribuídos em problemas repetíveis
- A FoundationDB criou uma simulação de thread única e processo único antes de implementar o banco de dados, e conseguia reexecutar situações raras de falha com a mesma semente aleatória
- Essa abordagem transformou falhas não determinísticas como concorrência, latência e reordenação de rede, problemas de disco e falhas de máquina em alvos de teste; na FoundationDB, avalia-se que houve apenas 1 ou 2 bugs reportados por clientes em todo o período
- Para evitar exigir que software existente fosse reescrito do zero, a Antithesis criou um hipervisor que emula um computador determinístico e atualmente se concentra em testes de confiabilidade e tolerância a falhas para sistemas distribuídos
- Trabalhou com MongoDB, Ethereum Foundation e Palantir, e evoluiu de uma ferramenta para encontrar bugs raros para um serviço contínuo de testes que valida builds recentes sem parar
Antithesis, nascida da experiência com a FoundationDB
- A Antithesis passou mais de 5 anos sendo desenvolvida em modo stealth e então revelou uma plataforma baseada na experiência com testes determinísticos obtida na FoundationDB
- Antes do lançamento público, a empresa trabalhou em contratações, clientes iniciais e investidores, e o primeiro ponto central que apresentou foi uma forma de testar sistemas complexos de maneira repetível
O problema de validação mais difícil em bancos de dados distribuídos
- Em 2010, a FoundationDB começou a construir um banco de dados distribuído escalável e tolerante a falhas com suporte a transações ACID
- Na época, o Spanner ainda não havia sido divulgado, e muita gente entendia mal o teorema CAP como se consistência forte e alta disponibilidade jamais pudessem coexistir
- A maior dificuldade não era o banco de dados em si, mas como testar esse tipo de sistema e ganhar confiança na sua correção
Os “desconhecidos desconhecidos” que os testes tradicionais deixam passar
- Software precisa lidar também com situações que o desenvolvedor não imaginou antes, mas testes comuns são fortes em validar casos já previstos
- Se um caso foi previsto a ponto de virar teste, é bem provável que o código também tenha sido escrito para lidar com ele
- Por isso, testes tradicionais são úteis para evitar regressões, mas fracos para capturar falhas inesperadas causadas por usuários reais e ambientes de produção
- Em sistemas de armazenamento distribuído, esse problema fica ainda maior
- Há concorrência ao mesmo tempo dentro das máquinas e entre máquinas
- A rede pode introduzir latência e reordenação de pacotes
- As causas de falha vão de disco, falha de máquina e queda de energia a incêndio em data center e erro humano
- Se um bug crítico depende da ordem de eventos entre várias máquinas, ele pode ser difícil de reproduzir mesmo depois de descoberto
A simulação determinística da FoundationDB
- Antes de escrever o banco de dados, a equipe da FoundationDB criou primeiro uma simulação de rede totalmente determinística e orientada a eventos
- Todo o cluster era simulado dentro de uma aplicação de thread única e processo único, executada com o mesmo gerador de números aleatórios
- No cluster virtual, era possível injetar falhas de rede, derrubar máquinas e repetir várias situações anormais
- Quando uma execução encontrava um bug de lógica da aplicação, era possível repetir a mesma sequência de eventos com a mesma semente aleatória
- Isso permitia rastrear até bugs muito raros, adicionando logs ou repetindo procedimentos de depuração
- Uma apresentação relacionada foi feita na Strangeloop de 2014, e o vídeo pode ser visto aqui
Como os testes mudaram a velocidade de desenvolvimento
- Na FoundationDB, avalia-se que houve apenas 1 ou 2 bugs reportados por clientes em toda a história da empresa
- Kyle Kingsbury, o “aphyr”, relatou que nem chegou a testar a FoundationDB com o Jepsen porque não havia nada a encontrar
- Quando os testes passaram a revelar bugs novos imediatamente, a forma de programar da equipe também mudou
- Compiladores e sistemas de tipos fortes trazem confiança contra certos tipos de bugs, mas isso é diferente de executar o software real em milhares de situações inesperadas
- Com base nessa confiança, a equipe da FoundationDB fez mudanças grandes
- Removeu todas as dependências, incluindo o Zookeeper, e escreveu uma implementação própria de Paxos em pouco tempo; essa implementação está incluída no artigo da FoundationDB
- Reescreveu todo o subsistema de processamento de transações para torná-lo mais rápido e mais escalável
- O maior efeito não foi apenas melhorar a estabilidade do banco de dados, mas dar a uma pequena equipe de engenharia a produtividade de um time 50 vezes maior
O vazio exposto após a aquisição pela Apple
- A Apple adquiriu a FoundationDB em 2015 e a usou como base da “cloud infrastructure” da empresa
- Alguns anos depois, a FoundationDB foi lançada como open source
- Mesmo depois de membros da equipe da FoundationDB se espalharem por outras grandes empresas de tecnologia, essas organizações não tinham testes de simulação determinística no estilo FoundationDB
- Como era difícil prever impactos não intencionais no sistema, mudanças em sistemas de backend avançavam devagar, e diagnosticar e corrigir bugs de produção consumia meses do tempo de engenheiros muito experientes
- Em 2018, junto com Dave Scherer, foi criada a Antithesis com o objetivo de levar o teste autônomo determinístico no estilo FoundationDB a outras equipes
Como tornar software existente determinístico
- A FoundationDB era um projeto greenfield concebido desde o início para ser testado dessa forma, e também podia remover dependências
- Software comum cria threads, consulta o tempo, pede valores aleatórios ao kernel e se comunica pela rede com outros softwares
- Como uma metodologia de desenvolvimento que exigisse reescrever todo o software do zero dificilmente seria amplamente adotada, a Antithesis escreveu um hipervisor que emula um computador determinístico
- Como resultado, o software executado dentro desse hipervisor pode ser colocado em um ambiente de execução determinístico
- Esse processo inclui lidar com comportamentos de baixo nível, como a extended page table de CPUs Intel
- O problema de encontrar violações de propriedades no espaço de estados de programas arbitrários é ainda mais difícil do que o problema da parada, e pode haver propriedades de teste incomputáveis mesmo que existisse um oráculo da parada para todos os programas
A plataforma atual e casos de clientes
- A plataforma da Antithesis tem como objetivo receber o software do usuário, encontrar bugs e garantir que os bugs encontrados possam sempre ser reproduzidos
- Ela busca manter a reprodutibilidade até em casos complexos em que vários serviços se comunicam pela rede
- Depois de encontrar um bug, é possível aplicar recursos poderosos de depuração
- No longo prazo, foi projetada para encontrar vários tipos de bugs em diversos tipos de software, mas no momento se concentra em testes de confiabilidade e tolerância a falhas em sistemas distribuídos, área em que já tem experiência
- Nos últimos anos, a empresa trabalhou com equipes de engenharia que operam sistemas grandes e complexos, nos quais confiabilidade é crítica
- Trabalhou por vários anos com a MongoDB para ajudar a testar o core server software e o mecanismo de armazenamento WiredTiger
- Com a Ethereum Foundation, trabalhou a partir de cerca de um ano antes do Merge para apoiar os testes do Merge e continua colaborando até hoje
- Também trabalha com a Palantir
De ferramenta para bugs raros a serviço contínuo de testes
- Os primeiros clientes usavam a Antithesis como uma espécie de ferramenta de forças especiais para descobrir e reproduzir os bugs mais difíceis e mais perigosos
- À medida que a plataforma amadureceu e se tornou mais interativa, ela se transformou em um serviço contínuo que testa continuamente os builds mais recentes
- O objetivo é reduzir o tempo entre o momento em que um bug é introduzido e o momento em que ele é descoberto
- Durante o desenvolvimento da FoundationDB, essa abordagem tornou o diagnóstico e a correção de bugs muito mais fáceis, além de melhorar a eficiência e a qualidade do software
- A Antithesis quer conversar com organizações que operam sistemas distribuídos e valorizam confiabilidade e produtividade de engenharia
- Para quem quer trabalhar com problemas difíceis, a empresa indica suas vagas
1 comentários
Opiniões no Hacker News
Tenho a impressão de que a expressão “lendário desenvolvedor 10x” foi distorcida para significar alguém que trabalha 15 horas por dia, 6,5 dias por semana, até sofrer burnout.
A produtividade realmente 10x, ou até 50x, vem de pessoas que implementam algo que quase ninguém achava possível ou sequer entendia, permitindo criar software funcional em muito menos tempo.
Gestores muitas vezes prestam mais atenção em quem faz 8 horas de trabalho ao longo de 12 horas do que em quem termina o mesmo trabalho em 8.
Além disso, tentativas de sair do “normal” não são vistas com bons olhos, e não há tempo no cronograma para melhorar processos; então, em um contexto em que se acha que basta carregar os baldes mais rápido, criar um carrinho de mão acaba sendo desencorajado.
Por isso engenheiros 10x existem. Aos 30 anos, eles não têm 10 anos, mas algo em torno de 20 anos de experiência em programação.
Também têm muito mais experiência profissional. Mesmo que aos 15 anos comecem com bicos estranhos, ajudando parentes de vez em quando, por volta dos 18 entram em uma empresa profissional e trabalham em paralelo aos estudos de ciência da computação.
Pelo menos era assim antigamente. De 2004 até mais ou menos 2018 isso era real, mas não sei se ainda é possível no ambiente de contratação atual.
Para que engenheiros 10x existam, bastam alguns exemplos. Parece que, em geral, todos concordam que são raros, e um exemplo publicamente visível de engenheiro 10x é esta pessoa. Ele jamais diria isso de si mesmo, mas meu palpite é que é um engenheiro 10x: https://bellard.org/
Se você discorda, fico curioso para saber em que ponto vê diferença. Eu sou apenas alguém tocando uma parte, como na história dos cegos e o elefante, e não afirmo enxergar o quadro completo.
Um desenvolvedor exército de uma pessoa só, que faz tudo sozinho, não se encaixa bem em equipes nas quais o trabalho é padronizado, fragmentado e distribuído.
Essas pessoas se dão melhor trabalhando em seus próprios projetos, sem colegas ou gestores atrapalhando, mas a maioria dos empregos não é assim.
Ao fazer parte de uma equipe, por mais brilhante que você seja, não dá para fazer coisas demais sozinho; no fim, você acaba desacelerando ao lidar com problemas criados por colegas mais lentos ou mais fracos, ou por questões de gestão. Por isso, mesmo com uma estrela no time, a equipe acaba se movendo no ritmo do menor denominador comum.
Também ajuda o fato de estarmos criando ferramentas internas e de estarmos muito próximos do processo e dos stakeholders.
“Hmm, existe outra forma de alcançar isso” é o que corresponde a 10x; a questão central não é fazer mais rápido.
Talvez seja o melhor texto de apresentação que já li até agora.
Ele estabelece bem a base de quem são as pessoas e o que elas construíram, e explica que o que estão construindo agora é consequência do que construíram antes.
Dá a sensação de que eles querem resolver esse problema para todo mundo, aparentemente porque já vivenciaram por conta própria o quanto a solução é boa.
Em seguida, também mostram equipes que já a usaram, com nomes bem grandes que têm sistemas complexos.
Tudo isso é embalado em um bom texto que funciona bem para desenvolvedores e fundadores, e a landing page também é excelente.
Eu queria ver alguns casos de uso e exemplos reais.
Em vez disso, eles listaram nomes de algumas grandes empresas, afirmaram ser um produto inovador que funciona como mágica e depois incluíram buzzwords típicas como “programador 10x” e “stealth mode”. Divulgar nomes de clientes e, ao mesmo tempo, falar em stealth mode não faz sentido.
Como oferece um modo de vida, de pensamento e de execução que eu nunca experimentei, faz com que eu queira essa solução.
O post linkado é 3/4 história e justificativa antes de finalmente dizer o que eles de fato construíram.
Parece aqueles blogs de receita irritantes em que você quer fazer panquecas veganas, mas primeiro precisa ler a história da infância do autor.
É uma ótima apresentação, e não quero parecer negativo, mas sinto que uma frase como “encontramos todos os bugs” só pode ser verdadeira se a definição de bug for bem restrita
Os bugs mais maliciosos e difíceis de encontrar que já encontrei até hoje não estavam tanto em cair em um estado de erro, mas em torno da lógica de negócios da aplicação
Por exemplo, o que deveria ser mostrado na página de transações recentes do cliente quando o banco de dados registra uma transação concluída do cliente, mas não há nenhum item comprado concluído?
Nesses casos, implementar “algo aparece e não dá crash” é muito diferente de garantir que a escolha realmente faça sentido no contexto das outras escolhas em toda a stack
No caso de um banco de dados, também há problemas como “o query planner cria um plano extremamente ineficiente para este caso de borda”
Esse tipo de coisa é impossível de detectar automaticamente. Não é uma questão de o programa chegar a um estado de erro, mas de entender, em primeiro lugar, o que é ‘correto’ na aplicação
Talvez eu esteja colocando o padrão de bug alto demais, mas imaginar zero bugs é diferente de construir software no mundo real. Ainda assim, eu aceitaria zero erros de runtime
Dito isso, é verdade que o FoundationDB é realmente famoso por ter elevado o estado da arte das práticas de teste: https://apple.github.io/foundationdb/testing.html
Normalmente isso soaria arrogante ou excessivamente confiante, mas aqui eles de fato chegaram muito perto de zero bugs
Claro que não dá para provar uma negativa, mas o fato de terem chegado a esse estado de “tudo verde” dava muita confiança de que estavam construindo sobre uma base sólida, e com o tempo ficou claro que era mesmo o caso
Problemas em torno da lógica de negócios não são falhas do sistema; o sistema funcionou conforme a especificação, e a especificação não era abrangente o bastante, então agora é questão de iterar e melhorar
Claro que muito software tem documentação insuficiente, e isso é um bug de documentação
Ainda assim, essa definição é boa porque, mesmo quando a documentação é incompleta, ela obriga a perguntar: “vamos mesmo documentar este comportamento, ou vamos mudar o comportamento e documentar isso?”
Pelo menos para mim, fica mais difícil varrer comportamentos estranhos para debaixo do tapete
Desde que conheci essa área pelo guia de simulação do
sledhttps://sled.rs/simulation.html, fiquei extremamente interessado. O texto mostra em linhas gerais como o FoundationDB faz issoNo momento, estou escrevendo nossos serviços no trabalho para que rodem sobre o
madsimhttps://github.com/madsim-rs/madsim?tab=readme-ov-file#madsim, tentando introduzir uma abordagem de testes semelhanteAssim, podemos continuar escrevendo serviços no estilo async/await com tokio, mas nos testes substituir todas as fontes de não determinismo — incluindo dependências que chamam o sistema operacional — por um executor determinístico. Funciona de forma bem fluida
O autor deste texto não exagera ao dizer que o custo inicial é enorme. Lidar com todas as possíveis fontes de não determinismo e reescrever serviços para que sejam testáveis e no estilo sans-IO https://sans-io.readthedocs.io/ exige muito esforço de engenharia
Mas, quando o sistema está montado, é difícil explicar em palavras a confiança que você passa a sentir no código. Combinado com ferramentas como quickcheck https://github.com/BurntSushi/quickcheck?tab=readme-ov-file#quickcheck, dá para testar centenas de milhares de casos sutis de falha envolvendo entrada e saída, ordem de eventos, timeouts, perda de pacotes, falhas no sistema de arquivos etc.
Esse tipo de teste é uma ferramenta muito poderosa para se ter na caixa de ferramentas, se você tiver paciência e persistência para investir
O próprio Antithesis também parece muito legal. Levar testes determinísticos para uma camada abaixo do sistema operacional é impressionante, e parece que permitirá testar sistemas inteiros sem precisar montar manualmente um harness toda vez. Estou ansioso para experimentar
Boa parte da complexidade que vi nesses sistemas vem do fato de que chamadas de “funções” são assíncronas, dependem do sistema operacional, podem ser executadas em algum momento ou nunca, retornam pacotes de strings que precisam ser parseados para voltar ao sistema de tipos estático, e têm seus próprios modos de falha
A tarefa aparentemente simples de abstrair lógica em componentes nomeados, isto é, funções, se torna extremamente complexa
Se a lógica ficar no mesmo processo e você simplesmente chamar funções, não precisa testar as falhas sutis mencionadas
Um monólito nem sempre é a melhor escolha nem a escolha correta, mas sou muito cético quanto a saber se a moda atual de arquiteturas de software baseadas em serviços é justificada e se a recompensa compensa
Também fico curioso se há empresas que usam Rust desenvolvendo dessa forma
Além disso, o TigerBeetle também é um produto escrito dessa maneira
madsimou testes de simulação determinística para aplicações JavaO texto é realmente divertido
Conseguir dizer “programar nesse estado é como viver cercado por um campo de força que protege contra todos os males… como havia bugs, removemos todas as dependências, incluindo o Zookeeper, e em pouquíssimo tempo escrevemos nossa própria implementação de Paxos, que não tinha bugs”, e ainda sustentar isso com evidências, parece algo realmente incrível
Nesse livro, o autor diz que era tão frustrante ter de depurar software alheio ao tentar resolver seu próprio problema por causa de bugs em pacotes de software numérico que, com exceção de pacotes de álgebra linear, ele normalmente escrevia o seu próprio
Ele via como ainda mais problemático o fato de que pacotes escondem falhas na formulação do problema. Se você coloca um conjunto de equações em um solver, mesmo que o condicionamento seja ruim ou haja singularidades inesperadas e a resposta se desvie da realidade física, em geral ele entrega uma solução sem reclamar; e, quando isso fica enterrado dentro de um programa grande, pode levar você a ignorar essa possibilidade
Mesmo ao detectar um comportamento suspeito, é difícil entrar no pacote e investigar o problema, então no fim você precisa reprogramá-lo por conta própria; e, se tivesse feito isso desde o início, provavelmente teria se aprofundado na realidade do problema e eliminado confusões lógicas com antecedência
No fim, fazer isso ou não depende de quão rigoroso você é, de quão rigorosa é uma dependência específica e de quanto tempo você tem. Eu não escreveria meu próprio banco de dados, porque é algo complexo demais e há muitas opções bem testadas. Por outro lado, se você usa só parte das funcionalidades de um pacote pequeno com testes fracos, pode fazer sentido criar você mesmo
Só não estou dizendo que minha especificação não tem bugs
Três pensamentos me vêm à cabeça
Primeiro, é uma ótima ideia no momento certo. Observando o sentimento dos desenvolvedores em relação a fuzzers, tipagem estática, segurança de memória, protocolos padronizados, contêineres etc., parece que as pessoas finalmente estão perdendo a paciência com software instável
Segundo, parece mirar um nicho de mercado. US$ 2 por CPU por hora, US$ 7.000 por CPU por ano com reserva, sem camada gratuita para hobby ou software livre e open source, e até o teste ou a compra só estão disponíveis mediante contato. É um modelo de negócio doloroso, mas válido. Ainda assim, é uma pena que não busque o maior impacto positivo possível
Terceiro, a qualidade do texto e da documentação é alta, e gosto muito de haver na documentação frases como “se um bug for encontrado em produção ou por um cliente, vocês devem exigir explicações de nós”
É assim que se conquista a simpatia de desenvolvedores. Isso me lembra a Mullvad, que ainda recomendo às pessoas mesmo depois de já ter me decepcionado
Comentei algo relacionado em https://news.ycombinator.com/item?id=39358526. Para referência, sou cofundador da Antithesis
O hardware também pode começar a adicionar recursos para dar suporte a isso, e daqui a 30 anos talvez seja simplesmente assim que a computação funcione
Mas, antes que os pioneiros realmente disseminem isso, eles precisam recuperar o custo das flechas que tomaram primeiro. Isso deve ser visto não como um evento isolado, mas como o início de um processo
Pela documentação, os bugs que esta plataforma foi projetada para encontrar são aqueles casos complicados, “impossíveis de reproduzir”, que só ocorrem raramente em produção
A maioria das equipes precisa corrigir problemas muito maiores e bugs óbvios. Na verdade, hoje a maior parte do software em produção mal tem testes unitários
Fico curioso para saber como os custos se multiplicam em casos de uso reais
Conheci a Antithesis na Strangeloop deste ano e conversei com a equipe; mesmo comparando com o estado da arte em injeção automática de falhas que eu acompanhava quando trabalhava na Amazon, considero este produto um salto enorme em relação a muitos sistemas de verificação formal usados hoje
De fato, pude acompanhar o processo de rastreamento de um bug em uma issue que eles encontraram no Apache Spark Streaming. A julgar pela documentação, eles encontraram um erro de correção sutil e desagradável em uma operação comum, um caso de borda de baixa visibilidade que teria sido uma dor de cabeça por anos
No fim, a conclusão foi que a documentação estava errada, mas, depois de ver esse processo, é difícil imaginar o quanto uma ferramenta como a Antithesis pode se tornar importante dentro de empresas que constroem sistemas distribuídos
Espero que em breve saia um post de blog entrando fundo nos detalhes técnicos. Gostaria de ouvir como eles chegaram à abordagem atual
Não quero entrar direto no ciclo de expectativas infladas, mas isso soa como o Santo Graal. Você usa a aplicação existente como está e, supondo que ela esteja conteinerizada, não basta verificar propriedades em cima dela?
O ponto em que sempre se travava era a base da máquina, isto é, CPU e sistema operacional não determinísticos
Como recriar toda a pilha vertical de computação é praticamente impossível, eles contornaram o problema criando um simulador determinístico de alta fidelidade
Ainda assim, fico curioso sobre como verificam a equivalência entre o simulador e o sistema operacional existente. Parece uma tarefa nada trivial. Mesmo assim, a ideia me convenceu bastante
Em seguida, executam os testes injetando todos os tipos de falhas: falhas do sistema operacional, problemas de rede, condições de corrida e de temporização, problemas no gerador de números aleatórios etc.
É muito provável que hoje esta seja a única forma prática de testar essas coisas de maneira confiável, mas ainda é necessário escrever todos os testes e definir o estado da aplicação
Dizem que é uma “plataforma que recebe software e caça bugs nele”, mas então, na prática, o que é isso?
Parece um serviço em nuvem que executa testes de integração. Pelo visto, você precisa descobrir como fazer deploy nesse ambiente especial e ainda precisa escrever testes de integração usando bibliotecas especiais
Mas, mesmo depois de fazer toda essa refatoração de integração, não entendo como ela encontraria bugs reais que meus próprios testes de integração, no meu ambiente, já não teriam encontrado
Dito isso, o Antithesis não exige testes manuais nem a escrita de testes de integração
Você precisa empacotar seu sistema de software em contêineres, o que é relativamente simples, e depois escrever uma carga de trabalho que imite o funcionamento normal do sistema. Por exemplo, em um site de e-commerce, isso seria consultar produtos, adicionar ao carrinho, fazer o pagamento etc.
Com base nisso, o Antithesis começa a testar o software executando a carga de trabalho, alterando entradas e injetando falhas, procurando violações de propriedades de teste
Mais de 60 propriedades de teste vêm prontas, como crashes, falta de memória etc. Para expor mais problemas específicos do seu sistema, você também pode — e, na prática, deve — definir propriedades personalizadas
À medida que os testes rodam, as violações de propriedades são relatadas e vêm com muitas informações úteis de depuração. Execuções de teste especialmente interessantes podem ser analisadas mais a fundo, porque é possível rebobiná-las, alterar entradas, capturar artefatos, adicionar logs etc.
Até agora, isso é o que sei. Suponho que haja alguma forma de fuzzing e análise estática, ou uma definição das ações que o software pode realizar
Sinceramente, parece haver muita sobreposição com o que a linguagem Vale tenta resolver: https://vale.dev/
Mas, em vez de criar uma nova linguagem para que o software novo já nasça basicamente nesse estado, parece que o foco é aproximar software existente desse estado
Usando o hipervisor, eles mudam a semente aleatória, fazem requisições HTTP falharem ou demorarem, cortam conexões entre servidores, mudam a ordem das respostas dos servidores e criam todo tipo de coisa que normalmente você não controla, mas que acontece no mundo real
Depois comparam com a resposta esperada da carga de trabalho para descobrir quais condições quebram o sistema
É por isso que vendem como contrato anual. A estrutura é pagar para manter sua carga de trabalho rodando o ano inteiro, tentando todo tipo de combinação de falhas
Fiquei bem animado e dei uma olhada rápida na documentação, mas não entendo bem como isso difere de testes unitários randomizados
Se você já tem um conjunto de testes unitários, isso não é 99% do trabalho? Entendi errado?
Essa foi a conclusão a que cheguei lendo a série de introdução da documentação, especialmente a seção Workloads https://antithesis.com/docs/getting_started/workload.html
A página How Antithesis Works pode responder como isso difere de simplesmente agrupar testes unitários: https://antithesis.com/docs/introduction/how_antithesis_works.html
Em resumo, testes unitários podem ajudar a compor a carga de trabalho, mas não são obrigatórios
Nós exploramos autonomamente os caminhos de execução do sistema de software introduzindo entradas diferentes, falhas etc., e descobrimos comportamentos que o autor dos testes unitários talvez não tivesse previsto
Se você escreveu um teste para uma função que faz uma chamada de rede e grava o resultado no disco, o teste falha se o código não souber lidar com casos como a chamada de rede falhar ou travar indefinidamente, o espaço em disco acabar, ou a energia cair logo antes de fechar o arquivo
Então sim, é isso mesmo, mas eles expandem o espaço que pode ser testado com a mesma facilidade de um teste unitário para um nível de complexidade muito mais interessante