Тестирование Phpunit с помощью базы данных
Я пытаюсь сосредоточиться на модульном тестировании с помощью PHPunit.
Я нашел здесь очень хороший учебник http://blog.nickbelhomme.com/php/phpunit-training-course-for-free_282
Но есть кое-что, что я пропустил и еще не понимаю, как это сделать.
У меня есть пользовательский модуль, который поддерживает всю информацию о пользователях. И есть функция save, которая сохраняет пользователя в базе данных. Поэтому у меня есть testFunction
public function testCanCreateUser()
{
$userData = array(
'userName' => 'User1',
'firstName' => 'Joey',
'lastName' => 'Hendricks',
'email' => '[email protected]',
'password' => 'f$tfe8F'
);
$user = new Model_User($userData);
$user->save();
}
В первый раз, когда я проведу свой тест, эта работа будет работать. Поскольку база данных пуста. Но когда я запускаю свои тесты во второй раз, это не сработает, так как моя система не позволяет одному и тому же пользователю дважды в db. Поэтому для этого мне нужно каждый раз воссоздавать свою тестовую базу, прежде чем запускать тесты. Каков наилучший способ сделать это?
Или эта проблема должна решаться по-другому?
Tnx.
Ответы
Ответ 1
Если вы хотите протестировать свою бизнес-логику: Откажитесь от класса базы данных и верните поддельные данные
Если вы хотите протестировать класс, который запускает операторы sql (и imho, вы можете проверить это тоже, так как я просто хочу знать, работает ли мой код с реальным db в бэкэнд), он получает немного сложнее, но есть способы сделать это:
-
Используя setUp() и tearDown(), чтобы получить согласованное состояние для данных перед запуском ваших тестов, это (imho) прекрасный способ записи db-driven unittests. Это может раздражать, чтобы писать много пользовательских sql вручную.
-
Чтобы сделать вашу жизнь проще, вы можете посмотреть расширение DbUnit и посмотреть, работает ли это для вашего приложения.
-
Если вы действительно хотите погрузиться в взаимодействие с базами данных Unittesting, лучше всего читать по теме (imho) в главе о db-unittesting в Себастьян Бергманнс phpqa.
-
Может ли ваше приложение разрешить настраиваемое имя базы данных и автоматическую настройку всех таблиц, также может быть возможно установить db один раз с большим количеством тестовых данных и использовать эти данные во всех ваших тестах. Вы можете быть осторожны, хотя один тест не зависит от данных, написанных другим.
Ответ 2
Запустите тесты с другой копией базы данных, которая пуста и/или очищена в методах setUp()
или tearDown()
, но будьте осторожны, чтобы не делать то, что github сделал.
Если вы используете хорошую базу данных (т.е. не MySQL с таблицами MyISAM), вы можете обернуть тест в транзакции и отбросить ее после теста:
function setUp() { $this->db->exec("BEGIN"); }
function tearDown() { $this->db->exec("ROLLBACK"); }
Недостатком является то, что вы не можете тестировать код, который использует транзакции (если вы не абстрагируете это и не эмулируете с помощью точек сохранения, но это iffy).
В идеале вы должны использовать инъекции зависимостей и запускать тесты в поддельном классе базы данных:
$fakedb = new DatabaseThatDoesntReallySaveThings();
$user = new Model_User($fakedb, $userData);
$user->save();
$this->assertTrue($fakedb->wasAskedToSaveUser());
Ответ 3
Я думаю, вы можете использовать метод tearDown()
для очистки сохраненных данных.
protected $_user;
public function testCanCreateUser()
{
...
$this->_user = new Model_User($userData);
$this->_user->save();
}
public function tearDown()
{
$this->_user->delete();
}