Por muito tempo eu pensei que os testes automatizados eram dispensáveis, que o tempo despendido para implementa-los poderia ser investido em novas features, que pudessem trazer melhores experiências para os usuários.
Essa maneira de pensar pode até funcionar por algum tempo, no entanto, os pesadelos começam quando a seguinte palavra começa a ser pronunciada com certa frequência: ESCALA.
O app nunca chega a um “estado de conclusão“, o que conseguimos concluir são as demandas. O app sempre está evoluindo, em outras palavras “engordando”.
Manter meia dúzia de telas e componentes é simples, mas e quando você salta para 80 ou 100 ítens, entre telas e componentes e com atividades divididas entre dois ou mais desenvolvedores?
Observação: O link para o repositório do projeto, está no final deste post.
É nesse ponto que você se arrepende de não ter iniciado o projeto incluindo os testes automatizados e pensa que tudo está perdido.
A boa notícia é que na maioria dos casos, ainda é possível incluir os testes sem a necessidade de alterações muito significativas no código.
O Detox é uma biblioteca de teste e automação para aplicações mobile, que pode ser executada no simulator/emulador ou nos dispositivos físicos.
As instruções atualizadas para instalação e configuração do Detox estão disponíveis neste link, caso algo já tenha mudado no momento em que você estiver lendo este post.
1) Instalando globalmente as ferramentas de linha de comando do Detox:
npm install -g detox-cli
2) Instalando as dependências específicas de cada plataforma. (Neste exemplo utilizando o ios):
xcode-select --install
brew tap wix/brew brew install applesimutils
3) Incluindo o Detox no seu projeto React Native:
yarn add detox -D
yarn add mocha -D
detox init -r mocha
Serão criados na raiz do projeto, o diretório e2e e o arquivo de configuração.
detox[51026] INFO: [init.js] Created a file at path: e2e/.mocharc.json detox[51026] INFO: [init.js] Created a file at path: e2e/init.js detox[51026] INFO: [init.js] Created a file at path: e2e/firstTest.spec.js detox[51026] INFO: [init.js] Created a file at path: .detoxrc.json
4) Configurando o runner Mocha:
Agora vamos editar o arquivo .detoxrc.json que foi criado na raiz do projeto.
Observação: Note que neste exemplo, o arquivo .detoxrc.json está com o nome do meu projeto, E2ETest.app. Tudo o que você precisa fazer é substituir o nome E2ETest pelo nome do seu projeto.
{ "testRunner": "mocha", "runnerConfig": "e2e/.mocharc.json", "configurations": { "ios": { "type": "ios.simulator", "name": "iPhone 11", "binaryPath": "ios/Build/Products/Debug-iphonesimulator/E2ETest.app", "build": "xcodebuild -project ios/E2ETest.app.xcworkspace -scheme E2ETest.app -configuration Debug -sdk iphonesimulator -derivedDataPath ios/Build" }, "android": { "type": "android.emulator", "binaryPath": "SPECIFY_PATH_TO_YOUR_APP_BINARY", "device": { "avdName": "Pixel_2_API_29" } } } }
5) Definindo o identificador do elemento que será testado:
Para se referenciar aos elementos presentes no código, o Detox utiliza métodos que distinguem cada elemento, estes métodos são chamados de Matchers.
Existem vários métodos (Matchers) que podem ser utilizados para fazer referência ao elemento, no entanto no exemplo a seguir, o Matcher utilizado é o by.id(id), cujo identificador pode ser definido pela propriedade testID, presente no React Native.
<Input testID="loginInput" value={email} label="E-mail" placeholder="Place your e-mail" onChangeText={(nextValue) => setEmail(nextValue)} style={{ paddingBottom: 30 }} />
Dica: Eu estou acostumado a setar as props no padrão “camelCase”, e muitas vezes me confundi, colocando testId invés de testID. Se no seu teste aparecerem erros do tipo “Error: Test Failed: No elements found for “MATCHER(identifier: (..) “, pode ser que o nome da prop esteja errado.
6) Escrevendo o arquivo de teste:
Quando iniciamos o Detox lá no passo 3, uma pasta chamada “e2e” foi gerada na raiz do projeto, e dentro dela um arquivo chamado “firstTest.spec.js” foi gerado.
É este arquivo que vamos editar para atingir nossos objetivos do teste.
Abaixo você tem um modelo do arquivo de teste:
describe('Login flow', () => { it('should fill the e-mail', async () => { await element(by.id('loginInput')).typeText('[email protected]'); }); });
Nesta linha estamos basicamente dizendo “vá até o elemento cuja propriedade testID é igual a loginInput. Em seguida digite o texto [email protected]“
Para o teste ficar um pouco mais completo, eu adicionei mais alguns elementos no arquivo firstTest.spec.js:
describe('Login flow', () => { it('should fill the e-mail', async () => { await element(by.id('loginInput')).typeText('[email protected]'); }); it('should fill the password', async () => { await element(by.id('passwordInput')).typeText('myawesomepassword'); await element(by.id('toggleSecureEntry')).tap(); }); it('should tap login button', async () => { await element(by.id('submitButton')).multiTap(3); }); });
7) Executando o teste:
Abra um terminal na pasta raiz do projeto e execute o comando a seguir:
detox test --configuration ios
Observação: Devido a abordagem deste post se basear somente na plataforma IOS, a flag — configuration ios foi adicionada, dessa forma restringindo os testes somente ao simulator.
Resultado dos testes:
Esta é a base para o início dos testes E2E, eu recomendo que você leia a documentação do Detox e acompanhe a evolução da biblioteca, pois pode ser que quando você estiver lendo este post as coisas já tenham mudado.
Link para o repositório no Github:
https://github.com/Jojr/e2e-tests-detox-react-native/