Ошибка XCTestCase с assert без продолжения выполнения теста, но без остановки других тестов

Я пытаюсь протестировать свое приложение, используя платформу XCTest.

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

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

Есть ли решение этой проблемы? Спасибо, Йоав

5 ответов

Решение

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

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

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

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

Это оно!

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

continueAfterFailure = false

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

стриж

override func setUp() {
    super.setUp()

    continueAfterFailure = false
}

Objective-C

 - (void)setUp {
    [super setUp];

    [self setContinueAfterFailure:NO];
}

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

Что-то вроде этого:

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

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

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

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

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

В проектах 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(),

Другие вопросы по тегам