Nano Hash - криптовалюты, майнинг, программирование

Как выводить в CLI во время выполнения модульных тестов PHP?

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

Я пробовал следующее (похоже на Руководство по PHPUnit пример);

class theTest extends PHPUnit_Framework_TestCase
{
    /**
     * @outputBuffering disabled
     */
    public function testOutput() {
        print_r("Hello World");
        print "Ping";
        echo "Pong";
        $out = "Foo";
        var_dump($out);
    }   
}

Со следующим результатом:

PHPUnit @package_version@ by Sebastian Bergmann.

.

Time: 0 seconds, Memory: 3.00Mb

OK (1 test, 0 assertions)

Обратите внимание, что ожидаемого результата нет.

Я использую HEAD-версии репозиториев git по состоянию на 19 сентября 2011 года.

Вывод php -version:

$ php -version
PHP 5.2.9 (cli) (built: Dec  8 2010 11:36:37) 
Copyright (c) 1997-2009 The PHP Group
Zend Engine v2.2.0, Copyright (c) 1998-2009 Zend Technologies
    with Xdebug v2.1.0, Copyright (c) 2002-2010, by Derick Rethans

Я что-то делаю неправильно, или это потенциально ошибка PHPUnit?

20.09.2011

  • Где код, вызывающий метод testOutput()? 21.09.2011
  • Вы очень отчаянно пытаетесь (echo, print, print_r, var_dump - это в основном весь вывод), обычно у меня нет проблем с выводом результатов тестов. Вы можете проверить, включена ли буферизация вывода: php.net/manual /en/function.ob-get-level.php - И самый безопасный способ принудительного тестирования - это создать исключение BTW. 21.09.2011
  • @DerrickTucker PHPUnit делает это, вызывая phpunit /path/to/tests/theTest.php (если указанный выше класс был в файле theTest.php). 21.09.2011
  • @hakre ob_get_level() возвращает 1. Однако этому противоречит следующий код: while (ob_get_level() > 0) { ob_end_flush(); } который ошибки с ob_end_clean(): failed to delete buffer. No buffer to delete.. Все любопытнее и любопытнее. 21.09.2011
  • ob_end_clean()-error: всегда проверяйте файл и строку с ошибкой, возможно, это не ваш код. 21.09.2011
  • @hakre Действительно, это дает мне phpunit.php: 46 что не так полезно, кроме как сказать, что это код где-то внутри теста (где вызывается ob_end_flush), правильно? 21.09.2011
  • Он говорит, что это код phpunit вызывает ошибку - очевидно, потому что проглатывание вывода phpunits активно (но вы его сломали). Посмотрите внимательно, название функции тоже отличается. 21.09.2011
  • Я должен вернуться к проблеме, так как был уверен, что это сработает. У меня это работает, не устанавливая никаких специальных аннотаций, вызывая частный тестовый метод, который использует printf. Вывод записывается в STDOUT при запуске testrunner из оболочки. Ничего особенного. PHPUnit 3.5.11. 03.10.2011

Ответы:


1

ОБНОВЛЕНИЕ

Только что реализовал другой способ сделать это, который работает намного лучше, чем параметр командной строки --verbose:

class TestSomething extends PHPUnit_Framework_TestCase {
    function testSomething() {
        $myDebugVar = array(1, 2, 3);
        fwrite(STDERR, print_r($myDebugVar, TRUE));
    }
}

Это позволяет выгрузить что-либо на консоль в любое время без нежелательного вывода, связанного с опцией --verbose CLI.


Как отмечали другие ответы, лучше всего тестировать вывод с помощью встроенных методов, таких как:

$this->expectOutputString('foo');

Однако иногда полезно проявить непослушание и увидеть одноразовые / временные результаты отладки в ваших тестовых примерах. Впрочем, var_dump хак / обходной путь не требуется. Это легко сделать, установив параметр командной строки --verbose при запуске вашего набора тестов. Например:

$ phpunit --verbose -c phpunit.xml

Это отобразит выходные данные из ваших методов тестирования при работе в среде CLI.

См .: Написание тестов для PHPUnit - Тестирование вывода .

