Тестовые примеры PHPUnit

Я новичок в модульном тестировании; Мне нужно использовать тест PHPUnit для написания тестовых примеров! Поскольку я не видел никаких тестовых примеров, я точно не знаю, как я могу тестировать, как я могу писать тестовые примеры ... Если вы можете помочь мне протестировать один из моих небольших методов, я смогу получить хорошее видение тестирования и понять логику. Поэтому мне было интересно, не могли бы вы помочь мне с тестированием следующего метода (желательно с PHPUnit, но любые другие тестовые примеры также могут помочь мне понять логику):

static public function get_accepted_images($limit, $page, $uuid) {

    try {
        $conn = new pdo_connect();

        $query = "  SELECT ....";

        $result = $conn->prepare($query);
        $result->bindParam(':uuid', $uuid);
        $result->execute();
        $array_result = $result->fetchAll(PDO::FETCH_OBJ);
        $paginate_result = WS_Utility::paginate_array($array_result, $page, $limit);
        $result_Set = array($paginate_result, TRUE);
    } catch (Exception $e) {

        $result_Set = array($e->getMessage(), FALSE);
    }


    return $result_Set;
}

Если вам нужны дополнительные разъяснения, дайте мне знать, и мы будем благодарны вам за вашу помощь!


person Community    schedule 01.06.2014    source источник
comment
Как правило, статические методы и модульное тестирование несовместимы.   -  person GordonM    schedule 01.06.2014
comment
Вы читали документацию PHPUnit и следовали приведенным там примерам?   -  person hek2mgl    schedule 02.06.2014
comment
@GordonM Спасибо за ответ! Итак, что мне делать в этом случае? Нужно ли мне преобразовывать их один за другим в нестатические методы только для тестирования ...?   -  person    schedule 02.06.2014
comment
@ hek2mgl Да, я видел документацию; Я просто в основном видел разные методы assert; но я действительно не знаю, как я могу протестировать свой код, в котором я использовал запросы PDO и DB? Спасибо   -  person    schedule 02.06.2014
comment
Вы также читали раздел «Тестирование базы данных»?   -  person hek2mgl    schedule 02.06.2014
comment
@GordonM То, что вы говорите, не совсем правда, особенно в этом случае. статические методы могут быть проблематичными для тестов, вы правы, но только если они задают какое-то состояние. Здесь дело обстоит иначе. Поэтому метод можно без проблем опробовать.   -  person hek2mgl    schedule 02.06.2014
comment
@ hek2mgl Я почти просмотрел документацию, которую вы сказали сейчас! Но до сих пор мне непонятно проверять свою функцию! Не могли бы вы помочь мне с одним тестовым примером для моего кода? Это точно мне поможет ... Заранее спасибо   -  person    schedule 02.06.2014
comment
Я должен признать, что мне нужно снова перечитать документацию, прежде чем я смогу дать вам хороший ответ. Интерфейс тестирования базы данных PHPUnit значительно изменился с тех пор, как я использовал его в последний раз. Однако я могу это сделать и тогда приведу вам пример. Для меня было важно, чтобы вы прочитали и поняли эту документацию, потому что это минимальная основа для понимания ответов здесь. Также вполне вероятно, что вам потребуется провести рефакторинг вашего кода, чтобы получить возможность тестирования.   -  person hek2mgl    schedule 02.06.2014
comment
Да, ты прав! Мне нужно сначала прочитать этот раздел! Но теперь, даже после просмотра примеров в документации, я думаю, что они немного отличаются от моих методов, или, может быть, я не смог правильно соотнести их с моим методом! В любом случае, если у вас было время и вы могли понять это, я очень ценю вашу помощь ...   -  person    schedule 02.06.2014
comment
В порядке. Жду ответа завтра, сегодня уже поздно. Вы должны следовать руководствам из документации независимо от вашего кода во время этого. Это поможет с ней познакомиться.   -  person hek2mgl    schedule 02.06.2014
comment
Конечно; А пока я сделаю больше исследований и найду больше примеров; Я очень ценю вашу помощь :-)   -  person    schedule 02.06.2014
comment
Давайте продолжим обсуждение в чате.   -  person hek2mgl    schedule 02.06.2014
comment
Извините, я пропустил ваш чат; Я оставил вам несколько сообщений в чате; Я не уверен, видите ли вы их по-прежнему или нет; Я просто хочу знать, смогу ли я пообщаться с тобой на выходных? Я ДЕЙСТВИТЕЛЬНО ценю вашу помощь; в любое время на выходных!   -  person    schedule 03.06.2014


