PHPUnit: несколько утверждений в одном тесте, только первый сбой
Следующая странность, которую я вижу с помощью PHPUnit:
class DummyTest extends PHPUnit_Framework_TestCase {
public function testDummy() {
$this->assertTrue(false, 'assert1');
$this->assertTrue(false, 'assert2');
}
public function testDummy2() {
$this->assertTrue(false, 'assert3');
}
}
Как только первое утверждение терпит неудачу в тесте, остальная часть теста игнорируется.
Итак (с простым вызовом phpunit DummyTest.php):
-
В приведенном выше коде будут отображаться 2 теста,
2, 2. Что?
-
Если я пройду все тесты, то
Я получу ОК (2 теста, 3 утверждения).
Хорошо.
-
Если я сделаю все тесты пройденными
за исключением assert2, я получаю 2 теста, 3
утверждения, 1 сбой. Хорошо.
Я не понимаю, но PHPUnit существует уже целую вечность, конечно, это должен быть я?
Мало того, что подсчеты не то, что я ожидаю, отображается только сообщение об ошибке для первого отказавшего подтверждения в приведенном выше коде.
(BTW, я анализирую XML-формат, сгенерированный PHPUnit для CI, вместо проверки реального кода, следовательно, практика множественных утверждений в одном тесте.)
Ответы
Ответ 1
Прежде всего: это ожидаемое поведение.
Каждый тестовый метод прекращает выполнение, как только утверждение терпит неудачу.
Для примера, где противоположное будет очень раздражать *:
class DummyTest extends PHPUnit_Framework_TestCase {
public function testDummy() {
$foo = get_me_my_foo();
$this->assertInstanceOf("MyObject", $foo);
$this->assertTrue($foo->doStuff());
}
}
если phpunit не остановится после первого утверждения, вы получите E_FATAL (вызов функции не-член), и весь процесс PHP будет умирать.
Итак, чтобы сформулировать хорошие утверждения и небольшие тесты, это более практично.
Для другого примера:
Когда "утверждая, что массив имеет размер X, а затем утверждая, что он содержит a, b и c", вам не важно, что он не содержит эти значения, если размер равен 0.
Если тест терпит неудачу, вам обычно просто нужно сообщение "почему это не удалось", а затем, исправляя его, вы автоматически убедитесь, что другие утверждения также проходят.
Кроме того, есть люди, которые утверждают, что вы должны иметь One Asssertion per Test case
, пока я не занимаюсь (и я не уверен, нравится ли мне это) Я хотел бы это отметить;)
Ответ 2
Добро пожаловать в модульное тестирование. Каждая тестовая функция должна проверять один элемент или процесс (процесс представляет собой ряд действий, которые может предпринять пользователь). (Это единица и почему ее называют "модульным тестированием".) Единственный раз, когда вам нужно иметь несколько утверждений в тестовой функции, является то, что часть теста зависит от успешной предыдущей части.
Я использую это для веб-страниц тестирования Selenium. Поэтому я могу утверждать, что каждый раз, когда я перехожу на новую страницу, я нахожусь в нужном месте. Например, если я перейду на веб-страницу, затем войдите в систему, а затем измените свой профиль, я бы сказал, что попал в нужное место, когда я вошел в систему, потому что тест больше не имеет смысла, если мой логин завершился неудачно. Это мешает мне получать дополнительные сообщения об ошибках, когда встречалась только одна проблема.
С другой стороны, если у меня есть два отдельных процесса для тестирования, я бы не тестировал их, а затем продолжал тестировать другой в той же функции, потому что ошибка в первом процессе замаскировала бы любые проблемы во втором. Вместо этого я бы написал одну тестовую функцию для каждого процесса. (И если один процесс зависел от успеха другого, например, размещал что-то на странице, а затем удалял сообщение, я бы использовал аннотацию @depends, чтобы предотвратить запуск второго теста, если первый сбой.)
Короче говоря, если ваш первый признак неудачи не делает второй невозможной для тестирования, то они должны быть в отдельных функциях. (Да, это может привести к избыточному коду.При модульном тестировании забудьте все, что вы узнали об исключении избыточного кода.Таким образом, или не выполняйте функции тестирования и вызывают их из тестовых функций.Это может сделать более сложным тестирование модулей, и, следовательно, сложнее обновить, когда изменения будут внесены в тему тестов.)
Я понимаю, что этот вопрос составляет 2 года, однако единственный ответ был не совсем ясен о том, почему. Я надеюсь, что это поможет другим лучше понять модульное тестирование.