
Meu nome é Dmitry, trabalho como testador na empresa . Recentemente, terminei de explorar uma funcionalidade relativamente nova da — especificamente, o teste instrumental de aplicativos iOS usando o framework de teste nativo XCUITest.
Antes disso, já havia experimentado o Firebase Test Lab para Android e gostei bastante, então decidi tentar implementar a infraestrutura de teste do projeto iOS nos mesmos moldes. Tive que pesquisar muito e nem tudo funcionou na primeira tentativa, por isso decidi escrever um artigo-tutorial para aqueles que ainda precisam passar por isso.
Portanto, se você tem testes de UI no seu projeto iOS, já pode tentar executá-los em dispositivos reais, gentilmente fornecidos pela Corporação do Bem. Interessados, sintam-se à vontade para continuar lendo.
Na narrativa, decidi partir de alguns dados iniciais — um repositório privado no GitHub e o sistema de construção CircleCI. O nome do aplicativo é AmazingApp, bundleID — com.company.amazingapp. Estou compartilhando esses dados desde já para reduzir possíveis confusões futuras.
Se você implementou certas soluções de forma diferente em seu projeto, compartilhe sua experiência nos comentários.
1. Os testes em si
Criamos um novo branch no projeto para os testes de UI:
$ git checkout develop
$ git pull
$ git checkout -b “feature/add-ui-tests”
Abrimos o projeto no XCode e criamos um novo Target com testes de UI [XCode -> File -> New -> Target -> iOS Testing Bundle], e damos a ele um nome descritivo: AmazingAppUITests.

Vamos para a seção Build Phases do Target criado e verificamos a presença de Target Dependencies — AmazingApp, em Compile Sources — AmazingAppUITests.swift.
Uma boa prática é separar as diferentes variantes de construção em Schemes. Criamos uma scheme para nossos testes de UI [XCode -> Product -> Scheme -> New Scheme] e damos a ela o mesmo nome: AmazingAppUITests.
A Build da scheme criada deve incluir o Target do aplicativo principal — AmazingApp e o Target dos testes de UI — AmazingAppUITests — veja a captura de tela.

Em seguida, criamos uma nova configuração de build para os testes de UI. No XCode, clicamos no arquivo do projeto, vamos para a seção Info. Clicamos em “+” e criamos uma nova configuração, por exemplo, XCtest. Isso será necessário mais tarde para evitar complicações quando se tratar de code signing.

No seu projeto, há pelo menos três Targets: o aplicativo principal, testes unitários (afinal, você os tem, não é?) e o Target de testes de UI que criamos.
Acesse o Target AmazingApp, aba Build Settings, seção Code Signing Identity. Para a configuração XCtest, selecionamos iOS Developer. Na seção Code Signing Style, escolhemos Manual. O provisioning profile ainda não foi gerado, mas voltaremos a isso em breve.
Para o Target AmazingAppUITests, fazemos a mesma coisa, mas no campo Product Bundle Identifier, inserimos com.company.amazingappuitests.
2. Configurando o projeto no Apple Developer Program
Acesse a página do Apple Developer Program, vá para a seção Certificates, Identifiers & Profiles e depois para o campo App IDs da seção Identifiers. Crie um novo App ID com o nome AmazingAppUITests e bundleID com.company.amazingappuitests.

Agora temos a capacidade de assinar nossos testes com um certificado separado, mas... O processo de construção do build para testes implica a construção do próprio aplicativo e da construção do runner de testes. Consequentemente, enfrentamos o problema de assinar dois bundle IDs com um único provisioning profile. Felizmente, existe uma solução simples e elegante — Wildcard App ID. Repetimos o procedimento de criação de um novo App ID, mas em vez de Explicit App ID, escolhemos Wildcard App ID, como na captura de tela.

Neste ponto, o trabalho com developer.apple.com está concluído, mas não vamos fechar a janela do navegador. Vamos ao e lemos sobre a ferramenta Match de cabo a rabo.
O leitor atento notou que, para usar essa ferramenta, precisaremos de um repositório privado e de uma conta que tenha acesso tanto ao Apple Developer Program quanto ao Github. Criamos (se é que não existe) uma conta do tipo InfrastructureAccount@your.company.domain, pensamos em uma senha forte, registramos ela em developer.apple.com e a designamos como administrador do projeto. Em seguida, damos à conta acesso ao repositório github da sua empresa e criamos um novo repositório privado com um nome como AmazingAppMatch.
3. Configurando o Fastlane e a ferramenta match
Abrimos o terminal, navegamos até a pasta do projeto e inicializamos o fastlane conforme indicado no . Após digitar o comando
$ fastlane initserá solicitado que escolha as configurações de uso disponíveis. Selecionamos a quarta opção — configuração manual do projeto.

