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

Сбой XCTestCase с утверждением без продолжения теста, но без остановки других тестов

Я пытаюсь протестировать свое приложение с помощью фреймворка XCTest.

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

Я заметил, что XCTestCase имеет свойство continueAfterFailure. Однако, установив его в YES, вынудивший неудовлетворительный тест продолжать выполнение строк после подтверждения, а установив его в NO, остальные тесты вообще не запускались.

Есть ли решение этой проблемы?

4b9b3361

Ответ 1

Ответ Паскаля дал мне идею добиться этого правильно. XCTool теперь ведет себя как OCUnit, когда утверждение терпит неудачу: выполнение тестового примера прерывается немедленно, вызывается tearDown и запускается следующий тестовый пример.

Просто переопределите метод invokeTest в базовом классе (тот, который наследуется от класса XCTestCase):

- (void)invokeTest
{
    self.continueAfterFailure = NO;

    @try
    {
        [super invokeTest];
    }
    @finally
    {
        self.continueAfterFailure = YES;
    }
}

Что это!

Ответ 2

Самый простой способ - добавить:

continueAfterFailure = false

в метод setUp(). Так оно будет выглядеть так:

Swift

override func setUp() {
    super.setUp()

    continueAfterFailure = false
}

Objective-C

 - (void)setUp {
    [super setUp];

    [self setContinueAfterFailure:NO];
}

Ответ 3

Один из вариантов - проверить состояние в нормальном режиме, затем выполнить сбой и вернуться из теста, если оно ложное.

Примерно так:

if (!condition) {
  XCFail(@"o noes");
  return;
}

Вы можете обернуть это в вспомогательный макрос, чтобы сохранить читабельность.

Библиотеки тестов BDD, такие как Kiwi, более изящны для такого рода вещей, поскольку они упрощают распределение настроек между многими тестами, что приводит к меньшему количеству утверждений на тест.

Ответ 4

Я могу использовать continueAfterFailure, а остальные тесты выполняются с использованием этого шаблона:

self.continueAfterFailure = NO;
@try
{
    // Perform test code here
}
@finally
{
    self.continueAfterFailure = YES;
}

Ответ 5

В проектах Swift я использую вспомогательную функцию (определенную в общем суперклассе всех моих тестов, которая сама расширяет XCTestCase):

/// Like 'XCTFail(...)' but aborts the test.
func XCTAbortTest(_ message: String, 
                  file: StaticString = #file, line: UInt = #line
                 ) -> Never {
    self.continueAfterFailure = false
    XCTFail(message, file: file, line: line)
    fatalError("never reached")
}

Как следует из комментария, вызов fatalError фактически никогда не выполняется; XCTFail прерывает тестирование упорядоченным образом (вызывается tearDown, следующие тестовые прогоны и т.д.). Вызов только для того, чтобы заставить компилятор принять Never в качестве возвращаемого типа, поскольку XCTFail возвращает Void (он возвращает, если continueAfterFailure == true).

Обратите внимание, что self.continueAfterFailure сбрасывается на значение по умолчанию true для каждого метода тестирования. Вы также можете сделать это явным образом в setUp().