Краткое введение в среду тестирования
PHPUnit предоставляет простую структуру для создания набора тестов для автоматизации тестирования функций и классов.PHPUnit вдохновлен JUnit, который был создан Кентом Беком и Эрихом Гаммой как инструмент для экстремального программирования.Одним из правил XP является тестирование небольших программных компонентов как можно чаще и на ранних этапах. Таким образом, вам не придется исправлять ошибки и ошибки в API при настройке и тестировании более крупных приложений, которые зависят от класса.В то время как модульное тестирование является одним из основных правил в XP, вам не нужно переключаться на XP, чтобы воспользоваться PHPUnit.PHPUnit сам по себе является хорошим инструментом для тестирования классов или набора функций, он облегчит ваш цикл разработки и поможет избежать бесконечных сеансов отладки.
Рабочая процедура
Обычно вы пишете класс, выполняете некоторые несистематические тесты, используя echo()
или var_dump()
.После этого вы используете класс в своем приложении и надеетесь, что все в порядке.Чтобы извлечь выгоду из PHPUnit вы должны переосмыслить поток.Лучший способ сделать это:
- создать свой класс / API
- создать набор тестов
- реализовать класс / API
- runнабор тестов
- исправляет сбои или ошибки и снова переходит к # 4
Может показаться, что на это потребуется много времени, но это впечатление неверное.Создание набора тестов с использованием PHPUnit занимает всего несколько минут, а запуск набора тестов - всего несколько секунд.
Разработка класса
Начнем с небольшого примера: строкового класса.Сначала мы создаем несколько объявлений функций для работы со строкой:
---- string.php ----
<?php
class String
{
//contains the internal data
var $data;
// constructor
function String($data) {
$this->data = $data;
}
// creates a deep copy of the string object
function copy() {
}
// adds another string object to this class
function add($string) {
}
// returns the formated string
function toString($format) {
}
}
?>
Создание набора тестов
Теперь мы можем создать набор тестов, который проверяет каждую функциювашего класса строки.Набор тестов - это обычный PHP-класс, унаследованный от PHPUnit_TestCase, содержащий тестовые функции, идентифицируемые лидирующим «тестом» в имени функции.В тестовой функции ожидаемое значение должно сравниваться с результатом тестируемой функции.Результат этого сравнения должен делегироваться функции assert*()-family
, которая решает, прошла ли функция тест или нет.
---- testcase.php ----
<?php
require_once 'string.php';
require_once 'PHPUnit.php';
class StringTest extends PHPUnit_TestCase
{
// contains the object handle of the string class
var $abc;
// constructor of the test suite
function StringTest($name) {
$this->PHPUnit_TestCase($name);
}
// called before the test functions will be executed
// this function is defined in PHPUnit_TestCase and overwritten
// here
function setUp() {
// create a new instance of String with the
// string 'abc'
$this->abc = new String("abc");
}
// called after the test functions are executed
// this function is defined in PHPUnit_TestCase and overwritten
// here
function tearDown() {
// delete your instance
unset($this->abc);
}
// test the toString function
function testToString() {
$result = $this->abc->toString('contains %s');
$expected = 'contains abc';
$this->assertTrue($result == $expected);
}
// test the copy function
function testCopy() {
$abc2 = $this->abc->copy();
$this->assertEquals($abc2, $this->abc);
}
// test the add function
function testAdd() {
$abc2 = new String('123');
$this->abc->add($abc2);
$result = $this->abc->toString("%s");
$expected = "abc123";
$this->assertTrue($result == $expected);
}
}
?>
Первый тестовый запуск
Теперь мы можем запустить первый тест.Убедитесь, что все пути указаны правильно, и затем запустите эту программу PHP.
---- stringtest.php ----
<?php
require_once 'testcase.php';
require_once 'PHPUnit.php';
$suite = new PHPUnit_TestSuite("StringTest");
$result = PHPUnit::run($suite);
echo $result -> toString();
?>
Если вы вызовете этот скрипт из командной строки, вы получите следующий вывод:
TestCase stringtest->testtostring() failed: expected true, actual false
TestCase stringtest->testcopy() failed: expected , actual Object
TestCase stringtest->testadd() failed: expected true, actual false
Каждая функция не проходит тест, потому что ваши строковые функции не вернули то, что мыопределяется как ожидаемое значение.
Если вы хотите вызвать скрипт через браузер, вы должны поместить скрипт на правильную HTML-страницу и вызвать $result->toHTML()
вместо $result->toString()
.
Реализация
Хорошо, давайте начнем с реализации нашего строкового класса.
---- string.php ----
<?php
class String
{
//contains the internal data
var $data;
// constructor
function String($data) {
$this->data = $data;
}
// creates a deep copy of the string object
function copy() {
$ret = new String($this->data);
return $ret;
}
// adds another string object to this class
function add($string) {
$this->data = $this->data.$string->toString("%ss");
}
// returns the formated string
function toString($format) {
$ret = sprintf($format, $this->data);
return $ret;
}
}
?>
Реализация завершена, и мы можем снова запустить тест:
~>
php -f stringtest.php
TestCase stringtest->testtostring() passed
TestCase stringtest->testcopy() passed
TestCase stringtest->testadd() failed: expected true, actual false
Черт возьми!последний тест не удался!Мы допустили опечатку.Измените строку 16 в файле string.php на
<?php
$this->data = $this->data.$string->toString("%s");
?>
и снова запустите тест:
~>
php -f stringtest.php
TestCase stringtest->testtostring() passed
TestCase stringtest->testcopy() passed
TestCase stringtest->testadd() passed
Теперь все в порядке!
Заключение
Кажется ли вам, что для тестирования трех простых функций требуется много работы?Не забывайте, это маленький пример.Подумайте о больших и более сложных API, таких как абстракция базы данных или классы корзин в приложении магазина.PHPUnit - отличный инструмент для выявления ошибок в реализации вашего класса.
Часто вам захочется переопределить или реорганизовать большой класс, который используется в нескольких различных приложениях.Без набора тестов вероятность того, что вы что-то сломаете в одном из приложений, которые зависят от вашего класса, очень высока.Благодаря модульным тестам вы можете создать набор тестов для своего класса, а затем переопределить ваш класс с уверенностью, зная, что, пока новый класс проходит тесты, приложения, которые зависят от класса, будут работать.
Использованный источник: http://pear.php.net