Testes unitários no iOS sem medo de ser feliz

Pietro Caselani
Involves Rocks
Published in
4 min readJun 4, 2018

É difícil falar de testes unitários no iOS sem falar sobre as dores envolvidas, como a lentidão para abrir o simulador, para compilar e instalar o app e só então começar a rodar os testes. Fora outras eventualidades que atrapalham o fluxo de trabalho.

CI quebrando pois o boot do simulador falhou

Neste post vou falar o que tenho feito para me livrar dessas dores e tentar ser mais feliz.

A ideia basicamente consiste em fugir do iOS. Testar no iOS é ruim e chato? Vamos tentar testar no macOS.

Comece criando um Cocoa Framework, um framework para macOS. Aqui é importante lembrar que só podemos utilizar dependências que sejam compatíveis com macOS e iOS.

Crie um Cocoa Framework

Após selecionar Cocoa Framework, dê um nome ao seu framework, selecione a linguagem que irá utilizar e marque a opção Include Unit Tests.

Selecione a opção Include Unit Tests

Agora temos um framework macOS onde vamos criar componentes como Repositories, Interactors, Services - coloque sua camada aqui - nesse target.

Faça testes unitários para essas camadas no testing bundle criado junto com os passos anteriores e agora conseguimos executar os testes de uma maneira muita mais simples rápida, que envolve apenas compilar o target e rodar os testes, sem mais simulador, sem mais instalação do app.

Você provavelmente utiliza algum padrão para a interação com a View, como MVP, MVC, MVVM… e talvez algo para abstrair a navegação do app, como um Router ou Coordinator. Você pode definir contratos e protocolos no framework macOS para essas camadas, mas a implementação da View e da navegação vão ficar no seu target do app iOS.

Vamos ver como isso ficaria na prática. No framework macOS vamos definir os seguintes protocolos:

Contratos para o módulo de filmes

Podemos criar uma implementação simples de MoviesViewModel com o seguinte código:

Conseguimos testar nosso MoviesDefaultViewModel no target macOS, da mesma forma que testamos no iOS:

Para utilizar o novo framework no app iOS, primeiramente é preciso criar um framework iOS. Para isso, criamos um Cocoa Touch Framework. Neste framework não é necessário marcar a opção Include Unit Tests, pois os testes estarão no testing bundle do macOS.

Crie um Cocoa Touch Framework

Os frameworks macOS e iOS precisam ter nomes diferentes, mas na hora que forem utilizados, o nome do módulo que será importado deverá ser o mesmo. Para isso, precisamos trocar o Product Name em Build Settings do framework iOS para o mesmo do framework macOS.

Troque o Product Name do framework iOS para o mesmo do framework macOS

Para utilizar o seu framework no app iOS, adicione o framework iOS no target do app iOS em Embedded Binaries.

Framework iOS linkado com o projeto

Adicione todos os arquivos que foram criados no framework macOS, no framework iOS e agora já é possível utilizar o framework no seu app. Basta criar as Views e componentes de navegação, que conformem com os protocolos definidos no framework.

Você pode conferir a implementação completa deste exemplo no github.

Além dos testes independentes do iOS, agora também conseguimos melhorar a abstração dos nossos dados e das nossas camadas. No Swift, o controle de acesso padrão a membros é o internal que torna o membro visível para todo o módulo. Como estamos criando um framework, conseguimos um melhor controle de acesso, já que apenas os membros marcados como public serão visíveis para o mundo externo.

E assim conseguimos um feedback muito mais rápido dos nossos testes, sem depender do ecossistema do iOS.

--

--