Подтвердить что ты не робот

Swift - unit test и частные вары

Я пишу BDD unit test для общедоступного метода . Метод изменяет частное свойство (private var), поэтому я хотел бы написать expect() и убедиться, что он установлен правильно. Поскольку он закрыт, я не могу решить, как получить доступ к нему из unit test.

Для Objective-C я просто добавлю заголовок расширения. Есть ли в Swift подобные трюки? В качестве примечания, свойство имеет didSet() с некоторым кодом, а также.

4b9b3361

Ответ 1

(Обратите внимание, что Swift 2 добавляет атрибут @testable, который может использовать внутренние методы и свойства для тестирования. См. комментарии @JeremyP ниже для получения дополнительной информации.)

Нет. В Swift частный частный. Компилятор может использовать этот факт для оптимизации, поэтому в зависимости от того, как вы используете это свойство, законным для компилятора является его удаление, вложение в него или выполнение каких-либо других действий, которые могли бы дать правильное поведение на основе кода, файл. (Действительно ли оптимизатор на самом деле тот умный сегодня или нет, это разрешено.)

Теперь, конечно, если вы объявите свой класс @objc, то вы можете разбить эти оптимизации, и вы можете пойти с ObjC, чтобы прочитать его. И есть причудливые обходные пути, которые могут позволить вам использовать Swift для вызова произвольных @objc открытых методов (например, zero-timeout NSTimer). Но не делайте этого.

Это классическая проблема с тестированием, и классический тестовый ответ не проверяет этот способ. Не проверяйте внутреннее состояние. Если буквально невозможно сказать извне, что что-то случилось, то нечего тестировать. Перепроектируйте объект таким образом, чтобы его можно было проверить в его общедоступном интерфейсе. И обычно это означает состав и издевательства.

Вероятно, наиболее распространенной версией этой проблемы является кэширование. Очень сложно проверить, что что-то на самом деле кэшировано, поскольку единственное различие может заключаться в том, что оно выполняется быстрее. Но это все еще проверяемо. Переместите функциональность кэширования в другой объект, и пусть ваш объект под тестом примет пользовательский объект кэширования. Затем вы можете передать макет, который записывает, были ли сделаны правильные запросы к кешу (или сетевые вызовы, или вызовы базы данных, или независимо от того, что имеет внутреннее состояние).

В основном ответ: редизайн, чтобы было легче протестировать.

ОК, но вы действительно, действительно, действительно нуждаетесь в этом... как это сделать? Хорошо, это возможно, не нарушая мир.

Создайте функцию внутри проверяемого файла, который предоставляет предмет, который вы хотите. Не метод. Просто бесплатная функция. Затем вы можете поместить эту вспомогательную функцию в #if TEST и установить TEST в своей тестовой конфигурации. В идеале я бы сделал функцию на самом деле проверять то, что вам нужно, а не подвергать переменную (и в этом случае, возможно, вы можете позволить функции быть внутренней или даже публичной). Но в любом случае.