Todos nós sabemos da importância dos testes unitários no desenvolvimento de software e nesse post vamos montar um pequeno projeto com o teste básico de uma lista a fim de apresentar a estrutura do XCTest, framework de teste utilizado pelo Xcode.
Para começar vamos criar um novo projeto e selecionar a opção “Include Unit Tests”
Após realizar todas as etapas de criação do projeto você poderá observar na hierarquia de pastas que o Xcode criou além da pasta padrão do projeto outra pasta na qual serão incluídos os testes de sua aplicação, reparem que o próprio Xcode já criou um arquivo de teste padrão.
Ao abrir o arquivo padrão disponibilizado pelo Xcode nos deparamos com o seguinte código:
Analizando esse código já temos alguns pontos interessantes:
O que essa linha faz é importar o seu projeto para o namespace do teste, a palavra chave @testable é necessário por causa da forma como o swift opera com seus modificadores de acesso.
O Swift possui três tipos de modificadores de acesso: Public, Internal e Private, que permitem visibilidade pública a qualquer namespace, visibilidade somente dentro do mesmo namespace e visibilidade apenas da classe/Struct, respectivamente.
Como o teste esta em um namespace separado do projeto, o desenvolvedor precisaria escrever todas as classes e variáveis com o modificador Public, para resolver esse impasse a Apple inseriu a partir da versão 2 do swift a palavra chave @testable, permitindo que as classes e variáveis com o modificador Internal fiquem visíveis no namespace de teste, o que garante a coerência dos modificadores de acesso.
Função setUp: Nela será inserido o código para garantir o estado inicial do seu ambiente de teste, como por exemplo, instanciar as controllers que serão testadas. Essa função é chamada antes de cada teste descrito no arquivo.
Função tearDown: Nela você limpará os dados gerados por seu teste. Essa função é chamada após a execução de cada teste descrito no arquivo.
Função testExample: O teste a ser executado, sendo que todos os testes devem obrigatoriamente começar com a palavra test em seu nome.
Função testPerformanceExample: Como no caso anterior, trata-se de um teste, mas como pode ser visto em seu corpo possui um bloco para medição de performance de seu código.
A partir deste ponto vamos começar a escrever o primeiro teste para nossa controller. Para isso vamos precisar cria-la em nosso ambiente e adicionar uma propriedade do mesmo tipo da controller.
var viewController: ViewController!
E na função setUp vamos instanciar nossa controller
override func setUp() {
super.setUp()
viewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewControllerWithIdentifier("Controller") as! ViewController
_ = viewController.view
}
Um ponto importante que devemos destacar nesse neste código é na chamada “_ = viewController.view”, ela é necessária para o carregamento correto da view, segundo a documentação da Apple, uma view só é carregada completamente, e de maneira correta quando requisitada.
Como essa chamada fica sem sentido na leitura de nosso código podemos melhorar a semântica criando uma extension para preload de nossa view controller:
import Foundation
import UIKit
extension UIViewController {
func preload() {
_ = self.view
}
}
E agora podemos utilizar a função de preload no setup de nosso teste, o que garante melhor legibilidade ao nosso código.
override func setUp() {
super.setUp()
viewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewControllerWithIdentifier("Controller") as! ViewController
viewController.preload()
}
A partir de agora já temos nossa view devidamente instanciada e podemos testa-la. Supondo que minha controller tenha apenas um tableview que deve conter exatamente a quantidade de linhas de meu array, vamos fazer nosso primeiro teste.
func testNumeroDeItensDaTabelaDeveSerIgualAQuantidadeDeDadosDoArray() {
viewController.array = ["Item 1", "Item 2", "Item 3"]
XCTAssertEqual(viewController.tableView?.numberOfRowsInSection(0), 3, "Numero de rows na tabela deve ser igual a 3")
}
Com nosso primeiro caso de teste construído podemos executá-los através do atalho command+U.
Se você fez corretamente todos os pontos descritos até esse momento seu teste obviamente irá falhar pois ainda não foi construído a controller com todos os elementos que utilizamos aqui.
Agora como desafio insira na sua controller uma propriedade chamada array e um tableview devidamente configurado para que este teste passe na validação.
Esse teste apesar de simples garante que o desenvolvedor não esqueça, por algum motivo, de configurar o datasource do tableview fazendo com que a lista simplesmente deixe de apresentar os dados.
No próximo post continuaremos os testes de nossa lista adicionando fluxo de telas e como estruturar melhor a chamada dos serviços para mockar os dados.