Как реализовать unit test для функции getValue
Что проверяют
Умеете ли вы превратить абстрактную функцию в набор проверяемых сценариев и изолировать её от внешнего состояния. Хороший кандидат первым делом уточняет, откуда getValue берёт данные, а интервьюер следом просит протестировать версию, которая читает из UserDefaults или сети.
Как отвечать
Начните с вопроса, что делает функция и от чего зависит. Если она чистая, тест простой. Если внутри UserDefaults.standard, кеш или сетевой клиент, вынесите зависимость в протокол и передайте её через инициализатор.
Каждый тест строится по схеме Arrange, Act, Assert: подготовили данные, вызвали функцию, проверили результат. Сценарии:
- ключ есть: возвращается ожидаемое значение;
- ключа нет:
nilили ошибка, смотря по контракту; - значение другого типа: по ключу лежит строка, а ждём
Int; - граничные случаи: пустой ключ, значение по умолчанию, повторный вызов.
Инструменты в Xcode: XCTest с XCTestCase, XCTAssertEqual, XCTAssertNil, XCTUnwrap и setUp/tearDown, либо Swift Testing, появившийся в Xcode 16: @Test, #expect, #require и параметризованные тесты через @Test(arguments:), удобные как раз для таблицы «ключ, ожидаемый результат». Код приложения подключается через @testable import.
Для UserDefaults в тесте создают отдельный набор UserDefaults(suiteName:) и после теста чистят его через removePersistentDomain(forName:). Асинхронную версию тестируют методом async throws, без ожиданий на таймерах.
Где спотыкаются
Тестируют стандартную библиотеку: захардкодили словарь внутри функции и проверили, что словарь возвращает значение. Логики вашего кода в таком тесте нет.
Используют UserDefaults.standard или общие синглтоны. Тесты начинают зависеть от порядка запуска и падают при параллельном прогоне.
Разворачивают опционалы через !. При ошибке падает весь прогон вместо одного понятного провала, для этого есть XCTUnwrap и #require. Вызывать defaultTestSuite.run() вручную тоже не нужно, тесты запускает Xcode.