Uma nova diretório fastlane foi criada no projeto, que contém dois arquivos — Appfile e Fastfile. Em resumo — no Appfile armazenamos dados de serviço, e no Fastfile descrevemos jobs, na terminologia do Fastlane chamados de lanes. Recomendo a leitura da documentação oficial: , .
Abra o Appfile no seu editor de texto favorito e ajuste-o para o seguinte formato:
app_identifier "com.company.amazingapp" # Bundle ID
apple_dev_portal_id "infrastructureaccount@your.company.domain" # Conta de infraestrutura criada com permissão para editar o projeto iOS no Programa de Desenvolvedores da Apple.
team_id "LSDY3IFJAY9" # Seu ID de equipe do Portal do Desenvolvedor
Voltamos ao terminal e, seguindo o manual oficial, começamos a configurar o match.
$ fastlane match init
$ fastlane match development
Em seguida, inserimos os dados solicitados — repositório, conta, senha, etc.
Importante: na primeira execução, a ferramenta match pedirá para inserir a senha para descriptografar o repositório. É muito importante guardar essa senha, pois vamos precisar dela na configuração do servidor CI!
Na pasta fastlane, apareceu um novo arquivo — Matchfile. Abrimos em nosso editor de texto favorito e ajustamos para o seguinte formato:
git_url("https://github.com/YourCompany/AmazingAppMatch") # Repositório privado criado para armazenar certificados e perfis.
type("development") # O tipo padrão pode ser: appstore, adhoc, enterprise ou development
app_identifier("com.company.amazingapp")
username("infrastructureaccount@your.company.domain") # Seu nome de usuário da conta de infraestrutura no Portal do Desenvolvedor Apple
Preencha exatamente dessa forma se quisermos usar o match para assinar builds para publicação no Crashlytics e/ou AppStore, ou seja, para assinar o bundle ID do seu aplicativo.
Mas, como lembramos, para assinar o build de teste, criamos um ID Wildcard especial. Portanto, abrimos o Fastfile e inserimos um novo lane:
lane :testing_build_for_firebase do
match(
type: "development",
readonly: true,
app_identifier: "com.company.*",
git_branch: "uitests" # criamos um branch separado para o certificado de desenvolvimento para assinar a build de teste.
)
end
Salvamos, e digitamos no terminal
fastlane testing_build_for_firebasee vemos como o fastlane criou um novo certificado e o colocou no repositório. Excelente!
Abrimos o XCode. Agora temos o provisioning profile necessário do tipo Match Development com com.company.*, que deve ser indicado na seção de Provisioning profile para os targets AmazingApp e AmazingAppUITests.

