---
# System prepended metadata

title: iOS-Инкубатор. Unit-тесты и TDD

---

# iOS-Инкубатор. Unit-тесты и TDD

24 ноября 2022

## Тесты

Тесты необходимы для подтверждения работоспостобности как всего приложения, так и отдельных его узлов.

![](https://i.imgur.com/pJRiKWL.png)

Если можно утвердждать, что для данного объекта его инварианты выполнены, эти утверждения должны быть доказаны тестами и проверяться при модификации объекта, то можно избежать огромного количества проверок как внутри методов объекта, так и при использовании его клиентами.

Мы всегда гоняем тесты. Но выбор за нами -- стоит ли это автоматизировать!

## Test Style Guide 

Имя `unit`-теста составное и содержит **4** части:

```swift
func test_login_withValidData_shouldStatusOnSuccess()
```

1. `test` - начало тестовой функции;
2. `login` - тестируемая функция;
3. `withValidData` - параметры тестирования (если нужны);
4. `shouldStatusOnSuccess` - ожидаемый результат теста.

## Частые вопросы на собеседовании

1. Что такое SUT, Dummy, Fake, Stub, Mock?
1. В чем заключается подход AAA при написании теста?
1. Для чего используются функции setUp(), tearDown() при написании TestCase?
1. Для чего используется @testable?
1. Что такое TDD?

### Что такое SUT, Dummy, Fake, Stub, Mock?

SUT -- System Under Test

Согласно Жерару Месарошу, существует 5 видов тестовых двойников:

-   Пустышка (dummy)
-   Стаб (stub)
-   Шпион (spy)
-   Мок (mock)
-   Фейк (fake)

![](https://i.imgur.com/vvTfciK.png)

#### Stub

Заглушки предоставляют готовые ответы на вызовы, сделанные во время теста, обычно не отвечая ни на что, кроме того, что запрограммировано для теста.

#### Dummy

Объекты-пустышки передаются, но фактически никогда не используются. Обычно они нужны просто для заполнения списков параметров.

#### Fake

Фальшивые объекты на самом деле имеют рабочие реализации, но используют некоторые сокращения, которые делают их непригодными для производства.


#### Mock

`Mock` — очень похож на `Stub`, но основан на взаимодействии, а не на состоянии. Это означает, что вы не ожидаете, что `Mock` вернет какое-то значение, но предполагаете, что выполняется определенный порядок вызовов методов.


#### Spy

Шпион: фиктивный фрагмент кода, который перехватывает некоторые вызовы реального фрагмента кода, позволяя вам проверять вызовы без замены всего исходного объекта.

### В чем заключается подход AAA при написании теста?

AAA (Arrange, Act, Assert) паттерн

Если посмотреть на юнит тест, то для большинства можно четко выделить 3 части кода:

- **Arrange** (настройка) — в этом блоке кода мы настраиваем тестовое окружение тестируемого юнита;
- **Act** (выполнение) — выполнение или вызов тестируемого сценария;
- **Assert** (проверка) — проверка того, что тестируемый вызов ведет себя определенным образом.


```swift
// Arrange
let sut = makeSUT()
let taskTypes = TaskType.Inventory.allCases
let notificationSoundName = UNNotificationSoundName(rawValue: "taskNotificationSound.caf")

//Act
let result: [Bool] = taskTypes.map {
			sut.makeNotificationSoundName(taskType: TaskType.inventory($0)) == notificationSoundName
}

//Assert
result.forEach { XCTAssertTrue($0, "Ошибка создания звука задания для Inventory") }
```

### Given-When-Then


- `Given` описывает предварительные условия и начальное состояние перед началом теста и допускает любую предварительную настройку, которая может произойти. 

- `When` описывает действия, предпринятые пользователем во время теста. 

- `Then` описывает результат действий, предпринятых в предложении 

```swift=
func test_loadView_shouldHaveCorrectTitle() {

	// Given
	let sut = makeSUT()

	// When
	sut.loadViewIfNeeded()

	// Then
	XCTAssertEqual(
		sut.title,
		L10n.SearchViewController.title,
		"Установлен неверный заголовок"
	)
}
```

### Для чего используются функции setUp(), tearDown() при написании TestCase?

- setUp -- для подготовки тестов к запуску
- tearDown -- для очистки после работы тестов

Каждый тест запускает setUp до и tearDown после совей работы!


### Для чего используется @testable?

Применяйте этот атрибут для импорта объявлений для компилируемых модулей с включенным режимом тестинга для доступа к сущностям с уровнем доступа internal как будто они имеют уровень доступа public.

![](https://i.imgur.com/oFeWnPY.png)


### Что такое TDD?

TDD расшифровывается как Test Driven Development (разработка через тестирование). 

![](https://i.imgur.com/xjHYvZL.png)

TDD -- это не про то, когда пишется тесты на все приложение, а потом пишут код, чтобы приложение заработало.

TDD -- это про то, что каждая строка кода должна сперва быть покрыта тестом. 

- Сперва пишем тест
- Он проваливается
- Рефакторим код
- Тест проходит успешно
- Повторить цикл


Со временем, практикуя TDD скорость разработки только увеличтся, но как побочный эффект будет то, что к вашему коду уже будут написаны тесты.

## Задача

Для следующей сессии Инкубатора мы будем реализовывать задачу.

### Написать приложение TODO-List

> [!abstract] Приложение
> Нам нужен список дел, который содержит отдельные задачи. Эти задачи можно добавлять и удалять из списка. Каждый пункт должен уметь быть либо выполненным либо нет и содержать дату выполнения. Кроме того, задачи можно решать только в очередности их добавления.
****

## Дополнительные материалы

- https://www.avanderlee.com/swift/unit-tests-best-practices/
- https://medium.com/capital-one-tech/using-stub-vs-mock-in-ios-unit-testing-634ec4cc6a10