Сбой XCTestCase с утверждением без продолжения теста, но без остановки других тестов
Я пытаюсь протестировать свое приложение с помощью фреймворка XCTest.
Я хочу, чтобы мой единственный контрольный пример провалился, если выполняется какое-то логическое условие (используя утверждение).
Я не хочу, чтобы остальная часть кода в тестовом примере выполнялась, потому что это может привести к проблемам (например, доступ к нулевым указателям)
Я также хочу, чтобы остальная часть тестового примера работала нормально, и только неудачный тест был помечен как неудачный.
Я заметил, что XCTestCase имеет свойство continueAfterFailure.
Однако, установив его в YES, вынудивший неудовлетворительный тест продолжать выполнение строк после подтверждения, а установив его в NO, остальные тесты вообще не запускались.
Есть ли решение этой проблемы?
Ответы
Ответ 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()
.