| name | unit-testing-ios-app |
| description | Правила написания unit-тестов для iOS приложений |
Правила написания unit-тестов
Для запуска тестов используй только команду make test.
Когда применять
- При написании новых unit-тестов для iOS-проекта
- При рефакторинге существующих тестов для соответствия стандартам
- При тестировании бизнес-логики сервисов и ViewModels
- При создании мок-клиентов для тестирования интеграции с сервером
- При написании параметризированных тестов для множества сценариев
Основные принципы
1. Технологии тестирования
- Swift Testing (import Testing) - основной фреймворк
- @Test для тестовых функций
- #expect для проверок
- #require для разворачивания опционалов
2. Правила написания тестов
Синтаксис тестов
См. примеры синтаксиса в references/EXAMPLE.md.
Описания тестов
- Обязательно добавляй описание теста на русском языке в аннотации
@Test
- Используй краткие и понятные описания того, что тестируется
- Пример:
@Test("Должен возвращать правильный результат для валидных данных")
Работа с опционалами
- Всегда разворачивай опционалы перед проверками с помощью
try #require()
- Не используй знаки вопроса (?) в проверках
#expect
- Пример:
let value = try #require(optionalValue) затем #expect(value == expected)
Асинхронные тесты
- Добавляй
throws если в тесте есть try
- Не добавляй
throws если нет try в тесте
- Добавляй
async для асинхронных тестов
- Не добавляй
async если в тесте нет await
Проверки Bool условий
- Не используй равенство для Bool значений
- Используй прямое сравнение:
#expect(isTrue) или #expect(isFalse)
- Пример:
#expect(condition) вместо #expect(condition == true)
Проверка конкретных ошибок
- Используй
#expect(throws: ErrorType) для проверки конкретных типов ошибок
- Не используй do-catch блоки для проверки ожидаемых ошибок
См. примеры в references/EXAMPLE.md.
Параметризированные тесты
- Используй параметризированные тесты когда нужно протестировать несколько сценариев с разными аргументами и одинаковой логикой
- Добавляй
arguments: в аннотацию @Test с массивом значений
- Параметр функции должен соответствовать типу аргументов
- Не используй в аргументах ожидаемый результат - в аргументах должны быть только вводные данные
- Группируй тесты с одинаковым сценарием или ожидаемым результатом
- Преимущества: сокращает дублирование кода, делает тесты более читаемыми, легко добавлять новые сценарии
См. примеры в references/EXAMPLE.md.
Комментарии в тестах
- Лишние комментарии в тестах не нужны - код должен быть самодокументируемым
- Для простых сценариев комментарии не нужны вообще
- Для сложной логики можно добавить краткий комментарий внутри
#expect
- Не используй обычные комментарии (
//) над #expect
- Чем короче комментарий, тем лучше
См. примеры в references/EXAMPLE.md.
3. Структура тестов
- Один тестовый файл на модуль
- Тестировать бизнес-логику в сервисах
- Тестировать ViewModels с моками
- Не тестировать UI напрямую
- Не дублировать одинаковые сценарии в разных тестах
- Пиши простые тесты, в тестах не должно быть сложной логики и проверки разных сценариев типа "if shouldThrow {} else {}"
4. Тестирование интеграции с сервером
- Используй только мок-клиенты для тестирования запросов к серверу и для работы со Swift Data (ModelContainer)
- Никогда не отправляй реальные запросы на сервер в тестах
- Создавай общие мок-клиенты в папке с тестами для переиспользования в разных тестовых файлах
- Группируй мок-клиенты по функциональности (например,
MockProgressClient, MockAuthClient)
- Используй dependency injection для передачи мок-клиентов в тестируемые сервисы
Заключение
При написании unit-тестов всегда следуй этим правилам для обеспечения консистентности и правильности тестового кода в проекте.