2. Написание тестов на PHPUnit
Пример 2.1 показывает, как мы можем писать тесты, используя PHPUnit, которые выполняют операции с массивом PHP. В этом примере представлены основные соглашения и шаги для написания тестов с помощью PHPUnit:
Кроме того, вы можете использовать аннотацию @test в докблоке метода, чтобы пометить его как метод тестирования.
Внутри тестовых методов для проверки того, соответствует ли фактическое значение ожидаемому используются методы-утверждения, такие как assertSame() (см. Утверждения ).
Зависимости тестов
Адриан Кун (Adrian Kuhn) и другие:
Модульные тесты главным образом пишутся в качестве хорошей практики, помогающей разработчикам выявлять и исправлять баги, проводить рефакторинг кода и служить в качестве документации для тестируемого программного модуля (программы). Для достижения этих преимуществ модульные тесты в идеале должны охватывать все возможные пути исполнения программы. Один модульный тест обычно покрывает один конкретный путь в одной функции или методе. Однако тестовые методы необязательно должны быть инкапсулированными и независимыми. Часто существуют неявные зависимости между тестовыми методами, скрытые в сценарии реализации теста.
PHPUnit поддерживает объявление явных зависимостей между тестовыми методами. Эти зависимости не определяют порядок, в котором должны выполняться тестовые методы, но они позволяют возвращать экземпляр (данные) фикстуры теста, созданные поставщиком (producer) для передачи его зависимым потребителям (consumers).
Пример 2.2 показывает, как использовать аннотацию @depends для представления зависимостей между тестовыми методами.
Провайдеры данных
Метод провайдера данных должен быть объявлен как public и возвращать либо массив массивов, либо объект, реализующий интерфейс Iterator и возвращать массив при каждой итерации. Для каждого массива, являющегося частью коллекции, будет вызываться тестовый метод с элементами массива в качестве его аргументов.
При использовании большого количества наборов данных полезно указывать для каждого из них строковый ключ, вместо использования числового ключа по умолчанию. Вывод станет более подробным, так как он будет содержать имя набора данных, не прошедший тест.
Чистые тесты на PHP и PHPUnit
В экосистеме PHP существует много инструментов, обеспечивающих удобное тестирование на PHP. Одним из самых известных является PHPUnit, это почти синоним тестирования на этом языке. Однако о хороших методиках тестирования пишут не так много. Есть много вариантов, для чего и когда писать тесты, какого рода тесты, и так далее. Но, честно говоря, не имеет смысла писать тест, если позднее вы не сможете его прочесть.
Тесты — это особая разновидность документации. Как я ранее писал о TDD на PHP, тест всегда будет (или хотя бы должен) ясно говорить о том, в чём заключается задача конкретной части кода.
Если один тест не может выразить эту идею, то тест плохой.
Я подготовил набор методик, которые станут подспорьем для PHP-разработчиков в написании хороших, удобочитаемых и полезных тестов.
Начнём с основ
Есть набор стандартных методик, которым многие следуют без каких-либо вопросов. Многие из них я упомяну и попытаюсь объяснить, для чего они нужны.
1. Тесты не должны содержать операций ввода-вывода
Основная причина: операции ввода-вывода медленные и ненадёжные.
Медленные: даже если у вас самое лучшее в мире железо, операции ввода-вывода всё равно будут медленнее обращений к памяти. Тесты всегда должны работать быстро, иначе люди будут слишком редко их запускать.
Ненадёжные: некоторые файлы, бинарники, сокеты, папки и DNS-записи могут быть недоступны на некоторых машинах, на которых вы проводите тестирование. Чем больше вы полагаетесь при тестировании на операции ввода-вывода, тем больше ваши тесты привязаны к инфраструктуре.
Какие операции относятся к вводу-выводу:
Изолируйте тесты так, чтобы им не нужны были операции ввода-вывода: ниже я привёл архитектурное решение, которое предотвращает выполнение тестами операций ввода-вывода за счёт разделения ответственности между интерфейсами.
При начале тестирования с помощью этого метода будет создан локальный файл, и время от времени будут создаваться его снимки:
Для этого нам нужно настроить предварительные условия запуска тестов. На первый взгляд всё выглядит разумно, но на самом деле это ужасно.
Пропуск теста из-за того, что не выполнены предварительные условия, не обеспечивает качество нашего ПО. Это лишь скроет баги!
Исправляем ситуацию: изолируем операции ввода-вывода, переложив ответственность на интерфейс.
Теперь я знаю, что JsonFilePeopleProvider в любом случае будет использовать ввод-вывод.
Вместо file_get_contents() можно использовать слой абстракции вроде файловой системы Flysystem, для которой легко сделать заглушки.
2. Тесты должны быть осознанными и осмысленными
Основная причина: тесты — это разновидность документации. Поддерживайте их понятность, краткость и удобочитаемость.
Понятность и краткость: ни беспорядка, ни тысяч строк заглушек, ни последовательностей утверждений.
Удобочитаемость: тесты должны рассказывать историю. Для этого отлично подходит структура «дано, когда, тогда».
Характеристики хорошего и удобочитаемого теста:
Повторюсь: дело не в покрытии, а в документировании.
Вот пример сбивающего с толку теста:
Давайте адаптируем формат «дано, когда, тогда» и посмотрим, что получится:
Как и раздел «дано» (Given), «когда» и «тогда» можно перенести в приватные методы. Это сделает ваш тест более удобочитаемым.
Теперь в assertEquals бессмысленный беспорядок. Читающий это человек должен проследить утверждение, чтобы понять, что оно означает.
Теперь всё предельно понятно! Если человек не имеет крыльев, он не должен уметь летать! Читается как стихотворение
Теперь раздел «Further cases», который дважды появляется в нашем тексте, является ярким свидетельством того, что тест делает слишком много утверждений. При этом метод testCanFly() совершенно бесполезен.
Давайте снова улучшим тест:
3. Тест не должен зависеть от других тестов
Основная причина: тесты должны запускаться и успешно выполняться в любом порядке.
Я не вижу достаточных причин для создания взаимосвязей между тестами. Недавно меня попросили сделать тест функции входа в систему, приведу его здесь в качестве хорошего примера.
Это плохо по нескольким причинам:
Также нам понадобится добавить тесты для аутентификации и т. д. Эта структура так хороша, что в Behat используется по умолчанию.
4. Всегда внедряйте зависимости
Основная причина: очень дурной тон — создавать заглушку для глобального состояния. Отсутствие возможности создавать заглушки для зависимостей не позволяет тестировать функцию.
Полезный совет: забудьте o статичных stateful-классах и экземплярах синглтонов. Если ваш класс от чего-то зависит, то сделайте так, чтобы его можно было внедрять.
Вот грустный пример:
Как можно протестировать этот ранний ответ?
Для его тестирования нам нужно понимать поведение класса Cookies и быть уверенными в том, что можем воспроизвести всё связанное с этим окружение, в результате получив определённые ответы.
Ситуацию можно исправить, если внедрить экземпляр Cookies в качестве зависимости. Тест будет выглядеть так:
Совершенно нормально менять архитектуру, чтобы облегчить тестирование! А создавать методы для облегчения тестирования — не нормально.
5. Никогда не тестируйте защищённые/приватные методы
Основная причина: они влияют на то, как мы тестируем функции, определяя сигнатуру поведения: при таком-то условии, когда я ввожу А, то ожидаю получить Б. Приватные/защищённые методы не являются частью сигнатур функций.
Я даже не хочу показывать способ «тестирования» приватных методов, но дам подсказку: вы можете это сделать только с помощью API reflection.
Всегда как-нибудь наказывайте себя, когда задумываетесь об использовании reflection для тестирования приватных методов! Плохой, плохоооой разработчик!
По своему определению, приватные методы вызываются только изнутри. То есть они не доступны публично. Это означает, что вызывать подобные методы могут только публичные методы из того же класса.
Если вы протестировали все свои публичные методы, то вы также протестировали все приватные/защищённые методы. Если это не так, то свободно удаляйте приватные/защищённые методы, их всё-равно никто не использует.
Продвинутые советы
Надеюсь, вы ещё не заскучали. Всё-таки про основы нужно было рассказать. Теперь поделюсь своим мнением о написании чистых тестов и решениях, влияющих на мой процесс разработки.
Самое важное, о чём я не забываю при написании тестов:
1. Тесты в начале, а не в конце
Ценности: учёба, быстрое получение обратной связи, документирование, рефакторинг, проектирование в ходе тестирования.
Это основа всего. Важнейший аспект, включающий в себя все перечисленные ценности. Когда вы заранее пишете тесты, это помогает вам сначала понять, как должна быть структурирована схема «дано, когда, тогда». При этом вы сначала документируете, и, что ещё важнее, запоминаете и задаёте свои требования как самые важные аспекты.
Странно слышать о том, чтобы писать тесты до реализации? А представьте, насколько странно реализовать что-то, а при тестировании выяснить, все ваши выражения «дано, когда, тогда» не имеют смысла.
Также этот подход позволит проверять ваши ожидания каждые две секунды. Вы получаете обратную связь максимально быстро. Вне зависимости от того, насколько большой или маленькой выглядит фича.
Зелёные тесты — идеальная область для рефакторинга. Главная мысль: нет тестов — нет рефакторинга. Рефакторинг без тестов просто опасен.
Наконец, задав структуру «дано, когда, тогда», вам станет очевидно, какие интерфейсы должны быть у ваших методов и как они должны себя вести. Соблюдение чистоты теста также заставит вас постоянно принимать разные архитектурные решения. Это заставит вас создавать фабрики, интерфейсы, нарушать наследования и т. д. И да, тестировать станет легче!
Если ваши тесты — это живые документы, объясняющие работу приложения, то крайне важно, чтобы они делали это понятно.
2. Лучше без тестов, чем с плохими тестами
Ценности: учёба, документирование, рефакторинг.
Многие разработчики думают о тестах так: напишу фичу, буду гонять фреймворк для тестирования до тех пор, пока тесты не покроют определённое количество новых строк, и отправлю в эксплуатацию.
Мне кажется, нужно уделять больше внимания ситуации, когда новый разработчик начинает работать с этой фичей. О чём расскажут тесты этому человеку?
Если ваши тесты представляют собой всего лишь беспорядочный код, который заставляет фреймворк покрывать больше строк, с примерами, которые не имеют смысла, то пришло время остановиться и подумать, стоит ли вообще писать эти тесты.
Помните: ваши тесты — живые документы, пытающиеся объяснить, как должно вести себя ваше приложение. assertFalse($a->canFly()) мало что документирует. А assertFalse($personWithNoWings->canFly()) — уже достаточно много.
3. Навязчиво прогоняйте тесты
Ценности: учёба, быстрое получение обратной связи, рефакторинг.
Прежде чем начать работу над фичей, запустите тесты. Если они сбоят до того, как вы принялись за дело, то вы узнаете об этом до того, как напишете код, и вам не придётся тратить драгоценные минуты на отладку сломанных тестов, о которых вы даже не беспокоились.
После сохранения файла запустите тесты. Чем раньше вы узнаете о том, что что-то поломалось, тем быстрее исправите и двинетесь дальше. Если прерывание рабочего процесса для решения проблемы вам кажется непродуктивным, то представьте, что позднее вам придётся вернуться на много шагов назад, если вы не будете знать о возникшей проблеме.
Поболтав пять минут с коллегами или проверив уведомления с Github, запустите тесты. Если они покраснели, то вы знаете, на чём остановились. Если тесты зелёные, можно работать дальше.
После любого рефакторинга, даже имён переменных, запустите тесты.
Серьёзно, запускайте чёртовы тесты. Так же часто, как вы нажимаете кнопку «сохранить».
PHPUnit Watcher может делать это за вас, и даже отправлять уведомления!
4. Большие тесты — большая ответственность
Ценности: учёба, рефакторинг, проектирование в ходе тестирования.
В идеале, каждый класс должен иметь один тест. Этот тест должен покрывать все публичные методы в этом классе, а также каждое условное выражение или оператор перехода…
Можно считать примерно так:
Чем больше у вас будет публичных методов, тем больше понадобится тестов.
Никто не любит читать длинную документацию. Поскольку ваши тесты тоже документы, то маленький размер и осмысленность будут только увеличивать их качество и полезность.
Также это важный сигнал о том, что ваш класс накапливает ответственности и пришло время отрефакторить его, перенеся ряд функций в другие классы, или перепроектировав систему.
5. Поддерживайте набор тестов для решения проблем с регрессией
Ценности: учёба, документирование, быстрое получение обратной связи.
Вы думаете, что кто-то передаёт «10», но на самом деле передаётся «10 bananas». То есть приходят два значения, но одно лишнее. У вас баг.
Что вы сделаете в первую очередь? Напишете тест, который обозначит такое поведение ошибочным.
Конечно, тесты ничего не передают. Но теперь вы знаете, что нужно сделать, чтобы они передавали. Исправьте ошибку, сделайте тесты зелёными, разверните приложение и будьте счастливы.
Сохраните у себя этот тест. По возможности, в наборе тестов, предназначенных для решения проблем с регрессией.
Вот и всё! Быстрое получение обратной связи, исправление багов, документирование, устойчивый к регрессии код и счастье.
Как создать онлайн тест на php
Иногда людям не знающим программирования, нужно создать онлайн тест на php для своего сайта, на самом деле все очень просто, постараюсь наглядно объяснить.
Для решения данной задачи мы будем использовать простую HTML форму и POST запросы. И так приступим.
1. Нам потребуется создать файл php, в общем по сути не важно, если вы используете CMS, то пишете там, где можно вставить php код.
2. Создадим простую форму с полями «radio», то есть для выбора вариантов ответа и кнопкой для результатов.
В результате получим:
3. Отлично мы создали форму. Теперь в неё нужно внести изменения, чтобы она работала.
Добавим атрибуты к форме.
5. А теперь пропишем имя ответов к каждому варианту, например ‘value = «a»‘
В результате получим:
6. Создадим файл result.php в том же каталоге, в котором создадим скрипт теста на php для обработки и вывода результата правильных и не правильных ответов.
7. Перед html кодом добавим скрипт php:
8. Теперь выводим на страницу в html коде правильные и неправильные ответы:
Заключение. Теперь у вас есть простой тест на php и html, теперь можно и запустить его для онлайн. Вы можете добавить сколько угодно вариантов ответов по аналогии. Добавить стилей и улучшить код. Можно было все сделать намного грамотней, но проще этого не придумаешь. Работа у теста такая: выбрали варианты, нажали на кнопку «результат», нас перекидывает на вторую страницу, где выводится подсчет правильных и неправильных ответов. Удачи!
Юнит-тестирование в PHP
Язык PHP очень легок для изучения. Это, а так же обилие литературы «Освой _что_угодно_ за 24 часа» породило большое количество, мягко говоря, некачественного кода. Как следствие, рано или поздно любой программист, который выходит за рамки создания гостевой книги или сайта-визитки сталкивается с вопросом: «а если я здесь немножко добавлю, все остальное не ляжет?» Дать ответ на этот вопрос и на многие другие может юнит-тестирование.
В самом начале хочется оговориться — здесь речь не будет идти о TDD и методологиях разработки ПО. В данной статье я попробую показать начинающему PHP-разработчику основы использования модульного тестирования на базе фреймворка PHPUnit
Вместо предисловия
Вначале возникает вполне резонный вопрос: А зачем, если все и так работает?
Здесь все просто. После очередного изменения что-то перестанет работать так как надо — это я вам обещаю. И тогда поиск ошибки может отнять очень много времени. Модульное тестирование может свести этот процесс к считанным минутам. Не будем так же исключать переезд на другую платформу и связанные с ним «подводные камни». Чего только стоит разность в точности вычислений на 64- и 32-разрядных системах. А когда-то вы в первый раз столкнетесь с нюансами вроде
Если вопрос необходимости отпал, то можно приступить к выбору инструмента. Здесь ассортимент в общем-то невелик — PHPUnit (http://www.phpunit.de/) и SimpleTest (http://www.simpletest.org/). Поскольку PHPUnit уже стал стандартом де-факто в тестировании PHP приложений, то на нем и остановимся.
Первое знакомство
Вопросы установки рассматривать не будем: все достаточно внятно изложено на сайте. Попробуем лучше понять, как это все работает.
Допустим, есть у нас некий класс «MyClass», одним из методов реализующий возведение числа в степень. (Здесь вынужден извиниться, но все примеры, в общем-то, высосаны из пальца)
Хочется проверить, правильно ли он работает. О всем классе речь пока не идет — только об одном методе. Напишем для проверки такой тест.
require_once ‘PHPUnit/Framework.php’ ;
require_once ‘MyClass.php’ ;
$ phpunit MyClassTest
.
Time: 0 seconds
OK (1 test, 1 assertion)
Результат выполнения теста «ОК». Казалось бы можно остановиться на этом, но иногда было бы неплохо для проверки скормить методу не один набор данных. PHPUnit предоставляет нам такую возможность — это провайдеры данных. Провайдер данных тоже является паблик-методом (название не существенно), который возвращает массив наборов данных для каждой итеррации. Для использования провайдера необходимо указать его в теге @dataProvider к тесту.
Изменим наш тест следующим образом:
require_once ‘PHPUnit/Framework.php’ ;
require_once ‘MyClass.php’ ;
class MyClassTest extends PHPUnit_Framework_TestCase <
После запуска увидим следующую картину:
Опишу подробнее. Точка, которую в первом выводе теста многие могли принять за опечатку на самом деле таковой не является — это успешно пройденный тест. F(ailure) — соответственно тест не пройденный. Значит в данном случае, было проведено 3 теста, один из который завершился неудачно. В расширенном описании нам было сказано, какой именно, с каким набором исходных данных, с каким реальным и каким ожидаемым результатом. Если бы 2 3 действительно равнялось 9-ти, то мы увидели бы таким образом ошибку в нашем сценарии.
Здесь, как мне кажется, есть смысл отвлечься от несколько абстрактной практики и перейти ко вполне конкретной теории. А именно, описать какими же assert-методами мы располагаем для проверки поведения тестируемых сценариев.
Два самых простых — это assertFalse() и assertTrue(). Проверяют, является ли полученное значение false и true соответственно. Далее идут уже упомянутый assertEquals() и обратный ему assertNotEquals(). В их использовании есть нюансы. Так при сравнении чисел с плавающей точкой есть возможность указать точность сравнения. Так же эти методы используются для сравнения экземпляров класса DOMDocument, массивов и любых объектов (в последнем случае равенство будет установлено, если атрибуты объектов содержат одинаковые значения). Так же следует упомянуть assertNull() и assertNotNull() которые проверяют соответствие параметра типу данных NULL (да-да, не забываем, что в PHP это отдельный тип данных). Этим возможные сравнения не ограничиваются. Нет смысла в рамках этой статьи заниматься перепечаткой документации, потому приведу по возможности структурированный список всех возможных методов. Более детально интересующиеся могут прочитать здесь
Базовые методы сравнения
assertTrue() / assertFalse()
assertEquals() / assertNotEquals()
assertGreaterThan()
assertGreaterThanOrEqual()
assertLessThan()
assertLessThanOrEqual()
assertNull() / assertNotNull()
assertType() / assertNotType()
assertSame() / assertNotSame()
assertRegExp() / assertNotRegExp()
Методы сравнения массивов
assertArrayHasKey() / assertArrayNotHasKey()
assertContains() / assertNotContains()
assertContainsOnly() / assertNotContainsOnly()
ООП специфичные методы
assertClassHasAttribute() / assertClassNotHasAttribute()
assertClassHasStaticAttribute() / assertClassNotHasStaticAttribute()
assertAttributeContains() / assertAttributeNotContains()
assertObjectHasAttribute() / assertObjectNotHasAttribute()
assertAttributeGreaterThan()
assertAttributeGreaterThanOrEqual()
assertAttributeLessThan()
assertAttributeLessThanOrEqual()
Методы сравнения файлов
assertFileEquals() / assertFileNotEquals()
assertFileExists() / assertFileNotExists()
assertStringEqualsFile() / assertStringNotEqualsFile()
Методы сравнения XML
assertEqualXMLStructure()
assertXmlFileEqualsXmlFile() / assertXmlFileNotEqualsXmlFile()
assertXmlStringEqualsXmlFile() / assertXmlStringNotEqualsXmlFile()
assertXmlStringEqualsXmlString() / assertXmlStringNotEqualsXmlString()
Разное
assertTag()
assertThat()
Исключения
Если еще не надоело, то вернемся к практике, а именно к обработке исключений. Для начала модифицируем наш тестируемый класс — введем в него метод, который будет это исключение выбрасывать.
class MathException extends Exception < >;
Теперь надо создать тест, который будет завершаться успешно в том случае, если при определенном наборе данных будет вызвано это исключение. Задать требуемое исключение можно как минимум двумя способами — добавив к тесту @expectedException либо вызвав в тесте метод setExpectedException().
require_once ‘PHPUnit/Framework.php’ ;
require_once ‘MyClass.php’ ;
class MyClassTest extends PHPUnit_Framework_TestCase <
Тесты, в общем-то, абсолютно идентичны. Выбор способа остается на ваше усмотрение. Помимо механизмов предоставляемых непосредственно PHPUnit, для тестирования исключений можно воспользоваться стандартным try <…>catch (), к примеру, так:
require_once ‘PHPUnit/Framework.php’ ;
require_once ‘MyClass.php’ ;
class MyClassTest extends PHPUnit_Framework_TestCase <
В этом примере мы так же видим не рассмотренный ранее способ завершения теста с помощью вызова метода fail(). Вывод теста будет следующим:
F
Time: 0 seconds
There was 1 failure:
1) testDivision3(MyClassTest)
Not raise an exception
/home/user/unit/MyClassTest.php:50
Принадлежности
Базовые методы тестирования мы освоили. Можно ли улучшить наш тест? Да. Написанный c начала этой статьи класс проводит несколько тестов, в каждом из которых создается экземпляр тестируемого класса, что абсолютно излишне, потому как PHPUnit предоставляет в наше пользование механизм принадлежностей теста (fixtures). Установить их можно защищенным методом setUp(), который вызывается один раз перед началом каждого теста. После окончания теста вызывается метод tearDown(), в котором мы можем провести «сборку мусора». Таким образом, исправленный тест может выглядеть так:
require_once ‘PHPUnit/Framework.php’ ;
require_once ‘MyClass.php’ ;
class MyClassTest extends PHPUnit_Framework_TestCase <
Наборы тестов
После того, как код нескольких классов будет покрыт тестами, становится довольно таки неудобно запускать каждый тест по отдельности. Здесь нам на помощь могут прийти наборы тестов — несколько связанных единой задачей тестов можно объединить в набор и запускать соответственно его. Наборы реализованы классом PHPUnit_Framework_TestSuite. Необходимо создать экземпляр этого класса и добавить в него необходимые тесты с помощью метода addTestSuite(). Так же с помощью метода addTest() возможно добавление другого набора.
require_once ‘PHPUnit/Framework.php’ ;
// подключаем файлы с тестами
require_once ‘MyClassTest.php’ ;
require_once ‘PHPUnit/Framework.php’ ;
// подключаем файл с набором тестов
require_once ‘SpecificTests.php’ ;
А теперь представим себе набор тестов для сценария, работающего с БД. Неужели нам в каждом тесте придется подключаться к базе? Нет — не придется. Для этого можно создать свой класс унаследованный от PHPUnit_Framework_TestSuite, определить его методы setUp() и tearDown() для инициализации интерфейса БД и просто передать его в тест атрибутом sharedFixture. Базы данных мы оставим на потом, а пока попробуем создать собственный набор тестов для уже имеющегося класса.
require_once ‘PHPUnit/Framework.php’ ;
require_once ‘MyClass.php’ ;
class MyClassTest extends PHPUnit_Framework_TestCase <
class MySuite extends PHPUnit_Framework_TestSuite <
Здесь мы в sharedFixture положили экземпляр тестируемого класса, а в тесте просто его использовали — решение не слишком красивое (я бы даже сказал, вообще не красивое), но общее представление о наборах тестов и передаче принадлежностей между тестами оно дает. Если наглядно изобразить очередность вызова методов, то получится нечто вроде такого:
MySuite::setUp()
MyClassTest::setUp()
MyClassTest::testPower()
MyClassTest::tearDown()
MyClassTest::setUp()
MyClassTest::testDivision()
MyClassTest::tearDown()
.
MySuite::tearDown()
Дополнительные возможности
Помимо всего вышеизложенного может возникнуть необходимость проверить не только расчеты и поведение сценария, но так же вывод и скорость отработки. Для этого в наше распоряжение предоставлены расширения PHPUnit_Extensions_OutputTestCase и PHPUnit_Extensions_PerformanceTestCase соответственно. Добавим в наш тестируемый класс еще один метод, и проверим правильно ли он работает.
require_once ‘PHPUnit/Framework.php’ ;
require_once ‘PHPUnit/Extensions/OutputTestCase.php’ ;
require_once ‘PHPUnit/Extensions/PerformanceTestCase.php’ ;
require_once ‘MyClass.php’ ;
class MyClassOutputTest extends PHPUnit_Extensions_OutputTestCase <
class MyClassPerformanceTest extends PHPUnit_Extensions_PerformanceTestCase <
class MyClassTest extends PHPUnit_Framework_TestCase <
Задать ожидаемый вывод сценария можно с помощью методов expectOutputString() или expectOutputRegex(). А для метода setMaxRunningTime() планируемое время отработки указывается в секундах. Для того, что бы эти тесты запускались вместе с уже написанными их всего лишь надо добавить к нашему набору:
class MySuite extends PHPUnit_Framework_TestSuite <
Пропускаем тесты
И напоследок рассмотрим ситуацию, в которой некоторые тесты необходимо пропускать по каким либо причинам. К примеру в том случае, когда на тестируемой машине отсутствует какое-либо расширение PHP, можно убедившись в его отсутствии пометить тест, как пропущенный добавив к его коду следующее:
Либо в том случае, когда тест написан для кода, которого еще нет в сценарии (не редкая для TDD ситуация) его можно пометить как не реализованный с помощью метода markTestIncomplete()