Статьи

Вся отладка и отсутствие тестирования делает программиста PHP тупым мальчиком

Несколько лет назад я участвовал в этом классе отладки , целью которого является отображение объекта, зараженного Doctrine ORM:

 public static function dump($var, $maxDepth = 2, $stripTags = true)
    {
        ini_set('html_errors', 'On');

        if (extension_loaded('xdebug')) {
            ini_set('xdebug.var_display_max_depth', $maxDepth);
        }

        $var = self::export($var, $maxDepth++);

        ob_start();
        var_dump($var);
        $dump = ob_get_contents();
        ob_end_clean();

        echo ($stripTags ? strip_tags(html_entity_decode($dump)) : $dump);

        ini_set('html_errors', 'Off');
    }

«Загрязненный» здесь означает, что прокси были вставлены, и весь граф объектов Doctrine был доступен через полевые ссылки заинтересованных объектов домена. Это означало, что использование var_dump () и аналогичных функций приведет к печати журнала длиной в 1 километр.

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


Отладка отстой, тестирование скал — Блог тестирования Google

Например, на прошлой неделе я наткнулся на этот хороший учебник по использованию удаленной отладки в вашей IDE и с помощью Xdebug. По сути, существует удаленный порт, который открывается Xdebug и что среда IDE может отправлять команды, чтобы остановить выполнение сценария в заранее определенных точках останова и возобновить его шаг за шагом, или проверить содержимое переменных.

Если ваш код не работает, это решение кажется хорошим: например, вы можете загрузить форму и отправить ее и остановиться в заранее определенных точках, чтобы точно определить, какая строка кода повреждает отправленные вами данные. В то же время вам не нужно вставлять вызовы var_dump () и print_r (), которые часто нарушают синтаксис ответов:

{
    "some_json" : "value"
}
string(2) "en"

и в этих случаях измените поведение того, что вы отлаживаете (чувствуя себя немного похожим на Гейзенберга сейчас?)

Но он имеет много случайных сложностей и некоторых внутренних свойств всех процессов отладки:

  • это можно выполнить только сквозным образом в браузере : вы не можете изолировать фрагменты кода, такие как отдельный класс или небольшой граф объектов, и вставлять в них значения, если вы не напишите отдельный скрипт, который воспроизводит проблему. Возможность написания этого отдельного сценария будет означать, что вам вообще не нужны возможности отладки, поскольку достаточно var_dump ().
  • Ему не хватает повторяемости, чтобы узнать, исправили ли вы проблему, вам нужно вручную открыть браузер и щелкнуть ссылки или вставить значения в форму и проверить, что происходит. И вы должны помнить, чтобы предпринять те же самые шаги, чтобы воспроизвести ошибку.

К настоящему времени вы уже поняли, что я всегда предлагал бы автоматизированные сквозные и модульные тесты как способ заменить большую часть отладки. Сквозные тесты могут служить только для того, чтобы обнаружить, что ошибка существует, в то время как задача модульного теста состоит в том, чтобы точно сказать вам, где проблема. Эти тесты по определению изолированы глобальным состоянием, таким как стандартный вывод, поэтому вы можете свободно вставлять в них вызовы var_dump ().

$ phpunit --filter JumpsToASecure Tests/Selenium2TestCase/URLTest.php
#!/usr/bin/env php
Shared strategy
PHPUnit @package_version@ by Sebastian Bergmann.

Configuration read from /home/giorgio/code/phpunit-selenium/phpunit.xml

.string(23) "https://www.example.com"


Time: 0 seconds, Memory: 7.00Mb

OK (1 test, 3 assertions)

У вас есть свобода повторять тест столько раз, сколько необходимо, при небольших затратах; и выделить только интересные тестовые случаи, запустив тесты для текущего класса или только для одного из них.

Слушай свои тесты

Смысл этого девиза в том, что если у вас возникают трудности при написании автоматических тестов, вам не нужно сразу подбирать большие пушки, такие как ручное тестирование или сквозные тесты Selenium, а скорее менять свой дизайн, чтобы упростить изоляцию. Целые серии шаблонов, такие как Humble Object, Adapter и Repository, позволяют выполнять модульное тестирование при наличии сложной для тестирования среды, такой как необходимость работать внутри фреймворка, необходимость выполнения HTTP-запросов или частого общения с базой данных.

Если вы пишете:

$ch = curl_init();

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

Нам всегда понадобятся некоторые возможности отладки, особенно в устаревшем коде, который не изолирован от других процессов, файловой системы и стандартного ввода и вывода. Но когда вы едете на машине к механику, он не ездит по городу, чтобы найти проблему, он проводит испытания на его части; при необходимости он отключает их и запускает их изолированно.

Не бросай Xdebug

Тем не менее, особенно при работе с устаревшим кодом, не отказывайтесь от Xdebug, поскольку он предоставляет несколько инструментов, которые могут сэкономить ваш день при очень небольших затратах. Два, которые я часто видел, приходят мне на помощь, когда в джунглях старого, непроверенного кода:

  • xdebug.max_nesting_level остановит бесконечные рекурсии (по умолчанию при глубине трассировки стека 100 вложенных вызовов, что достаточно для большинства кодов PHP).
  • xdebug.scream отключит оператор @.
  • xdebug.auto_trace запишет файл, содержащий все вызовы функций и методов, выполняемые процессами PHP. Это немного тяжело, но позволяет определить точную точку, в которой скрипт завершается в случае, если некоторые вызовы exit () пропускаются через код или происходит ошибка сегментации.

Xdebug также имеет несколько приятных функций, которые не имеют ничего общего с отладкой, таких как покрытие кода PHPUnit и профилирование кода для повышения производительности.

Выводы

Меньше отладки и больше автоматизированного тестирования принесет вам пользу в долгосрочной перспективе, и в этом случае вы можете рассмотреть длительный прогон в несколько минут; при первом повторении ручного теста вы уже экономите время. Однако помните, что только если вы будете ближе к единичным и функциональным уровням тестирования, вы сможете пожинать плоды изоляции: быстро обнаруживать ошибки, предназначенные для нескольких объектов за раз или всего компонента, но не всего стека LAMP. Разделение гигантской процедуры на объекты является одной из целей рефакторинга устаревшего кода.