# 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