Как сделать тест PHPUnit, который зависит от ~ реальных данных POST / GET? - PullRequest
7 голосов
/ 11 ноября 2010

Я создал класс PHP, который охватывает функции filter_input, чтобы облегчить жизнь нашему разработчику.
Чтобы проверить HTML-форму с полями url, name и age, код будет выглядеть следующим образом:

$post = Filter::POST();
if ($post->validate_string('name') && $post->validate_integer('age')) {
    $url = $post->sanitize_url('url');
}

Это было бы так же, как:

if (filter_input(INPUT_POST,'name',FILTER_UNSAFE_RAW) && filter_input(INPUT_POST,'age',FILTER_VALIDATE_INTEGER)) {
    $url = filter_input(INPUT_POST,'url',FILTER_SANITIZE_URL);
}

Ну, я думаю, что код готов, и теперь я хотел бы создать для него тест PHPUnit.

Проблема в том, что я понятия не имею, как подделать данные GET / POST для метода PHPUnit, не для этого случая.
Мне не нужно вставлять значения в $_POST, мне нужны «настоящие» данныена нем, потому что filter_input работает с данными, полученными сценарием, а не с фактическим $_POST суперглобальным.

Я попытался использовать следующий тест PHPT и метод PHPUnit для достижения этой цели, но безуспешновсе:

--TEST--
Generates POST and GET data to be used in FilterTest.php
--POST--
name=Igor&age=20
--GET--
name=Igor&age=19
--FILE--
<?php
echo $_POST['nome'].' = '.$_POST['idade'];
?>
--EXPECT--
Igor = 20

public function testPhpt() {
 $phpt = new PHPUnit_Extensions_PhptTestCase('FilterTest_data.phpt', array('cgi' => 'php-cgi'));
 $result = $phpt->run();
 $this->assertTrue($result->wasSuccessful());
}

РЕДАКТИРОВАТЬ

Оригинальный код : http://pastebin.com/fpw2fpxM
Код, использованный для первоначального тестирования : http://pastebin.com/vzxsBQWm
(извините за португальский, я знаю, что было бы лучше кодировать на английском, но здесь все работаетгде я работаю.Если вы действительно думаете, что это действительно необходимо, я могу перевести код).

Есть идеи о том, что я могу сделать, чтобы протестировать этот класс?

Ответы [ 2 ]

2 голосов
/ 12 ноября 2010

Есть 2 проблемы с вашим кодом. Во-первых, вы обращаетесь к глобальным переменным, которые сложно проверить. Во-вторых, вы тесно связываете класс с конкретными данными (отправка, получение и т. Д.).

То, что вы должны сделать, это заставить класс удовлетворять такой интерфейс:

$filter = new Filter($_POST);
$filter->validate_string('name');

Преимущества должны быть очевидны. Вам не нужно использовать $_POST или $_GET или любой другой предопределенный тип в качестве входных данных. Теперь вы можете не только проверять ввод из любого источника (поскольку вы просто передаете его в конструктор), но, что более важно, вы можете вставлять туда любые данные, которые вам нравятся, для целей тестирования.

Woops, я пропустил часть об использовании filter_input. Решение состоит в том, чтобы использовать filter_var вместо этого. Позволяет запускать фильтры по любой переменной.

2 голосов
/ 11 ноября 2010

Вы не можете подделать необработанные данные POST. Но проблема заключается в вашем коде: он не тестируется юнитами. Вместо:

if (filter_input(INPUT_POST,'name',FILTER_UNSAFE_RAW) && filter_input(INPUT_POST,'age', FILTER_VALIDATE_INTEGER)) {
    $url = filter_input(INPUT_POST,'url',FILTER_SANITIZE_URL);
}

Если у вас было:

if (filter_var($data['name'], FILTER_UNSAFE_RAW) && filter_var($data['age'], FILTER_VALIDATE_INT)) {
    $url = filter_var($data['url'], FILTER_SANITIZE_URL);
}
// where $data is a copy of $_POST in that case

сделает ваш код тестируемым и получит то же самое , что и ваш предыдущий код.

P.S .: FILTER_VALIDATE_INTEGER недействителен. Правильная константа для этого - FILTER_VALIDATE_INT

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...