Ответы (2)


Сначала вы должны изменить этот метод на нестатический.

public function get_accepted_images($limit, $page, $uuid) {
    try {
        $conn = new pdo_connect();
        $query = "SELECT...";
        $result = $conn->prepare($query);
        $result->bindParam(':uuid', $uuid);
        $result->execute();
        $array_result = $result->fetchAll(PDO::FETCH_OBJ);
        $paginate_result = WS_Utility::paginate_array($array_result, $page, $limit);
        $result_Set = array($paginate_result, TRUE);
    } catch (Exception $e) {
        $result_Set = array($e->getMessage(), FALSE);
    }
    return $res;
}

Далее следует поработать над этим методом с некоторым интеграционным тестированием (НЕ ЕДИНИЧНОЕ ТЕСТИРОВАНИЕ).
Когда вы проводите интеграционное тестирование, вам все равно, как реализован метод, но вы должны точно знать контракт метода (например: на этом входе я получаю этот вывод, в этом контексте я получаю это исключение и т. д. и т. д.)

Основываясь на знании этого контракта на метод, вы начинаете выполнять интеграционные тесты:

class ImageDatabaseHelperIntegrationTest extends PHPUnit_Framework_TestCase
{
//The most simple test. When no images exists in the DB what happens?
public function testWhenNoImagesExistsReturnCorrectResult() {
    $sut = new ImageDatabaseHelper(); //I dont know what is the name of the class
    $actual = $sut->get_accepted_images(1,1,1);
    $expected = array(null, FALSE); //?? I dont know what the result is. you know this
    $this->assertEquals($expected, $actual);
}


//You should keep doing like this. 
//The next tests will include inserting data in the database, and testing what is the output




ИЗМЕНИТЬ:

user3421904 писал: а почему не статический? Мы не можем сделать это так: $actual = images::get_accepted_images(1, 1, 11); этот работает и на моей стороне! Это неправильно?

Это не так. Но если вы собираетесь проводить модульное тестирование другого компонента, потребляющего ImageDatabaseHelper, вы не сможете имитировать его. Вот почему:

Допустим, вы используете класс ImageService, который напрямую использует статический метод get_accepted_images. Нравится:

class ImageService {

    public function getAcceptedImages() {
        $images = ImageDatabaseHelper::get_accepted_images(1,1,1);

        //...
        //more code 
        //...

        return $images;
    }
}

Как вы протестируете метод getAcceptedImages без доступа к БД? Вы не можете, правда?

Теперь представьте, что вы делаете метод нестатическим.

class ImageService {
    private $imageDatabaseHelper;

    public function __construct(ImageDatabaseHelper $imageDatabaseHelper = null) {
       if(!$imageDatabaseHelper) {
          $this->imageDatabaseHelper = new ImageDatabaseHelper();
       }
       else {
          $this->imageDatabaseHelper = $imageDatabaseHelper;
       }
    }


    public function getAcceptedImages() {
        $images = $this->imageDatabaseHelper->get_accepted_images(1,1,1);

        //...
        //more code 
        //...

        return $images;
    }
}

Это легко проверить !!!

class ImageServiceTest extends PHPUnit_Framework_TestCase {
    protected $sut;    

    protected $imageDatabaseHelperDouble;

    public function setUp() {
      $this->imageDatabaseHelperDouble = $this->getMockBuilder('ImageDatabaseHelper')->disableOriginalConstructor()->getMock();
      $this->sut = new ImageService($this->imageDatabaseHelperDouble);
    }


    public function testGetAcceptedImagesWhenCalledShouldCallImageDatabaseHelper() {
       $this->imageDatabaseHelperDouble->expected($this->once())->method('get_accepted_images')->with(1,1,1);
       $this->sut->getAcceptedImages();
    }


