Настройка PHPUnit перед запуском первого теста и срыв после запуска последнего теста
Я пытаюсь реализовать утилиту Django для тестирования для php-приложения, используя PHPUnit. По Django, я имею в виду, что отдельный тестовый db создается из основной базы данных перед запуском первого теста, и он упал после запуска последнего теста. Тестовый db необходимо создать только один раз, даже если одновременно запускается много тестовых случаев.
Для этого я принял следующий подход -
Я определил собственный класс тестового набора, чтобы я мог написать код для создания и удаления db в его методах настройки и удаления, а затем использовать этот класс для запуска тестов следующим образом
$ phpunit MyTestSuite
MyTestSuite определяет статический метод с именем suite
, где я просто использую glob
и добавляю тесты к testuite следующим образом
public static function suite() {
$suite = new MyTestSuite();
foreach (glob('./tests/*Test.php') as $tc) {
require_once $tc;
$suite->addTestSuite(basename($tc, '.php'));
}
return $suite;
}
Все классы Test Case распространяются от подкласса PHPUnit_Framework_TestCase
, а методы установки и разборки этого класса обеспечивают загрузку и очистку исходных данных из файлов json fixture.
Теперь как нет. тестов увеличивается, мне нужно запускать только выбранные тесты за раз. Но поскольку я уже загружаю тесты с помощью набора тестов, опция -filter не может использоваться.
Это заставляет меня чувствовать, что этот подход, возможно, не был правильным.
Итак, мой вопрос: какой правильный подход сделать что-то перед запуском первого теста и после запуска последнего теста независимо от того, как PHPUnit находит их?
PS: Я не использую PHPUnit_Extensions_Database_TestCase, но моя собственная реализация создания, заполнения и удаления db.
Ответы
Ответ 1
Мои две спонтанные идеи, которые не используют "Test Suites"
. То, что делает, находится внизу.
Тестировщик
Используя PHPUnits test listeners
, вы можете сделать
public function startTestSuite(PHPUnit_Framework_TestSuite $suite)
{
if($suite->getName() == "yourDBTests") { // set up db
}
public function endTestSuite(PHPUnit_Framework_TestSuite $suite)
{
if($suite->getName() == "yourDBTests") { // tear down db
}
Вы можете определить все ваши тесты БД в testuite в файле конфигурации xml, как показано in the docs
<phpunit>
<testsuites>
<testsuite name="db">
<dir>/tests/db/</dir>
</testsuite>
<testsuite name="unit">
<dir>/tests/unit/</dir>
</testsuite>
</testsuites>
</phpunit>
Bootstrap
Используя загрузочный файл phpunits, вы можете создать класс, который создает БД, и срывает его в своем собственном методе __destruct
, когда процесс завершится.
Помещение ссылки на объект в какой-либо глобальной области будет гарантировать, что объект будет только разрушен в конце всех тестов. (Как пояснил @beanland: Использование register_shutdown_function() делает намного больше смысла!)
Использование тестовых наборов:
http://www.phpunit.de/manual/3.2/en/organizing-test-suites.html показывает:
<?php
class MySuite extends PHPUnit_Framework_TestSuite
{
public static function suite()
{
return new MySuite('MyTest');
}
protected function setUp()
{
print "\nMySuite::setUp()";
}
protected function tearDown()
{
print "\nMySuite::tearDown()";
}
}
class MyTest extends PHPUnit_Framework_TestCase
{
public function testWorks() {
$this->assertTrue(true);
}
}
это хорошо работает в PHPUnit 3.6 и будет работать в версии 3.7. Это не в текущих документах, поскольку "классы тестового набора" несколько устарели/обескуражены, но они собираются в течение некоторого времени.
Обратите внимание, что срыв и настройка всего db для каждого тестового примера могут быть весьма полезны для борьбы с межтестовыми зависимостями, но если вы не будете запускать тесты в памяти (например, в памяти SQL), скорость может не стоить он.
Ответ 2
Недавно я столкнулся с чем-то, где мне нужно было решить ту же проблему. Я попробовал Edorian answer с помощью метода __destruct
пользовательского класса, но, похоже, он запускался в конце каждого теста, а не по завершении всех тестов.
Вместо использования специального класса в моем файле bootstrap.php я использовал PHP register_shutdown_function
для обработки очистки базы данных после завершения всех моих тестов, и казалось, что он отлично работает.
Вот пример того, что у меня было в файле bootstrap.php
register_shutdown_function(function(){
some_db_cleanup_methods();
});