Тестирование 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();
}