Итак, strlen () не взаимодействует.
Если какой-то код не взаимодействует, я делаю следующее:
- Устранение проблемы.Избавившись от всего, что не имеет отношения к делу.
- Попробуйте и уточнить, что следует делать, спросив себя: «Каковы мои утверждения и ожидания?».
- Напишите специальный сценарий для проверкинекорректно работающий код
- Изменяйте некорректно работающий код, пока он не будет вести себя как положено (делая его более тестируемым , если требуется).
Изолировать проблему.Избавившись от всего, что не имеет отношения к делу.
Сначала давайте возьмем ваш оригинальный пример кода и избавимся от всего, что не имеет отношения к конкретному рассматриваемому вопросу.Чтобы оставить только код проверки , который использует strlen .Итак, теперь мы можем видеть более четко.
Затем попытайтесь уточнить, что следует делать, спросив «Каковы мои утверждения и ожидания?».
Я предполагаю из вашего кода, что:
- дано
- a поле информации (название, имя, ip)
- и его минимальная длина
- и ее максимальная длина
- когда значение передается пользователем, который имеетдлина меньше минимальная длина или больше максимальная длина
- затем , значение должно быть отклонено
- иначе все нормально
Напишите специальный скрипт для проверки некорректно работающего кода
Я бы создал скрипт html / php исключительно для тестированияиз PHP, который вызывает горе.Назовите это FormFieldValidatorTest.php
например.Тестовый сценарий находится в проекте веб-сайта, но предназначен только для того, чтобы он выполнялся мнойПоэтому я поместил бы его в защищенный паролем каталог или другое недоступное для публики место.
Я хочу UTF-8 html-страницу, которая представляет некоторые строки известной длины.Скажем, буква «а», которую мы знаем, имеет длину один символ, а «пустое поле», которое мы знаем, имеет длину ноль символов.
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>My Test</title>
</head>
<body>
<form action="" method="get">
<input name="singleCharacterString" type="text" value="a" size="1" maxlength="1">
<input name="emptyString" type="text" value="" size="1" >
<input type="submit" name="Submit" value="Run Tests">
</form>
...
Затем в верхней части FormFieldValidatorTest.php
я бы написалнекоторый php-код для:
- получения этих фиксированных, жестко запрограммированных значений формы (данных прибора).
- передать данные о приборах в некоторые тесты, а затем
- вернуть мне массив результатов
Чтобы сохранить вещи в чистоте, я бы поставил в тупикпроверьте код в функции, назовите его runTestSuite()
, который будет подробно описан ниже.
<?php
//FormFieldValidatorTest.php
if ( $_REQUEST['Submit'] == 'Run Tests' ) {
//perform the tests
$testResultsArray = runTestSuite();
/**
* Lets loop through the results and count the failures
*/
$failureCounter = 0;
foreach ( $testResultsArray as $result ) {
if ( $result['hasFailed'] ) {
$failureCounter++;
}
}
} else {
//no tests were run set the results to null
$testResultsArray = null;
}
?>
<html>
...
Я бы добавил немного php в html-часть FormFieldValidatorTest.php
.Это должно распечатать результаты, если они были выполнены (то есть, когда $testResultsArray
не идентичен null
):
<code><?php
//FormFieldValidatorTest.php
...
?>
<html>
...
<body>
<form action="" method="get">
...
</form>
<?php if ( $testResultsArray !== null ) : ?>
<h1>Results</h1>
<pre>
<?php if ( $failureCounter > 0 ) : ?>
Failed. <?php echo $failureCounter ?> tests failed.
<?php print_r( $testResultsArray ); ?>
<?php else : ?>
Passed
<?php endif; ?>
Затем я заполнил бы все мои функции runTestSuite()
.По сути, это два вызова функции assertTrue()
, которые я конкретизирую позже.
- Во-первых, утверждается, что это правда, что strlen возвращает
1
, когда ему дано singleCharacterString
. - Затем он утверждает, что это правда, что strlen возвращает
0
, когда ему дано emptyString
.
В то же время он передает сообщение, описывающее каждый тест.Они сохраняются в массиве результатов, чтобы облегчить отладку в случае неудачи тестов.
/**
* @desc A suite of tests to excercise that troublesome code
* @return array of results for each test done
*/
function runTestSuite() {
/**
* Lets Run some tests
*/
/**
* Create the results array
*/
$testResultsArray = array();
/**
* Test some known data submitted via a form parameter
*/
assertTrue(
( strlen( $_REQUEST['singleCharacterString'] ) == 1 ),
'Expect it to be TRUE that singleCharacterString http parameter
has a stringlength of 1',
$testResultsArray );
/**
* @todo Add more tests here.
*/
assertTrue(
( strlen( $_REQUEST['emptyString'] ) == 0 ),
'Expect it to be TRUE that emptyString http parameter
has a stringlength of 0',
$testResultsArray );
return $testResultsArray;
}
Наконец, я расшифровал функцию assertTrue()
.Это в основном проверяет, имеет ли первый аргумент Failed проверку утверждения.Затем он добавляет этот результат и message
как запись в $testResultsArray
.
/**
* @desc A TRUE assertion
* @param mixed - a value that we expect to be true
* @param string - a message to help understand what we are testing
* @param array - a collection of results so far passed by reference
* @return void
*/
function assertTrue( $value, $message, &$testResultsArray ) {
if ( $value ) {
//value is as asserted
$currentResult = array(
'message' => $message,
'hasFailed' => FALSE
);
} else {
//value is not as asserted
$currentResult = array(
'message' => $message,
'hasFailed' => TRUE
);
}
$testResultsArray[] = $currentResult;
}
Теперь тестовый скрипт завершен. См. Здесь .
Если я запустлю его и увижу, что оно прошло, я могу быть уверен, что strlen сотрудничает.Если он не работает, я могу перейти к:
Изменить код неправильного поведения до тех пор, пока он не будет вести себя как положено.
Чтобы сделать это, вам, вероятно, понадобится разделить бит неправильного поведения наотдельная функция или класс, который находится в своем собственном файле.Это делает его повторно используемым , поэтому его можно вызывать как из тестового кода, так и из действующего производственного кода.
То, что мы действительно должны проверять, это правило длины , которое указывает, что разрешены только строки определенной длины.
Итак, давайте выделим это, чтобы мы могли его проверить.Может быть, функция в библиотеке rules с именем isCorrectLength () в файле с именем ServerValidationRules.php
<?php
//ServerValidationRules.php
/**
* @desc boolean function to test string length
* @param string to test
* @param integer defining minimum length required
* @param integer defining maximum length required
* @return TRUE if its the correct length, FALSE otherwise.
*/
function isCorrectLength( $string, $minLength, $maxLength ) {
if ( strlen( $string ) < $minLength ) {
//its too short
return FALSE;
}
if ( strlen( $string ) > $maxLength ) {
//its too long
return FALSE;
}
return TRUE;
}
Затем мы можем заменить код в нашем тесте, чтобы использовать его вместо собственного strlen()
function.
<?php
//FormFieldValidatorTest.php
require_once('ServerValidationRules.php');
...
/**
* @desc A suite of tests to excercise that troublesome code
* @return array of results for each test done
*/
function runTestSuite() {
$testResultsArray = array();
/**
* Test some known data submitted via a form parameter
*/
assertTrue(
//( strlen( $_REQUEST['singleCharacterString'] ) == 1 ),
isCorrectLength( $_REQUEST['singleCharacterString'], 0, 1 ),
'Expect it to be TRUE that singleCharacterString http parameter
has a stringlength of 1',
$testResultsArray );
/**
* @todo Add more tests here.
*/
assertTrue(
//( strlen( $_REQUEST['emptyString'] ) == 0 ),
isCorrectLength( $_REQUEST['emptyString'], 0, 0 ),
'Expect it to be TRUE that emptyString http parameter
has a stringlength of 0',
$testResultsArray );
return $testResultsArray;
}
...
Итак, теперь мы можем заменить код в производственном скрипте на:
<title>Terraria Server List</title>
...
<?php
...
if ( $submit ) {
if (!( isCorrectLength( $title, 0, 50 ) )) {
die("Invalid title!");
}
elseif (!( isCorrectLength($ip, 0, 50) )) {
die("Invalid IP!");
}
elseif (!( isCorrectLength( $desc, 0, 10000 ) )) {
die("Invalid description!");
}
elseif (!( isCorrectLength( $email, 0, 100 ) )) {
die("Invalid E-Mail!");
}
else {
//do the insert
}
}
...
Или, что еще лучше, переместить length правила в одну функцию, так что логика может быть повторно использована другим кодом (например, некоторый код в наборе тестов).
Мы могли бы свернуть все это в функцию с именем isServerFieldsValid
и поместить ее в нашServerValidationRules.php
file.
<?php
//ServerValidationRules.php
...
/**
* @desc tests user-submitted fields appending feedback to an array of messages upon failure.
* @param associative array of Posted values keyed by field name
* @param array of messages passed by reference
* @return boolean True if all fields are valid. False otherwise.
*/
function isServerFieldsValid( $values, &$messages ) {
$hasFailed = FALSE;
if (!( isCorrectLength( $values['title'], 1, 50 ) )) {
$hasFailed = TRUE;
$messages[] = "Invalid title!";
}
if (!( isCorrectLength($values['ip'], 1, 50) )) {
$hasFailed = TRUE;
$messages[] = "Invalid IP!";
}
if (!( isCorrectLength( $values['desc'], 1, 1000 ) )) {
$hasFailed = TRUE;
$messages[] = "Invalid description!";
}
if (!( isCorrectLength( $values['email'], 1, 100 ) )) {
$hasFailed = TRUE;
$messages[] = "Invalid E-Mail!";
}
if ( $hasFailed ) {
return FALSE;
}
//else
return TRUE;
}
, а затем добавьте еще несколько утверждений к функции набора тестов в нашем тестовом скрипте.
...
/**
* @desc A suite of tests to excercise that troublesome code
* @return array of results for each test done
*/
function runTestSuite() {
/**
* Initialize the results array
*/
$testResultsArray = array();
...
/**
* Test some variants of possible user submitted data
*
* @todo We ought to invoke an assertFalse() function.
* In meantime, hack it by passing a negated value to assertTrue().
*/
/**
* When given values that are too long,
* expect a validation failure.
*/
$validationMessages = array();
$result = isServerFieldsValid(
array(
'title' => str_repeat( 'a' , 51 ),
'ip' => str_repeat( 'a' , 51 ),
'desc' => str_repeat( 'a' , 1001 ),
//?'type' => str_repeat( 'a' , 1001 ),
'email' => str_repeat( 'a' , 101 ),
),
$validationMessages
);
assertTrue(
(!( $result )),
'Expect it to be TRUE that result is False when given long values',
$testResultsArray );
assertTrue(
in_array( 'Invalid title!', $validationMessages ),
'Expect messages to say "Invalid title!"',
$testResultsArray );
assertTrue(
in_array( 'Invalid IP!', $validationMessages ),
'Expect messages to say "Invalid IP!"',
$testResultsArray );
assertTrue(
in_array( 'Invalid description!', $validationMessages ),
'Expect messages to say "Invalid description!"',
$testResultsArray );
assertTrue(
in_array( 'Invalid E-Mail!', $validationMessages ),
'Expect messages to say "Invalid E-Mail!"',
$testResultsArray );
/**
* When given values that are too short,
* expect a validation failure.
*/
$validationMessages = array();
$result = isServerFieldsValid(
array(
'title' => null,
'ip' => null,
'desc' => null,
'email' => null,
),
$validationMessages
);
assertTrue(
(!( $result )),
'Expect it to be TRUE that result is False when given short values',
$testResultsArray );
assertTrue(
in_array( 'Invalid title!', $validationMessages ),
'Expect messages to say "Invalid title!"',
$testResultsArray );
assertTrue(
in_array( 'Invalid IP!', $validationMessages ),
'Expect messages to say "Invalid IP!"',
$testResultsArray );
assertTrue(
in_array( 'Invalid description!', $validationMessages ),
'Expect messages to say "Invalid description!"',
$testResultsArray );
assertTrue(
in_array( 'Invalid E-Mail!', $validationMessages ),
'Expect messages to say "Invalid E-Mail!"',
$testResultsArray );
/**
* When given values that are the correct length,
* expect a validation success.
*/
$validationMessages = array();
$result = isServerFieldsValid(
array(
'title' => 'a title',
'ip' => 'an ip',
'desc' => 'a desc',
'email' => 'an email',
),
$validationMessages
);
assertTrue(
( $result ),
'Expect it to be TRUE that result is True when given correct values',
$testResultsArray );
assertTrue(
(!( in_array( 'Invalid title!', $validationMessages ) )),
'Expect messages NOT to say "Invalid title!"',
$testResultsArray );
assertTrue(
(!( in_array( 'Invalid IP!', $validationMessages ) )),
'Expect messages NOT to say "Invalid IP!"',
$testResultsArray );
assertTrue(
(!( in_array( 'Invalid description!', $validationMessages ) )),
'Expect messages NOT to say "Invalid description!"',
$testResultsArray );
assertTrue(
(!( in_array( 'Invalid E-Mail!', $validationMessages ) )),
'Expect messages NOT to say "Invalid E-Mail!"',
$testResultsArray );
return $testResultsArray;
}
...
Итак, полный сценарий тестирования теперь выглядит следующим образом .
Итак, если это пройдет, мы можем изменить производственный код, заменив все эти if (strlen ) { die }
заявления с вызовом этой новой, хорошо протестированной, isServerFieldsValid()
функции:
<title>Terraria Server List</title>
...
if ( $submit ) {
$messages = array();
if (!( isServerFieldsValid( $_POST, $messages ) )) {
echo 'Invalid data was submitted:' . PHP_EOL;
foreach( $messages as $message ) {
echo $message . PHP_EOL;
}
exit;
} else {
//do the insert
}
...
Ну, вот как бы я справился с кодом, который все равно не взаимодействует.
Код:
Примечание:
Мне понадобилось несколько часов, чтобы написать этот ответ, но очень мало времени, чтобы написать реальный тест.Когда вы начинаете привыкать, часто требуется всего несколько минут, чтобы набросать тест и выяснить, почему какой-то код не взаимодействует.
Совет: вам не нужно писать свои собственные функции утверждений.,Смотри: http://www.simpletest.org/en/start-testing.html