Современные технологии разработки программного обеспечения способствуют написанию скриптов с модульной структурой, обеспечивая относительно простой рефакторинг и расширение системы. Независимо от того насколько Вы опытный программист и насколько простые изменения вносятся в программный код, после внесения изменений система должна быть протестирована.
Организация вывода данных с помощью простых методов echo или print – самый простой способ определить, соответствует ли полученный результат ожидаемому. До определенного момента такой подход будет оправдывать себя. Но при работе над довольно крупными проектами каждая лишняя строчка закомментированного кода сбивает с толку даже самого его автора.
Допустим, программист занимается самостоятельной разработкой однотипных сайтов на созданном им фреймворке. Через некоторое время он решил расширить сферу своей деятельности, для чего понадобилось внести изменения в сайтовый движок. Даже если он был создан по всем канонам ООП и имеет распространенную архитектуру MVC, некоторые изменения могут существенно повлиять на его работу в целом. Начинают возникать разнообразные ошибки, и в конечном итоге становится ясно, что проще начать разработку с нуля. Но подобной ситуации можно было избежать, если бы проект изначально содержал модульные тесты (также их называют unit-тесты).
Что такое модульное тестирование
Существует несколько способов тестирования кода приложений и скриптов. К распространенным относятся интеграционное и модульное тестирование. Первый используют для проверки зависимостей между несколькими компонентами системы чтобы убедиться в том, что они взаимодействуют корректно. Но современные программы состоят из большого количества структурных единиц – модулей. Наличие ошибок в одном из них может привести к неправильной работе программы в целом. Поэтому интеграционный подход в данном случае неприменим.
Модульное тестирование представляет собой процесс проверки отдельных частей кода программы. К таковым относятся функции, методы классов включая конструкторы, которые в некоторых случаях могут содержать сложную логику. Такой вид тестирования предполагает наличие навыков программирования у того, кто его проводит. Написание теста к каждой функции или методу занимает некоторое время, которое окупится в будущем при внесении любых изменений в исходный код. Так можно легко проверить, не привела ли очередная правка к возникновению ошибок.
Необходимость тестирования
Модульное тестирование приносит неоспоримую пользу, но к нему прибегают далеко не все даже опытные программисты. Главная причина – увеличение времени разработки проекта. Некоторые среды проектирования приложений генерируют простейшие тесты, но для качественной проверки требуется написание собственных нетривиальных методов. Практика показывает, что отсутствие модульных тестов значительно усложняет дальнейшее сопровождение проекта.
Вторая распространенная причина отказа от модульного тестирования – излишняя уверенность в собственных навыках и силах. Над разработкой современных программ трудятся целые команды специалистов. Разработчик, знающий про все «слабые места» кода, может сменить место работы, а у нового специалиста затем возникают сложности при внесении изменений, даже несмотря на корректно оформленную документацию. Наличие юнит-тестов спасло бы ситуацию.
Что нужно тестировать?
Некоторые программисты считают, что тесты должны покрывать 100% программного кода. Этот подход рационально использовать при разработке несрочных проектов, которые будут поддерживаться длительный период времени или к которым предъявляют высочайшие требования. Например, курьезный баг, которого можно было бы избежать при надлежащем тестировании, привел к неудаче при реализации программы Mars Climate Orbiter.
Весь программный код можно условно разделить на следующие компоненты:
- Простая логика, в которой отсутствуют зависимости. При грамотной реализации эту часть кода можно оставить без тестов.
- Сложный код с отсутствующими зависимостями. Эта часть программы содержит бизнес-логику и сложные алгоритмы, работоспособность которых необходимо тщательно проверять.
- Сложный код с большим числом зависимостей. Чаще всего, эта часть проекта подвергается многочисленным изменениям и правкам, которые касаются как отдельных методов, так и классов, и даже их иерархии. Обычные юнит-тесты – лишняя трата времени, поскольку многие из них окажутся неприменимыми. Поэтому в данном случае используют высокоуровневые приемочные тесты.
- Несложный код с многочисленными зависимостями. Вообще рекомендуется минимизировать число взаимосвязей, но их большого количества не всегда можно избежать. В данном случае тестировать каждый простой модуль нецелесообразно. Но проверить все взаимосвязи между ними крайне необходимо.
Библиотека PHPUnit
Существует несколько инструментов для тестирования кода, написанного на языке PHP. По мнению многих разработчиков, лучшим вариантом является библиотека PHPUnit. Для ее установки необходимо перейти на официальный сайт проекта (www.phpunit.de) и выполнить простые шаги, указанные в инструкции.
PHPUnit имеет следующие преимущества:
- Простота установки и интеграции в проект;
- Широкий набор инструментов на все случаи жизни;
- Два варианта работы: в командной строке или с конфигурационным файлом;
- Поддержка объявления зависимостей между методами тестирования;
- Работа с большими объемами данных и прочие.
Особенности использования библиотеки:
- Самым важным и часто используемым классом является TestCase, содержащий много полезных методов.
- Каждый тест представляет собой отдельный класс, имя которого должно состоять из имени тестируемого класса и подстроки “Test”. Например, для тестирования класса MainControler необходимо создать класс MainControllerTest.
- Имена методов в тестирующем классе должны начинаться со слова «test» (например, testDoAction()).
- Каждый метод в рамках тестирующего класса должен являться самодостаточным и независимым. Поэтому он не должен принимать данные на вход, то есть не иметь параметров.
Примеры использования
Самым простым примером реализации модульного теста является проверка метода некоторого класса на возвращаемое им значение. Рассмотрим следующий код:
<?php
namespace someApplication;
class SomeClass {
public function someAction() {
return true;
}
}
Имеем класс SomeClass с методом someAction(), который возвращает логическое true. Для проверки возвращаемого значения напишем следующий код:
<?php
namespace testing;
use PHPUnit\Framework\TestCase;
use someApplication\SomeClass;
class SomeClassTest extends TestCase {
public function testSomeAction() {
$obj = new SomeClass();
$this->assertTrue($obj->someAction());
}
}
Строка «$this->assertTrue($obj->check());» вызывает метод assertTrue(), который проверяет результат, возвращаемый методом someAction(). Тест будет пройден успешно, если возвращаемое значение является логическим true.
Библиотека PHPUnit содержит множество методов проверки, название которых начинается с «Assert». С их помощью можно проверить тип переменной, сравнить значения, в том числе с использованием регулярных выражений.
Еще один простой пример использования PHPUnit – проверка части строк на соответствие значению, содержащемуся в подстроке. Например, имеем класс закрытой переменной:
<?php
namespace someStrings;
class MyStrings {
private $firstString = “Some interesting text”;
public function getFirstString() {
return $this->firstString;
}
}
Проверим, начинается ли строка, хранящаяся в закрытом свойстве $firstString, символами «Some». Для этого создадим следующий класс:
<?php
namespace testing;
use PHPUnit\Framework\TestCase;
use someStrings\MyStrings;
class MyStringsTest extends TestCase {
public function testStringStartsFrom () {
$obj = new MyStrings();
$this->assertStringStartsWith(“Some”, $obj-> getFirstString());
}
}
Имеем класс SomeClass с методом someAction(), который возвращает логическое true. Для проверки возвращаемого значения напишем следующий код:
<?php
namespace testing;
use PHPUnit\Framework\TestCase;
use someStrings\MyStrings;
class MyStringsTest extends TestCase {
public function testStringStartsFrom () {
$obj = new MyStrings();
$this->assertStringStartsWith(“Some”, $obj-> getFirstString());
}
}
Для запуска теста необходимо открыть командную строку и ввести команду “phpunit”, а через пробел указать путь к файлу с расширением “.php”, который содержит код теста. Результатом выполнения каждого теста являются данные о затраченном времени, используемой памяти, количестве ошибок. Об успешном прохождении теста свидетельствует символ «.», неудачном – строка «false». Символы “I” и “S” сообщают о невозможности прохождения теста или его пропуске.
Дата: 16.01.2019 Автор: Евгений
|
Авторам статті важлива Ваша думка. Будемо раді його обговорити з Вами:
comments powered by Disqus