Простые модульные тесты в iOS-разработке

Тестировать тяжело. Вот почему этого недостаточно в разработке iOS. Когда я спрашиваю других разработчиков, многие из них вообще не пишут модульные тесты. Это не хорошо. Модульные тесты — это важный инструмент для создания высококачественных приложений для iOS, который позволяет выполнять деструктивный рефакторинг без нарушения функциональности.

Основные преимущества написания модульных тестов:

Код становится рефакторинговым.
Тестируемый код обычно лучше кода. Поэтому, когда вас «вынуждают» писать код, ваш код автоматически становится лучше.
Менее вероятно введение регрессии в код с хорошим тестовым покрытием.
Сначала написание тестов часто упрощает реализацию новой функции, потому что вы намеренно делаете очень маленькие шаги.
Тесты — это живая документация. Я имею в виду, что при жизни менее вероятно, что они станут асинхронными с фактическим кодом, как это часто происходит с традиционной документацией на каком-либо веб-сайте.
Ладно, тесты хорошие и важные. Предположим, вы готовы начать писать тесты для своего кода. Как начать? Самое главное — написать первый тест. Итак, вот несколько простых тестов, которые вы можете ввести в свой код прямо сейчас. Давайте начнем.

Проверить, установлено ли свойство

Допустим, у нас есть User структура с именем и фамилией:

struct User {
  var firstname: String = ""
  var lastname: String = ""
}

Теперь нам нужно свойство name то есть firstname а также lastname с пробелом между ними.

Мы добавим эту функцию с помощью Test-Diven Development (TDD). В TDD вы пишете тест до того, как добавляете тестируемый код. Звучит странно, но после того, как вы привыкнете к этому, это обретет смысл. Мы предполагаем, что у проекта уже есть тестовая цель. (Если это не так, просто добавьте тестовую цель.)

Теперь тест для функции, которую мы собираемся создать:

import XCTest
@testable import MyApp

class PropertyTests : XCTestCase {
  
  var sut: User!
  
  override func setUp() {
    sut = User()
  }
  
  override func tearDown() {
    sut = nil
  }
  
  func test_name_property() {
    // Arrange

    // Act
    sut.firstname = "Foo"
    sut.lastname = "Bar"
    
    // Assert
    XCTAssertEqual(sut.name, "Foo Bar")
  }
}

Попробуйте запустить тест с помощью ярлыка ⌘U. Тест не компилируется, так как у пользователя нет свойства с именем name. Некомпилируемый тест — это провальный тест. Давайте добавим достаточно кода, чтобы он скомпилировался.

struct User {
  var firstname: String = ""
  var lastname: String = ""
  var name: String = ""
}

Снова запустите тест с помощью ⌘U. Теперь тест компилируется, но если не получается. Это хороший знак, потому что мы не реализовали код, который хотим тестировать. Если бы тест прошел до того, как мы реализовали эту функцию, вероятно, тест проходил бы все время и, следовательно, был бы бесполезен.

Когда мы меняем структуру User на следующую, тест проходит:

struct User {
  var firstname: String = "" {
    didSet {
      updateName(firstname: firstname,
                 lastname: lastname)
    }
  }
  var lastname: String = "" {
    didSet {
      updateName(firstname: firstname,
                 lastname: lastname)
    }
  }
  var name: String = ""
  
  private mutating func updateName(firstname: String, lastname: String) {
    
    name = "\(firstname) \(lastname)"
  }
}

Если вы снова запустите тест, вы увидите, что теперь он проходит. Потрясающий! Мы только что использовали разработку через тестирование, чтобы добавить функцию в структуру пользователя.

Если вы хотите узнать больше о TDD и о том, как тестировать множество различных сценариев разработки под iOS, я пишу об этом книгу. Это все еще в процессе, но вы уже можете получить его в обеденный паб.

Похожие записи

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *