Arquitetando Sign In with Apple de uma forma testável

Usar o SignInWithApple para logar em diversos aplicativos é incrível, mas como implementá-lo de uma forma testável?

Bianca Itiroko
iFood Tech
5 min readNov 11, 2020

--

Se você está aqui, provavelmente já conhece ou já ouviu falar da famigerada WWDC (WorldWide Developers Conference), certo?

Tudo bem se não também! Vou explicar brevemente.

A WWDC é uma conferência em que todas as novidades relacionadas às plataformas Apple são reveladas aos desenvolvedores. Nela são reunidas em torno de 5000 pessoas durante 5 dias com um cronograma que conta com diversas apresentações, sessões 1-a-1 com os engenheiros da própria Apple para tirar dúvidas e também sessões relacionadas à design. Além disso, todas as apresentações são gravadas e podem ser encontradas no site da Apple!

Na edição de 2019, eu e alguns Foodlovers estivemos por lá e acompanhamos de pertinho a feature de SignInWithApple saindo do forno!

Ela se trata de uma nova opção de autenticação baseada em uma conta Apple e, como todo usuário de iPhone já possui uma conta, esta opção oferece menos atrito no onboarding da sua aplicação — e claro, todas as features de privacidade e segurança que a Apple inclui em seus produtos (como autenticação dois fatores e etc). Um grande diferencial é permitir que o usuário escolha não compartilhar seu email com o app pra compartilhar um email falso no lugar que encaminhará as mensagens para o oficial.

Naquela época eu tinha menos de um ano de iFood e desde o começo de 2019 estava alocada no time de Account, então ainda estava aprendendo como as coisas eram feitas. Fiquei extremamente animada quando o SignInWithApple foi apresentado ao mundo e mais ainda com a ideia de implementarmos em nosso aplicativo!

Desde o início, havia sido anunciado que em algum momento a feature seria obrigatória para todos os aplicativos que já contassem com outras opções externas de autenticação, como por exemplo Facebook, Google etc. — o que era o nosso caso! Isso somado ao fato de ser uma feature incrível e que traria uma experiência mais rápida e fluída para nossos usuários entrarem na app, foi parte do meu argumento em porquê deveríamos priorizá-la em nosso cronograma.

Assim que os betas do Xcode e do iOS foram liberados, já começamos a testar e mapear os possíveis problemas que enfrentaríamos ao adaptar o projeto do iFood para o iOS 13. Todas as bibliotecas externas que usávamos precisavam estar adaptadas também e foi um dos principais problemas que tivemos.

Após adaptações aqui e ali, comecei a fazer POCs (proofs of concept ou provas de conceito) do SignInWithApple na nossa app.

Colocando a mão na massa!

Estruturamos o SignInWithApple seguindo a arquitetura VIP com alguns detalhes específicos para a parte que importaria diretamente o framework da Apple, o AuthenticationServices.

Sabendo que gostaríamos de isolar ao máximo o código dependente do framework, demos bastante atenção aos princípios do SOLID de inversão de dependência e de responsabilidade única ao desacoplar e concentrar o consumo do framework na menor quantidade de classes possível.

Utilizar essa abordagem nos trouxe alguns benefícios:

  • Manutenibilidade: no caso de atualizações e/ou mudanças no framework, poucas classes seriam afetadas e nenhum impacto em nossa lógica de negócios;
  • Testabilidade: maior facilidade para criar cenários para testes unitários por termos as dependências do framework isoladas e limitadas;
  • Rastreabilidade: facilidade para identificar a origem de comportamentos inesperados e descartar possíveis erros de lógica por má interpretação das respostas do framework.

Tudo certo e separadinho, agora é "só" testar né?!

Photo by Chris Ried on Unsplash

Se o peixe morre pela boca, nós desenvolvedores morremos pelo uso do "só" 😅

Adicionar testes à camada que acessa o framework de AuthenticationServices foi um desafio, especialmente porque a maioria dos objetos usados pela Apple mantém muita informação privada, como por exemplo os métodos construtores.

Para conseguirmos testar essa parte, foi preciso fazer com que a credencial retornada ASAuthorizationAppleIDCredential implementasse um protocolo criado por nós ASAuthorizationAppleIDCredentialProtocol. Desta forma, recebemos a credencial normalmente da Apple e nos testes conseguimos simular os cenários desejados usando objetos dublês.

Para garantir os benefícios que citei acima, a classe que acessa o framework AppleAuthenticationProvider fica totalmente isenta de lógicas de negócio. Os testes unitários aqui precisariam garantir o comportamento de que tudo que é retornado pela Apple é passado para frente exatamente da forma como veio.

Deixamos o mínimo de código nos métodos de delegate do framework e concentramos o mapeamento entre ASAuthorizationAppleIDCredentialProtocol e o objeto que seria retornado ao worker em um método didFetch(authorizationCredential:).

E, assim, nos testes foi possível garantir a corretude desse mapeamento.

Agradecimentos especiais ao Henrique Morbin, que me ajudou pra caramba em como estruturar a feature e como driblar as limitações para conseguirmos adicionar nossos amados testes! ❤

Considerações finais

Essa feature foi minha primeira experiência mexendo com algo tão novo e com tão poucas pessoas passando pelos mesmos problemas na internet. Vários dos problemas que tivemos acabamos resolvendo nós mesmos e outros foi preciso até acionar a ajuda da Apple.

Acredito que essa experiência foi uma das coisas mais legais que desenvolvi até agora no iFood, especialmente porque pude ter contato direto com o time de backend, lidando com os problemas que surgiam desde o começo, lendo documentações até entender quais informações a app tinha acesso e podia enviar ao backend, além de estudar como fazer a integração com nossos serviços já existentes e manter tudo funcionando em harmonia.

O processo todo foi bastante desafiador, enfrentamos muitos altos e baixos e muitos problemas que tivemos que correr para resolver.

Nada disso teria sido possível sem nosso time incrível de desenvolvedores, em especial ao chapter iOS, que nos ajudou demais a resolver problemas de adaptação ao iOS 13 e a testar os mais diversos fluxos para garantir que tudo continuava funcionando.

E por aí? Já pensaram em adicionar o SignInWithApple no app de vocês? Se já implementaram, como foram os testes unitários? Quais foram seus maiores desafios? Comentem aqui!

Quer receber conteúdos exclusivos criados pelos nossos times de tecnologia? Inscreva-se.

--

--