Vamos nos aprofundar nos testes em Swift, conhecer os pontos fortes do XCTest e a nova e empolgante API SwiftTesting introduzida na WWDC24. Embora o XCTest continue sendo fundamental, ele enfrenta dificuldades com concorrência e personalização. Entra em cena o SwiftTesting, uma abordagem moderna que utiliza macros para simplificar o código e aprimorar a organização dos testes. Descubra como esses avanços estão transformando os testes, tornando-os mais eficientes e amigáveis para desenvolvedores no ecossistema em evolução do Swift.
O Framework mais utilizado
O XCTest é a principal API para testes unitários no ecossistema Apple. Originalmente escrito pela Apple em 1998 em Objective-C, foi integrado ao Xcode em 2013, fornecendo ferramentas para escrever e fazer asserções. Ainda funciona perfeitamente, apesar da evolução do Swift e da introdução de novas APIs incríveis.
Desafios com concorrência
Apesar das inúmeras melhorias no XCTest para facilitar o teste de concorrência, o Swift Testing agora oferece uma solução mais eficiente, proporcionando melhores ferramentas e executando testes em paralelo por padrão.
Desde a introdução da nova API de concorrência, os desenvolvedores têm experimentado diversas maneiras de escrever testes unitários usando esse framework. Às vezes, isso resulta em código repetitivo ou até mesmo em código que não faz muito sentido.
Um ótimo exemplo:
Mesmo que chamemos a função usando a palavra-chave await, o teste falhará porque, em teoria, precisamos esperar a tarefa ser concluída. Portanto, precisamos chamar a propriedade `.value`, que representa o resultado de uma tarefa após sua conclusão.
Customização e outros problemas
Há outros problemas, como a personalização. Atualmente, é difícil configurar um ambiente para os testes. Não há uma maneira eficaz de organizar os testes, e problemas de desempenho são comuns, já que o framework não oferece suporte robusto para paralelização e tarefas assíncronas. Depurar falhas nos testes sempre foi algo demorado e desafiador.
Swift Testing
A Apple introduziu uma API open-source inovadora que é ergonômica, moderna, expressiva e altamente personalizável. Esta nova API utiliza extensivamente macros para minimizar código repetitivo e permitir operações complexas com menos esforço.
Com a introdução da macro @Test, os desenvolvedores podem passar traits, permitindo a especificação de condições de tempo de execução.
A API aproveita macros para definir a estrutura dos testes, utilizando @Suite e @Test para organização. Essas macros, combinadas com os traits personalizáveis, oferecem uma experiência de teste completamente adaptável. Além disso, a macro #expect garante que as condições esperadas sejam validadas e quaisquer falhas sejam relatadas de forma eficaz.
Testes Parametrizados
Para cenários em que um teste deve ser executado com diferentes entradas, os testes parametrizados oferecem uma solução conveniente. Esses testes permitem a definição de uma coleção de valores de entrada que o teste pode iterar, garantindo que cada caso seja avaliado.

Fonte: https://developer.apple.com/documentation/testing/parameterizedtesting#Parameterize-over-the-cases-of-an-enumeration
Adicionando Tags
Você pode adicionar tags customizadas para categorizar, identificar ou filtrar um conjunto de testes.
Fonte: https://developer.apple.com/documentation/testing/addingtags#Add-a-tag
Configurando Comportamentos Personalizados
Ao utilizar traits, podemos definir comportamentos personalizados, como habilitar ou desabilitar testes, configurar timeouts, executar testes de forma serial ou em paralelo e adicionar anotações para associar testes a bugs. Além disso, podemos criar traits personalizados, realizar testes específicos para dispositivos ou limitar testes a versões específicas do sistema operacional para uma cobertura de testes mais direcionada.
Migrando para Swift Testing
A Apple projetou o Swift Testing para funcionar em conjunto com o XCTest, permitindo uma adoção gradual. Em vez de precisar substituir totalmente o XCTest, os desenvolvedores podem migrar seus testes lentamente, escrevendo novos testes com o Swift Testing enquanto mantêm seus antigos testes do XCTest.

Agrupando testes
Anteriormente, precisávamos usar uma classe que herdava de XCTestCase para agrupar testes. Agora, podemos usar uma struct, que é reconhecida como uma suíte. Além disso, para que uma função seja considerada uma função de teste, ela não precisa mais começar com “test”. A Apple aproveitou eficazmente as macros para alcançar isso.
Setup e Teardown
Executar código antes ou depois de cada teste agora é mais simples. Como nossa suíte é uma struct, podemos usar os métodos `init` e `deinit` para gerenciar a configuração e a desmontagem (setup e teardown).

Simplificando Asserções
As asserções nos testes em Swift foram redesenhadas para parecer mais naturais, permitindo que os desenvolvedores utilizem código Swift simples em vez de depender de funções especializadas. Isso elimina a necessidade de consultar constantemente as funções de teste, tornando o processo mais intuitivo.
Além disso, o relatório de resultados dos testes foi significativamente aprimorado. Em vez de feedbacks vagos ou pouco claros, o novo sistema fornece resultados de comparação (diffing) poderosos, facilitando a compreensão do motivo pelo qual um teste está falhando.
Esta tabela demonstra como podemos expressar nossas expectativas na nova API com base no XCTest.

Fonte: https://developer.apple.com/documentation/testing/migratingfromxctest
Aqui está como o resultado é exibido após uma falha de teste. Podemos expandir a comparação de falhas (failure diff), o que é um divisor de águas para nossa produtividade.

Swift Testing: Uma Visão Abrangente – Considerações Finais
Embora o XCTest tenha servido bem ao ecossistema Apple por anos, a API Swift Testing introduz uma abordagem nova e moderna para testes unitários. Com seu foco em simplicidade, flexibilidade e nas poderosas macros, o Swift Testing aborda muitas das limitações que os desenvolvedores enfrentavam com o XCTest, especialmente em relação à concorrência e personalização.
À medida que o Swift continua a evoluir, adotar o Swift Testing pode ajudar os desenvolvedores a simplificar seu processo de teste e criar um código mais sustentável e eficiente. Abraçar essas novas ferramentas garante que os testes em Swift acompanhem os rápidos avanços da linguagem.
Happy testing, and may all your bugs be shallow!