    public function testGetAcceptedImagesWhenCalledShouldReturnImages() {
       $this->imageDatabaseHelperDouble->expected($this->any())->method('get_accepted_images')->will($this->returnValue(array("hi im an image", "me tooo")));
       $actual = $this->sut->getAcceptedImages();

       $expected = array("hi im an image", "me tooo");
       $this->assertEquals($expected, $actual);
    }

}

Понимаете? Имитация ImageDatabaseHelper переопределяет исходную ImageDatabaseHelper, используемую ImageService, и он думает, что использует ее. От этого вы можете делать все, что хотите! (это также включает создание исключений для ImageDatabaseHelper!)

Развлекайся!

person Tomas Prado    schedule 03.06.2014
comment
Большое спасибо за ответ :-) Но почему не статические? Мы не можем сделать это так: $ actual = images :: get_accepted_images (1, 1, 11); этот работает и с моей стороны! Это неправильно? - person ; 04.06.2014
comment
Если вы хотите выполнить модульное тестирование на вышеперечисленных слоях, вы должны заглушить метод get_accepted_images, чтобы вернуть все, что вы хотите. С помощью статического метода вы скрываете зависимости от объектов, поэтому невозможно внедрить имитируемый объект и использовать заглушенный метод. - person Tomas Prado; 04.06.2014
comment
Привет, спасибо за хорошее объяснение! Извините, если я вернусь к вам поздно! Ваше объяснение было таким приятным, но я предполагаю, что вы предполагаете, что я хочу протестировать другую функцию, в которой я использовал эту статическую функцию, но я хотел бы упростить ее и предположить, что у меня есть просто статические функции, в которых я не вызываю никаких другие статические методы (даже игнорируйте WS_Utility :: paginate_array ()); - person ; 12.06.2014
comment
по какой-то причине я не могу изменить статические методы, хотя стоит упомянуть, что в этих статических методах я не вызываю никаких других статических методов, и мне просто нужно протестировать эти статические методы на основе этой ссылки (stackoverflow.com/questions/5961023/) и пояснения здесь, если у меня нет любые статические методы в этой функции, тестирование будет в порядке! Итак, я задал еще два вопроса, и я очень ценю вашу помощь! - person ; 12.06.2014
comment
поскольку вопрос другой, я создал новый пост (stackoverflow.com/questions/24175487/) и заранее благодарю вас! :-) - person ; 12.06.2014
comment
Я согласен. Если вы не собираетесь тестировать другую функцию, которая будет использовать этот статический метод, то будет правильным оставить ее статической, если вы хотите большей простоты. :) - person Tomas Prado; 15.06.2014

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

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

Я не вижу особого смысла в тестировании вышеупомянутого метода, но я предлагаю скорее протестировать WS_Utility::paginate_array(), потому что это единственный вызов функции, который выполняет какую-либо логику, кроме, конечно, выборки из БД.

person pgampe    schedule 01.06.2014
comment
Спасибо за ответ! Да, думаю, вы правы! Мне нужно провести функциональное тестирование. Не могли бы вы сообщить мне, как лучше всего это сделать? Любой небольшой пример, чтобы уточнить больше, пожалуйста? - person ; 02.06.2014
comment
Правильно ли я понял, что нет необходимости использовать команду из PHPUnit, такую ​​как getDataSet (), наборы данных, таблицы данных, assert .... Нужно ли мне вызывать функции индивидуально и использовать var_dump или print_r, чтобы увидеть возвращенные значения с ожидаемыми Результаты? Не могли бы вы написать одно функциональное тестирование для моего кода, чтобы было понятнее? - person ; 02.06.2014
comment
Взгляните на phpunit.de/getting-started.html. Если у вас возникнут конкретные вопросы, приходите еще раз, и я помогу вам разобраться в деталях. - person pgampe; 02.06.2014
comment
+1. Но разве это не интеграционное тестирование? Функциональное тестирование проверяет функциональность программы, которую может понять владелец продукта. Интеграционное тестирование проверяет либо внутренности одной системы, либо объединение нескольких систем вместе, чтобы сделать что-то полезное. - person Tomas Prado; 03.06.2014
comment
Зависит от вашего определения нескольких систем. Например. в мире PHP база данных считается частью логики приложения, потому что обе они действительно тесно связаны. Следовательно, вы не можете проводить функциональное тестирование без базы данных. Вы можете попытаться высмеять это, но я сомневаюсь, что вы действительно получите полезные тесты для этого, и это будет очень тяжелым для памяти. Интеграционное тестирование - это (по крайней мере, для меня), если вы тестируете несколько слабосвязанных сервисов. Например. протестировать CMS в сочетании с сервером изображений, протестировать репликацию пользователей между двумя системами и т. д. Но это действительно то, как вы это определяете. - person pgampe; 03.06.2014
comment
Спасибо за ваше объяснение! Извините, если я вернусь к вам поздно! Я написал свой тестовый пример и задал два вопроса; Я очень ценю вашу помощь: я разместил свои вопросы по следующей ссылке, поскольку мой вопрос немного отличается: stackoverflow.com/questions/24175487/ - person ; 12.06.2014