Xcode: TEST против макросов препроцессора DEBUG - PullRequest
34 голосов
/ 19 июля 2011

При создании нового проекта с модульными тестами XCode устанавливает конфигурацию сборки на Debug для схемы Test (то же самое для схемы Run).

Должен ли я различать Run (Command-R) и Test (Схемы Command-U)?

Т.е. мне следует создать новую конфигурацию сборки под названием Test, добавить к ней макрос препроцессора TEST = 1 и использовать вместо этого в качестве конфигурации сборки для схемы Test?Или я должен оставить Run & Test для Debug?

Я пришел из Ruby / Rails-среды, где у вас обычно есть среда тестирования, разработки и производства.Мне кажется, что Debug - это как разработка, а Release - как производство, но мы пропускаем тест, поэтому я думаю, что имеет смысл добавить Test.

Комментарии?Мнения?Предложения?

Я специально спрашиваю об этом, потому что хочу скомпилировать что-нибудь для Test с помощью:

#ifdef TEST
// Do something when I test.
#endif

Не думаю, что это имеет значение, если я также скомпилирую это для Debug.Итак, я действительно мог бы просто сделать:

#ifdef DEBUG
// Do something when I run or test.
#endif

Но я сейчас действительно собираюсь сделать это только для тестов.Итак, вот почему я думаю, что должен различать отладку и тестирование, но мне интересно, почему XCode не делает это для вас по умолчанию?Apple считает, что вы не должны различать их?

Ответы [ 11 ]

29 голосов
/ 15 января 2014

Макросы препроцессора не будут работать, вам нужно проверить среду во время выполнения.

static BOOL isRunningTests(void)
{
    NSDictionary* environment = [[NSProcessInfo processInfo] environment];
    return (environment[@"XCInjectBundleInto"] != nil);
}

(Обновлено для Xcode 7.3)

28 голосов
/ 06 февраля 2013

Возможно, вы захотите добавить новую конфигурацию сборки.

В xcode 4, нажмите на ваш проект в навигаторе слева.

В главном окне щелкните свой проект, а затем выберите вкладку «Информация».

Нажмите кнопку «+», чтобы добавить новую конфигурацию (если хотите, вы можете назвать свою «тестовой»).

Теперь нажмите на цель и перейдите на вкладку настроек сборки.

Поиск "макросов препроцессора"

Здесь вы можете добавить макросы препроцессора для новой конфигурации сборки.

Просто дважды щелкните по вашей новой "тестовой" конфигурации и добавьте TESTING = 1.

Наконец, отредактируйте схему сборки. Выберите параметры теста для вашей схемы. Должно быть выпадающее меню «Конфигурация сборки». Выберите свою «тестовую» конфигурацию.

24 голосов
/ 20 июля 2011

Вместо создания конфигурации тестовой сборки I:

  1. создал файл Tests-Prefix.pch:

    #define TEST 1
    #import <SenTestingKit/SenTestingKit.h>
    #import "CocoaPlant-Prefix.pch"
    
  2. ввел свой путьв поле «Заголовок префикса» параметров сборки цели «Тесты».

  3. добавил следующий код в начало созданного мной файла с именем MyAppDefines.h, импортированного в MyApp-Prefix.pch:

    #ifdef TEST
    #define TEST_CLASS NSClassFromString(@"AppDelegateTests") // any test class
    #define BUNDLE [NSBundle bundleForClass:TEST_CLASS]
    #define APP_NAME @"Tests"
    #else
    #define BUNDLE [NSBundle mainBundle]
    #define APP_NAME [[BUNDLE infoDictionary] objectForKey:(NSString *)kCFBundleNameKey]
    #endif
    

Это позволяет мне использовать BUNDLE везде, где я имею в виду [NSBundle mainBundle], и также работать, когда я запускаю тесты.

Импортировать SenTestingKit в Tests-Prefix.pchускоряет компиляцию SenTestingKit Framework и позволяет опустить #import <SenTestingKit/SenTestingKit.h> из верхней части всех тестовых файлов.

16 голосов
/ 29 августа 2014

Я решил добавить проверку для переменной окружения в самом коде вместо того, чтобы использовать предложение isRunningTests (), которое сделал Роберт.

  1. Изменить текущую схему (Продукт / Схема / Изменить схему) или Команда + <</li>
  2. Нажмите на тестовую конфигурацию
  3. Нажмите на аргументы Снимите флажок «Использовать аргументы действия« Выполнить »и переменные среды»
  4. Разверните раздел Environment Variable и добавьте переменную TESTING со значением YES
  5. Добавьте это к своему коду где-нибудь и звоните, когда вам нужно:
 + (BOOL) isTesting
    {
        NSDictionary* environment = [[NSProcessInfo processInfo] environment];
        return [environment objectForKey:@"TESTING"] != nil;
    }

Экран должен выглядеть следующим образом.

The screen should look like this

Приведенный выше код найдет переменную среды TESTING при работе в тестовом режиме или в режиме приложения. Этот код входит в ваше приложение, а не в файлы модульного теста. Вы можете использовать

#ifdef DEBUG
...
#endif

Для предотвращения выполнения кода в производстве.

5 голосов
/ 02 апреля 2017

Ответ Роберта в SWIFT 3.0:

func isRunningTests() -> Bool {
    let environment = ProcessInfo().environment
    return (environment["XCInjectBundleInto"] != nil);
}
2 голосов
/ 11 июня 2018

Если вы создадите конфигурацию тестовой сборки и затем установите для свойства «Другие флаги Swift» вашей цели значение «-DTEST», это определит макрос TEST, который будет работать в вашем коде swift. Убедитесь, что вы установили его в настройках сборки целевого приложения, чтобы использовать его в коде Swift вашего приложения.

Other Swift Flags setting for DEBUG and TEST

Затем с помощью этого набора вы можете проверить свой код следующим образом:

func testMacro() {
   #if !TEST 
       // skipping over this block of code for unit tests
   #endif
}
2 голосов
/ 18 декабря 2012

Я тестировал так долго, нашел результат:

Мало того, что вы добавили макрос препроцессора в свою цель модульного теста (у вас может быть много методов , использующих переменные только для модульного тестирования и следуйте методам @MattDiPasquale),

, но также необходимо добавить файл соответствия условий в цель теста.мы должны перекомпилировать этот файл, потому что у вас есть новый макрос препроцессора для этого файла, но этот файл имеет встроенную цель приложения в тот момент, когда ваш макрос препроцессора не был установлен.

Надеюсь, это поможет вам.

1 голос
/ 26 ноября 2018

Обновлено для Xcode10:

static let isRunningUnitTests: Bool = {
    let environment = ProcessInfo().environment
    return (environment["XCTestConfigurationFilePath"] != nil)
}()
0 голосов
/ 13 августа 2017

Модифицированная версия ответа Кева, которая работает для меня на Xcode 8.3.2

+(BOOL)isUnitTest {

    static BOOL runningTests;
    static dispatch_once_t onceToken;

    // Only check once
    dispatch_once(&onceToken, ^{
        NSDictionary* environment = [[NSProcessInfo processInfo] environment];
        if (environment[@"XCTestConfigurationFilePath"] != nil && ((NSString *)environment[@"XCTestConfigurationFilePath"]).length > 0) {
            runningTests = true;
        } else {
            runningTests = false;
        }
    });
    return runningTests;
}
0 голосов
/ 18 ноября 2015

В iOS [UIApplication sharedApplication] вернет nil при выполнении модульного теста.

...