26.09.2012
  • извините, пропустил пишем на stderr. Действительно работает. Мне просто пришлось вместо этого использовать file_put_contents('php://stderr', $myDebugVar, FILE_APPEND);, потому что у меня было сообщение Use of undefined constant STDERR - assumed 'STDERR' с fwrite. 19.11.2013
  • Проблема в том, что это не работает с изоляцией процесса. 11.06.2014
  • @donquixote Неудивительно, поскольку тест будет выполняться в другом процессе, чей вывод потока STDERR, вероятно, будет отброшен ... 11.06.2014
  • Вы также можете использовать STDOUT вместо STERR 28.02.2015
  • @ Крис Ты уверен в этом? Возможно, вы правы, но я не проверял. Я думаю STDOUT перехватывается phpunit через ob_start() (именно поэтому вы не можете просто echo вещи в первую очередь). Это логика использования STDERR 01.03.2015
  • да. Он работает и, кажется, выводит так же, как STDERR. Я использую PHPUnit 4.5.0 в строке cmd Windows. оператор echo не дает тех же результатов. echo выводит данные, но только после того, как отобразится результат теста. fwrite(STDERR, 'string') или fwrite(STDOUT,'string') дают те же результаты: вывод перед отображением результата теста. 01.03.2015
  • посмотрите здесь: phpunit.de/manual/current/en/fixtures.html в примере 4.2. они используют STDOUT 01.03.2015
  • Спасибо! Это было единственное решение, которое сработало для меня с phpunit 7.4.3 (включая --debug и --verbose) в контейнере Docker. Все остальное проглотил - даже лог пишет! 10.04.2019

  • 2

    Обновление. См. обновление rdlowrey ниже относительно использования fwrite(STDERR, print_r($myDebugVar, TRUE)); как более простого решения


    Такое поведение является преднамеренным (поскольку jasonbar имеет указал). Конфликтующее состояние руководства было в PHPUnit.

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

    class theTest extends PHPUnit_Framework_TestCase
    {
        /**
         * @outputBuffering disabled
         */
        public function testOutput() {
            $this->expectOutputString(''); // tell PHPUnit to expect '' as output
            print_r("Hello World");
            print "Ping";
            echo "Pong";
            $out = "Foo";
            var_dump($out);
        }   
    }
    

    дает:

    PHPUnit @package_version@ by Sebastian Bergmann.
    
    F
    
    Time: 1 second, Memory: 3.50Mb
    
    There was 1 failure:
    
    1) theTest::testOutput
    Failed asserting that two strings are equal.
    --- Expected
    +++ Actual
    @@ @@
    -''
    +'Hello WorldPingPongstring(4) "Foo"
    +'
    
    FAILURES!
    Tests: 1, Assertions: 1, Failures: 1.
    

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

    21.09.2011

    3

    Попробуйте использовать --debug

    Полезно, если вы пытаетесь найти правильный путь к включаемому или исходному файлу данных.

    20.05.2013
  • Это правильный ответ для меня. Все утверждения fwrite, написанные в более ранних ответах, для меня не работали. 28.12.2014

  • 4

    Это не ошибка, но это сделано намеренно. Лучше всего записать в какой-либо файл журнала и следить за выходом журнала.

    Если вы пытаетесь ПРОВЕРИТЬ вывод, отметьте это.

    Также:

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

    21.09.2011
  • Если бы это было намеренно, то, конечно, в руководстве не было бы приведи пример? Кроме того, не пытайтесь тестировать сам вывод. Просто используйте его, чтобы увидеть некоторые результаты, из-за которых тесты терпят неудачу, а не должны. 21.09.2011
  • Как написано: Обычно у меня нет проблемы с эхом при запуске тестов. У вас может быть какая-то конфигурация, которая улавливает ввод. 21.09.2011
  • Если бы это было не намеренно, то, конечно же, руководство не было бы скажите, что это было. 21.09.2011
  • Так кажется конфликт в документации. @hakre, похоже, находится под тем же впечатлением, что и я (что его нельзя глотать) - какая часть документации верна? 21.09.2011
  • Тесты генерации вывода завершаются неудачно, ТОЛЬКО когда --disallow-test-output (или файл conf имеет beStrictAboutOutputDuringTests = true) - в документации теперь указано, что тест, который генерирует вывод, например, путем вызова print либо в тестовом коде, либо в тестируемом коде, будет отмечен так же рискованно, когда эта проверка включена. phpunit.readthedocs.io/en/8.4/risky-tests. html # risky-tests 12.11.2019

  • 5

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

    Это означает, что вам будет нужна информация всегда, когда тест терпит неудачу, а добавление var_dump для поиска причины - слишком большая работа. Скорее вложите данные в свои утверждения.

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

    21.09.2011
  • Я согласен на 100% со всем, что вы сказали. Я использую PHPUnit для выполнения интеграционных тестов, которые в конечном итоге вызывают один из XML API Google. Все модульные тесты пройдены (с имитацией вызовов API), но окончательный тест (с вызовами живого API) не прошел. Оказалось, что это была ошибка Google API а пока я хотел сбросить необработанный HTTP-ответ. 22.09.2011
  • Что, если вам нужно отладить свой код на пути к достижению того, что вы здесь изложили? 24.05.2015
  • Вот почему мне не нравятся ответы, в которых возникают сомнения в том, что хотят делать пользователи. Я здесь, потому что у меня есть тест, ожидающий очистки кеша. С 5-секундным ttls кеша это означает, что мой тест зависает на ~ 16 секунд. Я просто хотел бы уведомить пользователя о том, что нет, все в порядке, мы просто ждем, пока истечет время ожидания кешей. Если люди могут просто ответить на вопрос, то люди с другими вариантами использования тоже получат свой ответ. 14.10.2019

  • 6

    Мне повезло с VisualPHPUnit, и, помимо прочего, он помогает отображать вывод.

    class TestHello extends PHPUnit_Framework_TestCase 
    {
        public function test_Hello() 
        {
            print "hello world";
        }
    }
    

    Результаты TestHello

    25.03.2013
  • Хм, а почему голос против? Чем это бесполезно в качестве альтернативного способа сбросить отладочную информацию в тесте PHPUnit? 04.02.2014
  • Я предполагаю, что это отклонено, потому что, если кто-то попытается запустить это, вы получите синтаксическую ошибку. Массивный. 15.04.2014
  • D'oh я забыл функцию. Теперь починил, проверил, вырезал и приклеил. Спасибо, @Jimbo 15.04.2014
  • К сожалению, на данный момент он несовместим с PHP 7, по-видимому: VisualPHPUnit не совместим с php 7 в настоящее время из-за способа использования phpunit. Php 7 будет поддерживаться в следующем основном выпуске. 24.01.2020

  • 7

    В laravel 5 вы можете использовать dump (), выгрузить содержимое из последнего ответа.

    class ExampleTest extends TestCase{
        public function test1()
        {
            $this->post('/user', ['name' => 'Gema']);
            $this->dump();
        }
    }
    

    дает

    08.07.2016

    8

    Просто используйте флаг --verbose при выполнении phpunit.

    $ phpunit --verbose -c phpunit.xml 
    

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

    Надеюсь, это поможет.

    22.05.2018

    9

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

    class yourTests extends PHPUnit_Framework_TestCase
    {
        /* Add Warnings */
        protected function addWarning($msg, Exception $previous = null)
        {
            $add_warning = $this->getTestResultObject();
            $msg = new PHPUnit_Framework_Warning($msg, 0, $previous);
            $add_warning->addWarning($this, $msg, time());
            $this->setTestResultObject($add_warning);
        }
    
        /* Add errors */
        protected function addError($msg, Exception $previous = null)
        {
            $add_error = $this->getTestResultObject();
            $msg = new PHPUnit_Framework_AssertionFailedError($msg, 0, $previous);
            $add_error->addError($this, $msg, time());
            $this->setTestResultObject($add_error);
        }
    
        /* Add failures */
        protected function addFailure($msg, Exception $previous = null)
        {
            $add_failure = $this->getTestResultObject();
            $msg = new PHPUnit_Framework_AssertionFailedError($msg, 0, $previous);
            $add_failure->addFailure($this, $msg, time());
            $this->setTestResultObject($add_failure);
        }
    
        public function test_messages()
        {
            $this->addWarning("Your warning message!");
            $this->addError("Your error message!");
            $this->addFailure("Your Failure message");
        }
    
        /* Or just mark test states! */
        public function test_testMarking()
        {
            $this->markTestIncomplete();
            $this->markTestSkipped();
        }
    }
    
    21.12.2015

    10

    Это было взято из документации PHPUnit о приспособлениях.

    Это должно позволить вам сбрасывать информацию в любой момент в течение жизненного цикла теста phpunit.

    Просто замените __METHOD__ в приведенном ниже коде тем, что вы хотите вывести.

    Пример 4.2: Пример, показывающий все доступные методы шаблона

    <?php
    class TemplateMethodsTest extends PHPUnit_Framework_TestCase
    {
        public static function setUpBeforeClass()
        {
            fwrite(STDOUT, __METHOD__ . "\n");
        }
    
        protected function setUp()
        {
            fwrite(STDOUT, __METHOD__ . "\n");
        }
    
        protected function assertPreConditions()
        {
            fwrite(STDOUT, __METHOD__ . "\n");
        }
    
        public function testOne()
        {
            fwrite(STDOUT, __METHOD__ . "\n");
            $this->assertTrue(TRUE);
        }
    
        public function testTwo()
        {
            fwrite(STDOUT, __METHOD__ . "\n");
            $this->assertTrue(FALSE);
        }
    
        protected function assertPostConditions()
        {
            fwrite(STDOUT, __METHOD__ . "\n");
        }
    
        protected function tearDown()
        {
            fwrite(STDOUT, __METHOD__ . "\n");
        }
    
        public static function tearDownAfterClass()
        {
            fwrite(STDOUT, __METHOD__ . "\n");
        }
    
        protected function onNotSuccessfulTest(Exception $e)
        {
            fwrite(STDOUT, __METHOD__ . "\n");
            throw $e;
        }
    }
    ?>
    
    01.03.2015

    11

    Хакерство, но работает: выбросить исключение с выводом отладки в качестве сообщения.

    class theTest extends PHPUnit_Framework_TestCase
    {
        public function testOutput() {
            throw new \Exception("hello");
        }   
    }
    

    Урожайность:

    ...
    There was 1 error:
    
    1) theTest::testOutput
    Exception: hello
    
    28.02.2018

    12

    PHPUnit скрывает вывод с помощью ob_start(). Мы можем временно отключить его.

        public function log($something = null)
        {
            ob_end_clean();
            var_dump($something);
            ob_start();
        }
    
    16.01.2020

    13

    Я вывожу свои Testresults на основе HTML, в этом случае было полезно очистить содержимое:

    var_dump($array);
    ob_flush();
    

    Есть второй метод PHP

    flush() 
    

    который я не пробовал.

    27.09.2017

    14

    это платный продукт, но я считаю, что он хорошо справляется со своей задачей: Рэй из Spatie https://spatie.be/products/ray

    просто используйте это так:

    луч ('сообщение')

    и сообщение появится в окне вывода лучей.

    10.06.2021

    15

    Мне пришлось изменить исходный код, чтобы этот код работал, поэтому вам нужно добавить URL для этот разветвленный репозиторий композитору для этого будет работать

    class TestCase extends \PHPUnit_Framework_TestCase
    {
        /**
         *  Save last response
         * @var Response|null A Response instance
         */
        static $lastResponse;
        /**
         *  Modify to save response
         *
         * @param  string $method
         * @param  string $uri
         * @param  array $parameters
         * @param  array $files
         * @param  array $server
         * @param  string $content
         * @param  bool $changeHistory
         * @return \Illuminate\Http\Response
         */
        final public function call(
            $method,
            $uri,
            $parameters = [],
            $files = [],
            $server = [],
            $content = null,
            $changeHistory = true
        ) {
    
            $response = parent::call($method, $uri, $parameters, $files, $server, $content, $changeHistory);
            static::$lastResponse = $this->client->getResponse();
            return $response;
        }
    
    
        /**
         * Modify message to add response text
         *
         * @param mixed $value
         * @param PHPUnit_Framework_Constraint $constraint
         * @param string $message
         * @since  Method available since Release 3.0.0
         */
        final public static function assertThat($value, PHPUnit_Framework_Constraint $constraint, $message = '')
        {
            $message .= PHP_EOL . static::$lastResponse . PHP_EOL;
            parent::assertThat($value, $constraint, $message);
        }
    }
    
    08.10.2014

    16

    Вот несколько методов, полезных для печати отладочных сообщений в PHPUnit 4.x:

    • syslog(LOG_DEBUG, "Debug: Message 1!");

      Более практичный пример:

      syslog(LOG_DEBUG, sprintf("%s: Value: %s", __METHOD__, var_export($_GET, TRUE)));
      

      Вызов syslog() приведет к созданию сообщения системного журнала (см .: man syslog.conf).

      Примечание: возможные уровни: LOG_DEBUG, LOG_INFO, LOG_NOTICE, LOG_WARNING, LOG_ERR и т. д.

      В macOS для потоковой передачи сообщений системного журнала в реальном времени выполните:

      log stream --level debug --predicate 'processImagePath contains "php"'
      
    • fwrite(STDERR, "LOG: Message 2!\n");

      Примечание. Константа STDERR недоступна при чтении сценария PHP из stdin. Вот обходной путь.

      Примечание: вместо STDERR вы также можете указать имя файла.

    • file_put_contents('php://stderr', "LOG: Message 3!\n", FILE_APPEND);

      Примечание. Используйте этот метод, если у вас нет Определена STDERR константа.

    • register_shutdown_function('file_put_contents', 'php://stderr', "LOG: Message 4!\n", FILE_APPEND);

      Примечание: используйте этот метод, если вы хотите напечатать что-то в самом конце, не влияя на тесты.

    Чтобы выгрузить переменную, используйте var_export(), например "Value: " . var_export($some_var, TRUE) . "\n".

    Чтобы распечатать вышеуказанные сообщения только в режиме подробного вывода или отладки, см .: Есть ли способ узнать, передано ли --debug или --verbose в PHPUnit в тесте?


    Хотя, если тестирование вывода является частью самого теста, проверьте: Выходные данные тестирования документы.

    02.02.2018

    17

    Короче говоря, phpunit подавляет STDOUT. По умолчанию он записывает в STDERR, если вы не добавите --verbose или --debug. Вы можете сделать одно из следующих действий:

    • вместо этого распечатайте выходные данные отладки в STDERR
    • var_dump ваша отладка как обычно, но добавьте --verbose в командную строку phpunit
    • var_dump выполняйте отладку как обычно, но добавьте строку ob_flush(); под ней
    • используйте правильные команды в phpunit для тестирования именно того, что вы пытаетесь проверить здесь

    Очевидно, что самое хорошее - это последнее, что нужно делать, а все остальное - это быстрые временные взломы.

    07.09.2020

    18

    Вы можете использовать способ отображения сообщений PHPunit по умолчанию для отладки переменных внутри вашего теста следующим образом:

    $this->assertTrue(false,$your_variable);
    
    17.10.2020
  • Это приведет к сбою выполнения теста. Что, если я хочу выводить контент, но не прерывать выполнение тестов? 13.05.2021

  • 19

    Можно использовать Symfony\Component\Console\Output\TrimmedBufferOutput, а затем проверить буферизованную строку вывода следующим образом:

    use Symfony\Component\Console\Output\TrimmedBufferOutput;
    
    //...
    public function testSomething()
    {
       $output = new TrimmedBufferOutput(999);
       $output->writeln('Do something in your code with the output class...');
       
       //test the output:
       $this->assertStringContainsString('expected string...', $output->fetch());   
    }
    
    08.12.2020

    20

    Просто позвоните ob_flush() после вывода текста

    Пример кода:

        public function testDebugOutputToCli() {
            var_dump(new DateTime());
            ob_flush();
        }
    

    Снимок экрана с кодом и выводом:

    Снимок экрана использования ob_flush для вывода содержимого, которое в противном случае было бы скрыто PHPUnit

    Почему? PHPUnit всегда буферизует вывод, поэтому нам нужно сбросить буфер при отладке.

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

    Я читал руководство PHPUnit, как хороший ботаник, и наткнулся на это, что, как мне кажется, объясняет, что вызывает всю эту проблему во всем PHPUnit, а не только в Codeception:

    Руководство PHPUnit, результаты тестирования: «Иногда вы хотите утверждать, что выполнение метода, например, генерирует ожидаемый результат (например, через эхо или печать). Класс PHPUnit \ Framework \ TestCase использует функцию буферизации вывода PHP для обеспечения необходимой для этого функциональности ».

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

    Но когда мы отлаживаем, мы просто хотим сразу увидеть текст, и, понимая все это, решение очевидное: Просто используйте ob_flush() для печати содержимого выходного буфера по запросу!

    Три ура за чтение забавных руководств!

    P.S. Также нашел этот совет, скрытый в Как показать var_dumps в phpunit или codeception от Джулиана на dev.to

    10.07.2021

    21

    Если вы используете Laravel, вы можете использовать функции ведения журнала, такие как info (), для входа в файл журнала Laravel в разделе storage / logs. Таким образом, он появится не в вашем терминале, а в файле журнала.

    24.01.2020
    Новые материалы

    Кластеризация: более глубокий взгляд
    Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

    Как написать эффективное резюме
    Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

    Частный метод Python: улучшение инкапсуляции и безопасности
    Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

    Как я автоматизирую тестирование с помощью Jest
    Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

    Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
    Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

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

    Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
    В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..