Resta adicionar o lane para a compilação dos testes. Vamos em projeto do plugin para fastlane, que facilita a configuração da exportação para o Firebase Test Lab, e seguimos as instruções.
Copiamos do exemplo original, para que nosso lane testing_build_for_firebase fique assim:
lane :testing_build_for_firebase do
match(
type: "development",
readonly: true,
app_identifier: "com.company.*",
git_branch: "uitests"
)
scan(
scheme: 'AmazingAppUITests', # Esquema de teste UI
clean: true, # Recomendado: Isso garantiria que a construção não incluiria arquivos desnecessários
skip_detect_devices: true, # Necessário
build_for_testing: true, # Necessário
sdk: 'iphoneos', # Necessário
should_zip_build_products: true, # Deve ser verdadeiro para definir o formato correto para o Firebase Test Lab
)
firebase_test_lab_ios_xctest(
gcp_project: 'AmazingAppUITests', # Nome do seu projeto Google Cloud (voltaremos a essa linha mais tarde)
devices: [ # Dispositivo(s) para rodar os testes
{
ios_model_id: 'iphonex', # ID do modelo do dispositivo, veja o comando gcloud acima
ios_version_id: '12.0', # ID da versão do iOS, veja o comando gcloud acima
locale: 'en_US', # Opcional: padrão para en_US se não definido
orientation: 'portrait' # Opcional: padrão para retrato se não definido
}
]
)
end
Para obter informações completas sobre a configuração do fastlane no CircleCI, recomendo a leitura da documentação oficial .
Não esqueçamos de adicionar a nova tarefa ao nosso config.yml:
build-for-firebase-test-lab:
macos:
xcode: "10.1.0"
working_directory: ~\/project
shell: \/bin\/bash --login -o pipefail
steps:
- checkout
- attach_workspace:
at: ~\/project
- run: sudo bundle install # atualiza as dependências
- run:
name: instalar gcloud-sdk # precisamos instalar o gcloud na máquina mac
command: |
ruby -e "$(curl -fsSL https:\/\/raw.githubusercontent.com\/Homebrew\/install\/master\/install)" < \/dev\/null 2> \/dev\/null ; brew install caskroom\/cask\/brew-cask 2> \/dev\/null
brew cask install google-cloud-sdk
- run:
name: construir app para teste
command: fastlane testing_build_for_firebase # executa a lane de construção e envio para o firebase
4. E quanto ao nosso ambiente de teste? Vamos configurar o Firebase.
Vamos começar, afinal, é para isso que este artigo foi escrito.
Talvez seu aplicativo utilize o Firebase no plano gratuito, ou talvez não utilize. Não faz diferença, pois para fins de teste podemos criar um projeto separado com um ano de uso gratuito (legal, né?)
Fazemos login na nossa conta de infraestrutura (ou qualquer outra, tanto faz), e vamos para . Criamos um novo projeto com o nome AmazingAppUITests.
Importante: No passo anterior, no Fastfile, o parâmetro gcp_project na lane firebase_test_lab_ios_xctest deve corresponder ao nome do projeto.

As configurações padrão são aceitáveis para nós.
Não fechamos a aba, sob a mesma conta registramo-nos no — isso é uma medida necessária, pois a comunicação com o Firebase ocorre por meio da interface do console gcloud.
O Google oferece $300 por ano, o que, no contexto da execução de testes automatizados, equivale a um ano de uso gratuito do serviço. Inserimos os dados de pagamento, aguardamos a cobrança de teste de $1 e recebemos $300 na conta. Após um ano, o projeto será automaticamente transferido para o plano gratuito, portanto, não há necessidade de se preocupar com a possível perda de dinheiro.
Voltamos à aba com o projeto Firebase e o transferimos para o plano Blaze - agora temos como pagar em caso de exceder o limite.
Na interface gcloud, escolhemos nosso projeto Firebase, selecionamos a opção do menu principal 'Catálogo' e adicionamos o Cloud Testing API e o Cloud Tools Result API.

Em seguida, vamos ao menu 'IAM e administração' -> Contas de serviço -> Criar conta de serviço. Concedemos permissões para edição do projeto.

Criamos a chave API no formato JSON.

O JSON baixado nos será útil mais tarde, enquanto isso consideramos que a configuração do Test Lab está concluída.
5. Configuração do CircleCI
Surge uma pergunta razoável - e quanto às senhas? Para armazenar com segurança nossas senhas e outros dados sensíveis, utilizaremos o mecanismo de variáveis de ambiente da nossa máquina de build. Nas configurações do projeto CircleCI, escolhemos Variáveis de Ambiente.

E criamos as seguintes variáveis:
- chave: GOOGLE_APPLICATION_CREDENTIALS
valor: conteúdo do arquivo JSON da chave da conta de serviço gcloud - chave: MATCH_PASSWORD
valor: senha para descriptografar o repositório do GitHub com os certificados - chave: FASTLANE_PASSWORD
valor: senha da conta de infraestrutura do Apple Developer Portal
Salvamos as alterações, criamos um PR e enviamos para revisão ao nosso líder de equipe.
Resultados
Como resultado da execução dessas simples ações, conseguimos um bom ambiente de teste estável, com a capacidade de gravar vídeos da tela do dispositivo durante a execução dos testes. No exemplo de teste, indiquei o modelo do dispositivo iPhone X, mas a fazenda oferece uma rica seleção de combinações de diferentes modelos e versões do iOS.
A segunda parte será dedicada à configuração passo a passo do Firebase Test Lab para projetos Android.
Fonte: habr.com
