TDD: Как проверить поиск? - PullRequest
       21

TDD: Как проверить поиск?

8 голосов
/ 14 сентября 2011

Мой сайт будет иметь расширенный поиск. Pleople может пойти туда и искать права (например, автомобили). Я создал несколько тестов, которые проверяют количество результатов на основе параметров поиска. Я думаю о том, какие тесты я должен написать, затем я пишу его, затем добавляю данные в базу данных тестов. Но тут возникает проблема. Когда я вставляю новые значения в базу данных, мои старые тесты ломаются. Это потому, что я проверяю количество записей ...

<?php defined('SYSPATH') or die('No direct access allowed!');

class Search_Test extends PHPUnit_Extensions_Database_TestCase
{
    /**
     * @return PHPUnit_Extensions_Database_DB_IDatabaseConnection
     */
    public function getConnection()
    {
        $pdo = new PDO('mysql:dbname=db_test;host=127.0.0.1', 'root', null);
        return $this->createDefaultDBConnection($pdo, 'db_test');
    }

    /**
     * @return PHPUnit_Extensions_Database_DataSet_IDataSet
     */
    public function getDataSet()
    {
        $fixture = realpath(dirname(__FILE__).'/../data/fixture.xml');
        return $this->createXMLDataSet($fixture);
    }

    public function numberOfResultsDataProvider()
    {
        return array(
            array(1, null, null, 1),
            array(2, null, null, 3),
            array(3, null, null, 0),
            array('abc', null, null, 5),
            array(null, 1996, 2003, 3),
            array(null, 1996, 1999, 2),
            array(null, 2002, 2003, 1),
            array(null, 1500, 1800, 0),
            array(null, 2003, 2003, 1),
            array(null, null, 2005, 4),
            array(null, 1996, null, 4),
            array(null, null, null, 4),
            array(null, 2003, 1996, 0),
            array(null, 'abc', 2003, 4),
            array(null, '1996', '1999', 2),
            array(2, 2003, 2005, 2),
            array(null, null, null, 4),
        );
    }

    /**
     * @dataProvider numberOfResultsDataProvider
     */
    public function testNumberOfResults($brandId, $startYear, 
        $endYear, $numberOfResults
    ) {
        $search = ORM::factory('search');
        $search->setBrand($brandId)
            ->setYearRange($startYear, $endYear);
        $results = $search->results();
        $this->assertEquals($results->count(), $numberOfResults);
    }
}
?>

Это нормально? Должны ли мои старые тесты ломаться при создании новых тестов?

Должны ли мои тесты быть привязаны к данным?

В моем поиске слишком много параметров, и они будут использоваться в одной форме (просмотр). Должен ли я создавать тесты для поиска каждого параметра или я должен тестировать их вместе? Должен ли я разделить его на несколько тестовых классов?

Спасибо.

Ответы [ 5 ]

6 голосов
/ 14 сентября 2011

при выполнении модульного теста, включающего базу данных, тест должен предоставлять фактическую базу данных, с которой он будет проверяться.Это может быть просто простая база данных, которая содержит только значения, относящиеся к тесту, например одну строку, которая будет соответствовать, и одну строку, которая не соответствует.Также разумно создать несколько тестов для моментального снимка действующей базы данных, поскольку она существовала в определенный момент времени.

Одним из особенно удобных способов достижения этого является для нас база данных Sqlite3 специально для тестаи настройте приложение на использование этого для теста.

1 голос
/ 14 сентября 2011

Короче говоря:
Нет способа сделать это в действующей базе данных

Вам нужна отдельная база данных для тестов. Это может быть макет базы данных на самом деле.

Затем, перед тестами, вам нужно подготовить базу данных, чтобы она была в фиксированном состоянии , как вы ожидаете (например, загрузка данных из фиксаторов или импорт файла sql).

Тогда лучшим вариантом будет запуск транзакции базы данных , когда вы планируете внести какие-либо изменения в исходное состояние базы данных.

После запуска транзакции вы можете работать с базой данных.

После завершения тестов вы просто откатываете транзакцию и получаете базу данных в чистом состоянии.

Sqlite (уже упоминалось) в большинстве случаев будет работать нормально, но может отличаться от действующей базы данных. В любом случае, наличие другой базы данных адаптеров будет очень полезно.

1 голос
/ 14 сентября 2011

Если это вообще возможно, вы должны разорвать связь между тем, как ваш код извлекает ваши данные, и самой базой данных.Ваши модульные тесты не должны зависеть от базы данных, и вы наткнулись на несколько причин, по которым: вы должны поддерживать свои данные в разных тестах, создание новых тестов приводит к тому, что другие ломаются и т.Если бы вы могли каким-то образом подделать точку доступа к данным и вернуть данные строго в памяти, это было бы идеальным случаем.Я не знаю, насколько это было бы легко в PHP, но построение интерфейса вокруг вашего кода доступа к данным и использование фиктивной / поддельной реализации этого интерфейса может помочь в достижении этой цели.

0 голосов
/ 14 сентября 2011

Я хотел бы, чтобы каждый метод тестирования создавал свои собственные данные, затем выполнял их поиск, утверждал и затем уничтожал свои собственные выборочные данные.

Обычно у меня будет общий метод addData (), а затем метод очистки базы данных. Надеюсь, вы сможете каким-то образом сделать добавленные данные идентифицируемыми, чтобы ваш метод очистки мог быть универсальным. В вашем примере, возможно, вы могли бы начать все ваш brandId с «test-», а затем ваш запрос будет искать и удалять все записи, где brandId похож на «test -%».

0 голосов
/ 14 сентября 2011

Ваши тесты должны не прерываться при создании новых тестов, и ваши тесты должны не зависеть от данных.Тест, который требует определенных данных в базе данных, должен поместить эти данные в базу данных.И если для этого требуется, чтобы в базе данных не было других данных, он должен очистить все остальное.

Это, конечно, замедлит ваши тесты - так что смоделируйте слой доступа к данным.

...