Olá, gostaríamos de te dar as boas-vindas ao curso de teste de integração com iOS da Alura, ministrado por Ândriu Coelho.
Audiodescrição: Ândriu se identifica como um homem branco. Tem olhos e cabelos castanhos. Usa barba e camiseta azul-escura com o logotipo da Alura. Ao fundo, estúdio com iluminação azulada e, à direita, estante com decorações.
Neste curso, vamos estudar sobre teste de integração utilizando o aplicativo Chef Delivery. O objeto é avançar na pirâmide de teste. Anteriormente, testávamos unidades; agora, testaremos fluxos.
Por exemplo, iremos executar um teste automatizado para executar todos os passos pré-definidos e assegurar o principal fluxo do aplicativo, que é a realização de um pedido. Com isso, estudaremos os conceitos e práticas de teste de integração no projeto Chef Delivery.
Outro ponto importante que estudaremos é sobre testes de snapshot. É uma técnica que o Ândriu usa como pessoa desenvolvedora na empresa em que trabalha, o Mercado Livre, que consiste em tirar uma foto do componente para garantir que não haverá inconsistência de layout a cada atualização do aplicativo.
Se ocorrer alguma movimentação ou alteração de cor e tamanho dos componentes, subiremos uma nova foto e o teste comparará se a foto que subimos é igual à foto atual. Dessa forma, conseguimos garantir que, além do fluxo, a parte visual do aplicativo estará assegurada a cada nova entrega.
Como pré-requisito, é importante ter conhecimento em Swift e layouts com SwiftUI, além de concluir os cursos de teste de unidade desta formação.
Gostou do conteúdo que abordaremos? Te esperamos na primeira aula!
Para iniciar esse curso, vamos continuar trabalhando com o app Chef Delivery, que já utilizamos nos cursos anteriores de teste. O objetivo é iniciar um novo contexto de teste dentro desse aplicativo.
Utilizamos a metodologia ágil, ou seja, temos entregas semanais de novas funcionalidades ou correções de bugs. Com isso, incrementamos o aplicativo com novas atualizações. Além disso, já temos testes de unidade assegurando boa parte da regra de negócio do Chef Delivery.
Qual é o novo problema que enfrentamos? As pessoas usuárias estão insatisfeitas e reclamando de algumas pequenas questões na loja. Um dos comentários mais comuns é que os botões não respondem. Provavelmente, a pessoa usuária tentou clicar em algo dentro do aplicativo e não funcionou.
Outra reclamação é que as telas não carregam, ou seja, há fluxos que não estão adequados. A pessoa usuária precisou fechar o aplicativo e abrir novamente para conseguir utilizá-lo. Temos vários outros problemas relacionados a esse tipo de uso inadequado do aplicativo pelas pessoas usuárias.
E, com isso, a pessoa usuária avalia negativamente o aplicativo, o que impacta na recomendação do nosso app quando outras pessoas o buscam na loja.
Qual é a solução que podemos adotar? Juntamente com a equipe de desenvolvimento e tech leads, uma das tarefas foi analisar o uso de teste de integração no nosso aplicativo.
Até agora, estávamos testando pequenas unidades do nosso código, assegurando que a regra de negócios funcionem. Porém, essa integração entre módulos e telas ainda não foi abordada. A ideia é que possamos, a partir de agora, começar a explorar esse tema de teste de integração.
Já estamos com o projeto Chef Delivery aberto, utilizando o Xcode, para começar a trabalhar com testes de integração. É muito comum utilizar o Xcode para testes de UI, ou seja, testes de interface - que é um tipo similar de abordagem.
Para começar a escrever esse tipo de teste, precisamos primeiro analisar os targets presentes no projeto. No painel lateral esquerdo, observamos dois targets: ChefDelivery
e ChefDeliveryTests
. O primeiro é o projeto principal de produção e o segundo é o teste de unidade, criado nos cursos anteriores.
Como vamos abordar testes de UI, precisamos criar um novo target. Para isso, clicamos em "File" no menu superior, selecionamos "New" e escolhemos a opção "Target".
Ao clicar, uma caixa de diálogo se abre para escolher um modelo de target. Na seção de teste no iOS, existem duas opções: teste de unidade e testes de UI. Selecionamos a opção de "UI Testing Bundle" e depois no botão "Next" no canto inferior direito.
Na janela de opções, vamos manter as opções padrão, incluso o nome sugerido ChefDeliveryUITests
, e clicamos no botão "Finish" para concluir a criação.
Agora, no painel lateral esquerdo, temos três targets: o projeto, o teste de unidade e o teste de UI, que são os testes de integração que vamos realizar. Ao clicar na pasta "ChefDeliveryUITests", contamos com dois arquivos criados por padrão: ChefDeliveryUITests
e ChefDeliveryUITestsLaunchTests
. Vamos analisá-los.
ChefDeliveryUITests.swift
:
import XCTest
final class ChefDeliveryUITests: XCTestCase {
override func setUpWithError() throws {
// Put setup code here. This method is cal led before the invocation of each test method in the class.
// In UI tests t is usual ly best to stop immediately when a failure occurs.
continueAfterFailure = false
// In UI tests it's important to set the initial state — such as interface orientation — required for your tests before they run. The setUp method is a good place to do this.
}
override func tearDownWithError() throws {
// Put teardown code here. This method is cal led after the invocation of each test method in the class.
}
func testExample() throws {
// UI tests must launch the application that they test.
let app = XCUIApplication()
app.launch()
// Use XCTAssert and related functions to verify your tests produce the correct results.
}
func testLaunchPerfomance() throws {
if #available(macOS 10.15, iOS 13.0, tvOS 13.0, watchOS 7.0, *) {
// This measures how long it takes to launch your application.
measure(metrics: [XCTApplicationLaunchMetric()]) {
XCUIApplication().launch()
}
}
}
}
A classe ChefDeliveryUITests
utiliza o framework que já conhecemos e utilizamos para escrever os testes de unidade, que é o XCTest
.
O primeiro método chamado setUpWithError()
é utilizado para fazer uma pré-configuração, seja de uma variável ou de um objeto, antes do teste ser iniciado. O próximo método é o tearDownWithError()
, que é o contrário do primeiro. Ele é utilizado para configurar detalhes após a execução de cada teste.
Também temos um método chamado testExample()
, que traz um exemplo de teste que vamos analisar. Há também um método testLaunchPerfomance()
que mede o desempenho, o qual não vamos utilizar por enquanto.
Vamos apagar tanto o método testLaunchPerfomance()
quanto todos os comentários em inglês, deixando apenas o código.
final class ChefDeliveryUITests: XCTestCase {
override func setUpWithError() throws {
continueAfterFailure = false
}
override func tearDownWithError() throws { }
func testExample() throws {
let app = XCUIApplication()
app.launch()
}
}
O testExample
é um exemplo de como o teste de integração inicia. Em let app
, temos a instância da aplicação rodando nos testes de UI. Na próxima linha, através do app.launch()
, inicializamos o aplicativo.
No menu superior, vamos acessar "Product", clicar na opção "Test" (atalho "Command + U") e aguardar o build ser gerado.
Ao executar o teste, como ele tem apenas uma instrução na linha 20, o aplicativo é inicializado e rapidamente já se fecha. Isso porque ainda não passamos nenhuma instrução para navegar e testar alguma parte do nosso projeto.
Resumindo, esse teste inicial mostra como inicializar o aplicativo. A partir daqui, podemos pensar em qual fluxo testar e como utilizar os testes de UI para isso.
Nós acabamos de criar o target para testes de integração, ou seja, para testes de UI no Xcode.
Por padrão, é criado um método chamado testExample()
. Vamos alterar a nomenclatura desse método, mas, por enquanto, descobrimos que as duas linhas iniciais desse método nos ajudam a inicializar o aplicativo. A partir daqui, podemos começar a escrever nosso primeiro teste de integração.
Inicialmente, é preciso definir quais fluxos testaremos. Para isso, vamos abrir o aplicativo e rodar o app.
A primeira tela é o onboarding, que podemos deslizar para entrar na home do app, ou seja, a tela inicial, a partir da qual conseguimos acessar todos os outros fluxos.
Um dos comentários que as pessoas usuárias estavam reportando é que botões não estavam funcionando corretamente e algumas telas não estavam sendo abertas. Com base nisso, podemos mapear alguns fluxos para escrever scripts que executem os testes de forma automática, como se programássemos um robô para executar os passos pré-determinados no código.
Vamos utilizar um exemplo para entender melhor. Quando a pessoa usuária clica no botão de "Filtrar", ela pode escolher uma das opções do popover para filtrar por lojas de 1 até 5 estrelas. A ação desse botão é o primeiro fluxo que vamos garantir utilizando o teste de interface.
Pensando nessa lógica, onde devemos configurar um robô para realizar os testes, qual o primeiro passo que devemos ensinar para que ele consiga encontrar esse botão? A home tem vários componentes, como labels, botões e listas.
Basicamente, queremos que o robô identifique um único botão neste momento, que é o botão de filtrar, para clicar nele e, em seguida, clicar em uma das opções do popover.
Agora que entendemos nossa demanda, vamos voltar à classe de teste de interface chamada ChefDeliveryUITests()
.
Em testExample()
, logo abaixo da linha 20, onde o aplicativo é inicializado, devemos identificar o botão filtrar. Para fazer isso, vamos criar uma nova constante let
chamada filterMenu
.
A partir da constante de app
, temos acesso ao XCUIApplication
, o qual tem uma propriedade chamada buttons
que serve para analisar o identificador de um botão. Desse modo, por meio de app.buttons
, podemos colocar, entre colchetes e aspas, o identificador FilterMenu
.
Assim, supondo que esse botão de menu de filtro seja encontrado, podemos chamar o filterMenu
e aplicar o método tap()
, que é uma ação feita automaticamente. Em suma, nosso teste inicializará o simulador, identificará, entre todos os botões visíveis, um botão com o identificador FilterMenu
e, tocará nesse botão.
ChefDeliveryUITests.swift
:
func testExample() throws {
let app = XCUIApplication()
app.launch()
let filterMenu = app.buttons["FilterMenu"]
filterMenu.tap()
}
É uma boa prática, seja em teste de unidade ou teste de integração, utilizar Asserts, que são instruções que garantem que nosso teste está funcionando corretamente.
Antes de fazer o tap()
, seria melhor garantir que o botão existe, para que o teste não clique em um botão que não encontre. Assim, caso o botão com esse identificador não seja encontramos, o teste já quebraria nessa primeira etapa.
Para isso, utilizamos o framework que já conhecemos, o XCTest
. Antes do tap()
, chamamos o XCTestAssertTrue()
e passamos uma condição para que a função avalie se é verdadeira ou falsa. Nesse caso, deve ser verdadeira.
A condição é filterMenu.exists
. Se ele existir, o teste avança. Se não existir, o teste falha.
Como segundo parâmetro opcional, podemos colocar uma mensagem de falha para informar a pessoa desenvolvedora qual foi o problema. Por exemplo, a string "O menu de filtro deve existir".
func testExample() throws {
let app = XCUIApplication()
app.launch()
let filterMenu = app.buttons["FilterMenu"]
XCTAssertTrue(filterMenu.exists, "O menu de filtro deve existir")
filterMenu.tap()
}
Desse modo, desenvolvemos o primeiro bloco do teste de UI. Abrindo o simulador, relembraremos o primeiro passo: se o teste for bem-sucedido, o robô do teste acessa a página inicial, procura o botão com o identificador filterMenu
e realiza um tap
(ou seja, clica). Isso abre um popover com várias opções.
Agora, no segundo bloco de código, precisamos ensinar ao teste qual opção ele deve clicar. Vamos selecionar, por exemplo, a opção de "3 estrelas ou mais".
Depois do primeiro bloco, vamos criar uma constante chamada ratingFilterMenu
que será igual a app.buttons
. Entre colchetes e aspas, passaremos outro identificador, que será RatingFilterButton_3
, a terceira opção do popover.
Caso o botão exista, chamamos o ratingFilterMenu.tap()
para executar a ação de clique.
Antes disso, também podemos fazer um assert, assim como fizemos anteriormente. Através da função XCTAssertTrue
, verificaremos se ratingFilterMenu.exists
e informamos, em caso de falha, que "O botão de filtro de 3 estrelas deve existir".
func testExample() throws {
let app = XCUIApplication()
app.launch()
let filterMenu = app.buttons["FilterMenu"]
XCTAssertTrue(filterMenu.exists, "O menu de filtro deve existir")
filterMenu.tap()
let ratingFilterMenu = app.buttons["RatingFilterButton_3"]
XCTAssertTrue(ratingFilterMenu.exists, "O botão de filtro de 3 estrelas deve existir")
ratingFilterMenu.tap()
}
Assim, o teste inicial está mais completo.
Basicamente, existem duas formas de se executar um teste. Se o Xcode estiver com a configuração padrão, ele exibirá um diamante ao lado de cada linha. Basta clicar nele para rodar o teste.
Caso isso não apareça, podemos acessar uma aba específica de teste no painel lateral esquerdo, chamada "Show the Test Navigator" (Mostrar navegador de teste). Nela, são listadas todos os testes do projeto, sejam teste de unidade ou teste de UI.
Neste caso, utilizaremos apenas o target de teste de UI, que é o foco atual. Para evitar confusão, podemos ocultar os testes de unidade clicando no ícone de seta à esquerda para colapsá-los.
Em ChefDeliveryUITest
, vamos executar o testExample
clicando no ícone de diamante à sua direita. Ocorre um erro, pois não temos um esquema configurado para rodar os testes de UI.
O esquema funciona como um ambiente onde os testes de integração serão executados.
Além de criar o target, precisamos configurar o esquema. Basta clicar em cima do target na barra superior do Xcode e escolher a opção "New Scheme". Na caixa de diálogo, contamos com os campos de "Target" e "Name". Iremos selecionar o target ChefDeliveryUITest
e manter o nome sugerido. Por fim, clicamos no botão "OK".
Desse modo, o esquema separa nosso teste de UI dos outros testes. Agora, podemos executar novamente o teste ChefDeliveryUITest
, clicando no ícone de diamante. Após iniciar o simulador e gerar o build, a aplicação será inicializada.
O primeiro problema é que a aplicação abre a tela de onboarding. Porém, o teste espera que a home seja carregada para buscar o filterMenu
.
Por enquanto, vamos corrigir isso alterando a inicialização do app. No painel lateral esquerdo, vamos acessar a pasta "ChefDelivery > App" para abrir o arquivo ChefDeliveryApp
.
Na linha 14, no lugar de HomeView()
, vamos abrir o ContentView()
, que é a tela inicial do app.
ChefDeliveryApp.swift
struct ChefDeliveryApp: App {
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
Voltamos ao arquivo de teste, abrimos a aba de teste no painel lateral e clicamos novamente no ícone de diamante para executar o ChefDeliveryUITest
. Agora, o aplicativo carrega a home, mas o teste ainda falha porque o menu de filtro não foi encontrado.
XCTAssertTrue failed - O menu de filtro deve existir
Ao longo do vídeo, mencionamos propositalmente várias vezes a palavra "identificador", que é uma forma de mostrar ao teste qual elemento ele deve capturar e manipular. A seguir, vamos realizar esse passo para corrigir nosso primeiro teste de integração.
O curso iOS: garantindo a qualidade do app com testes de UI e snapshot possui 126 minutos de vídeos, em um total de 48 atividades. Gostou? Conheça nossos outros cursos de iOS em Mobile, ou leia nossos artigos de Mobile.
Matricule-se e comece a estudar com a gente hoje! Conheça outros tópicos abordados durante o curso:
Impulsione a sua carreira com os melhores cursos e faça parte da maior comunidade tech.
1 ano de Alura
Assine o PLUS e garanta:
Formações com mais de 1500 cursos atualizados e novos lançamentos semanais, em Programação, Inteligência Artificial, Front-end, UX & Design, Data Science, Mobile, DevOps e Inovação & Gestão.
A cada curso ou formação concluído, um novo certificado para turbinar seu currículo e LinkedIn.
No Discord, você tem acesso a eventos exclusivos, grupos de estudos e mentorias com especialistas de diferentes áreas.
Faça parte da maior comunidade Dev do país e crie conexões com mais de 120 mil pessoas no Discord.
Acesso ilimitado ao catálogo de Imersões da Alura para praticar conhecimentos em diferentes áreas.
Explore um universo de possibilidades na palma da sua mão. Baixe as aulas para assistir offline, onde e quando quiser.
Acelere o seu aprendizado com a IA da Alura e prepare-se para o mercado internacional.
1 ano de Alura
Todos os benefícios do PLUS e mais vantagens exclusivas:
Luri é nossa inteligência artificial que tira dúvidas, dá exemplos práticos, corrige exercícios e ajuda a mergulhar ainda mais durante as aulas. Você pode conversar com a Luri até 100 mensagens por semana.
Aprenda um novo idioma e expanda seus horizontes profissionais. Cursos de Inglês, Espanhol e Inglês para Devs, 100% focado em tecnologia.
Transforme a sua jornada com benefícios exclusivos e evolua ainda mais na sua carreira.
1 ano de Alura
Todos os benefícios do PRO e mais vantagens exclusivas:
Mensagens ilimitadas para estudar com a Luri, a IA da Alura, disponível 24hs para tirar suas dúvidas, dar exemplos práticos, corrigir exercícios e impulsionar seus estudos.
Envie imagens para a Luri e ela te ajuda a solucionar problemas, identificar erros, esclarecer gráficos, analisar design e muito mais.
Escolha os ebooks da Casa do Código, a editora da Alura, que apoiarão a sua jornada de aprendizado para sempre.