PHP यूनिट परीक्षणों के निष्पादन के दौरान CLI में आउटपुट कैसे करें?


151

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)

ध्यान दें कि अपेक्षित आउटपुट नहीं है।

मैं सितंबर 19, 2011 तक git repos के HEAD संस्करणों का उपयोग कर रहा हूं ।

का आउटपुट 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 बग है?


1
testOutput()विधि को कॉल करने वाला कोड कहां है ?
डेरिक टकर

आप वास्तव में सख्त कोशिश करते हैं (गूंज, प्रिंट, प्रिंट_, var_dump - यह मूल रूप से सभी "आउटपुट" है), आम तौर पर मुझे परीक्षण से आउटपुट करने में कोई समस्या नहीं है। आउटपुट बफ़रिंग सक्षम है या नहीं, आप जाँच सकते हैं: php.net/manual/en/function.ob-get-level.php - और बलपूर्वक "परीक्षण" का सबसे सुरक्षित तरीका एक अपवाद बीटीडब्लू फेंकना है।
हकेरे

3
@DerrickTucker PHPUnit इसे कॉल करके करता है phpunit /path/to/tests/theTest.php(यदि उपरोक्त वर्ग फ़ाइल में था theTest.php)।
जेस टल्फर्ड

@ ठेकरे ob_get_level()लौटते हैं 1। हालांकि, यह निम्नलिखित कोड द्वारा विरोधाभास है: while (ob_get_level() > 0) { ob_end_flush(); }जो त्रुटियों के साथ ob_end_clean(): failed to delete buffer. No buffer to delete.। अजीब तरह से।
जेस टेलफ़ोर्ड

1
यह कह रहा है कि यह phpunit का कोड है जो त्रुटि को ट्रिगर कर रहा है - जाहिर है क्योंकि phpunits आउटपुट निगल रहा है सक्रिय है (लेकिन आपने इसे तोड़ दिया है)। ठीक से देखो, फ़ंक्शन का नाम भी अलग है।
हक़

जवाबों:


196

अपडेट करें

इसे करने का एक और तरीका है जो --verboseकमांड लाइन विकल्प की तुलना में बहुत बेहतर काम करता है :

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

यह आपको --verboseCLI विकल्प के साथ आने वाले सभी अवांछित आउटपुट के बिना किसी भी समय आपके कंसोल के लिए कुछ भी डंप करने देता है ।


जैसा कि अन्य उत्तरों ने उल्लेख किया है, बिल्ट-इन तरीकों का उपयोग करके आउटपुट का परीक्षण करना सबसे अच्छा है:

$this->expectOutputString('foo');

हालांकि, कभी-कभी यह शरारती होने में मददगार होता है और आपके परीक्षण मामलों में एक-बंद / अस्थायी डिबगिंग आउटपुट को देखता है। var_dumpहालांकि हैक / वर्कअराउंड की कोई आवश्यकता नहीं है । --verboseअपने टेस्ट सूट को चलाते समय कमांड लाइन विकल्प को सेट करके इसे आसानी से पूरा किया जा सकता है । उदाहरण के लिए:

$ phpunit --verbose -c phpunit.xml

यह CLI वातावरण में चलने पर आपके परीक्षण विधियों के अंदर से आउटपुट प्रदर्शित करेगा।

देखें: PHPUnit के लिए लेखन परीक्षण - परीक्षण आउटपुट


5
क्षमा करें, याद किया हम stderr करने के लिए लिखें। वास्तव में काम करता है। मुझे सिर्फ file_put_contents('php://stderr', $myDebugVar, FILE_APPEND);इसके बजाय उपयोग करने के लिए मजबूर किया गया था , क्योंकि मेरे पास राइटाइट केUse of undefined constant STDERR - assumed 'STDERR' साथ संदेश था ।
सर्ज

समस्या यह है कि यह प्रक्रिया अलगाव के साथ काम नहीं करता है।
दान

@donquixote इस बात से आश्चर्यचकित नहीं है कि परीक्षण एक अन्य प्रक्रिया में निष्पादित होगा जिसकी STDERR स्ट्रीम आउटपुट संभावित रूप से खारिज कर दी गई है ...
rdlowrey

1
आप STDOUTइसके बजाय का उपयोग कर सकते हैंSTERR
क्रिस

2
हाँ। यह काम करता है और उसी तरह आउटपुट करता है STDERR। मैं PHPUnit 4.5.0विंडोज़ cmd लाइन में उपयोग कर रहा हूँ । एक echoबयान समान परिणाम नहीं देता है। echoउत्पादन करता है, लेकिन केवल परीक्षा परिणाम प्रदर्शित होने के बाद। fwrite(STDERR, 'string')या fwrite(STDOUT,'string')एक ही परिणाम का उत्पादन: परीक्षण के परिणाम प्रदर्शित होने से पहले एक आउटपुट।
क्रिस

33

अद्यतन: देखें rdlowrey का अद्यतन नीचे के fwrite(STDERR, print_r($myDebugVar, TRUE));रूप में एक बहुत सरल काम के उपयोग के बारे में है


यह व्यवहार जानबूझकर किया गया है (जैसा कि जोंसर ने बताया है )। मैनुअल की परस्पर विरोधी स्थिति को 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.

परीक्षण के लिए आपके पास मौजूद किसी भी अन्य दावे को निष्क्रिय करने के लिए निश्चित रहें क्योंकि वे आउटपुट के परीक्षण से पहले विफल हो सकते हैं (और इसलिए आप आउटपुट नहीं देख पाएंगे)।


33

प्रयोग करके देखें --debug

उपयोगी यदि आप किसी शामिल या स्रोत डेटा फ़ाइल के लिए सही पथ प्राप्त करने का प्रयास कर रहे हैं।


2
यह मेरे लिए सही उत्तर है। पहले के जवाबों में लिखे गए सभी फर्जी बयान मेरे लिए कारगर नहीं थे।
किम स्टैक

9

यह बग नहीं है, लेकिन बहुत जानबूझकर है। आपका सबसे अच्छा शर्त यह है कि किसी प्रकार की लॉग फ़ाइल में लिखें और आउटपुट के लिए लॉग को देखने के लिए लॉग को पूंछें।

यदि आप परीक्षण आउटपुट की कोशिश कर रहे हैं, तो इसे देखें

इसके अलावा:

नोट : कृपया ध्यान दें कि PHPUnit एक परीक्षण के निष्पादन के दौरान उत्सर्जित सभी आउटपुट को निगल लेता है। सख्त मोड में, आउटपुट का उत्सर्जन करने वाला परीक्षण विफल हो जाएगा।


1
यदि यह जानबूझकर होता, तो निश्चित रूप से मैनुअल इसका उदाहरण नहीं देता ? इसके अलावा, आउटपुट का परीक्षण करने की कोशिश नहीं कर रहा है। बस इसका उपयोग करने के लिए कुछ परिणाम देखने के लिए परीक्षण विफल हो जाता है जब वे नहीं करना चाहिए।
जेस टेलफ़ोर्ड

जैसा कि लिखा है: जब परीक्षण चलते हैं तो मुझे आम तौर पर गूंजने की समस्या नहीं होती है। आपके पास कुछ कॉन्फ़िगरेशन हो सकते हैं जो इनपुट को पकड़ रहे हैं।
हक़

1
यदि यह जानबूझकर नहीं किया गया था, तो निश्चित रूप से मैनुअल यह नहीं कहेगा कि यह था
जसोब्बर

1
तो यह प्रलेखन में एक संघर्ष लगता है। @ ठाकरे उसी धारणा के तहत प्रतीत होते हैं जो मैं था (कि इसे निगला नहीं जाना चाहिए) - प्रलेखन का कौन सा हिस्सा सही है?
जेस टेलफ़ोर्ड

आउटपुट जनरेटिंग परीक्षण केवल तभी विफल हो जाते हैं जब -disallow-test-output (या conf फ़ाइल beStrictAboutOutputDuringTests = "true") - प्रलेखन अब कहता है कि "एक परीक्षण जो आउटपुट का उत्सर्जन करता है, उदाहरण के लिए या तो परीक्षण कोड या परीक्षण कोड में प्रिंट को इंवाइट करके। यह जाँच सक्षम होने पर जोखिम भरे के रूप में चिह्नित किया जाएगा। " phpunit.readthedocs.io/en/8.4/risky-tests.html#risky-tests
NULL पॉइंटर

7

मैं VisualPHPUnit के साथ कुछ किस्मत वाला हूं , और यह अन्य चीजों के साथ आउटपुट को दिखाने में मदद करता है।

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

TestHello परिणाम


हम्म, डाउनवोट क्यों? यह PHPUnit परीक्षण में डिबग आउटपुट को डंप करने के वैकल्पिक तरीके के रूप में कैसे सहायक नहीं है?
बॉब स्टीन

1
मैं यह अनुमान लगा रहा हूं कि अगर कोई इसे चलाने की कोशिश करता है तो आपको एक सिंटैक्स त्रुटि मिलेगी। एक विशाल।
जिम्बो

D'oh मैं फ़ंक्शन भूल गया। अब यह तय, परीक्षण, कट और चिपकाया गया है। धन्यवाद, @ जिंबो
बॉब स्टीन

दुख की बात यह है कि यह PHP 7 के साथ फिलहाल संगत नहीं है, जाहिरा तौर पर: "VisualPHPUnit इस समय php 7 संगत नहीं है क्योंकि जिस तरह से phpunit का उपयोग किया जाता है। Php 7 अगले प्रमुख रिलीज में समर्थित होगा"
lex

6

आपको वास्तव में अपने इरादों के बारे में सोचना चाहिए: यदि आपको परीक्षण को ठीक करने के लिए डिबगिंग के दौरान अब जानकारी की आवश्यकता है, तो परीक्षण के टूटने पर आपको अगले सप्ताह फिर से इसकी आवश्यकता होगी।

इसका मतलब यह है कि आपको परीक्षण की असफलता होने पर आपको हमेशा जानकारी की आवश्यकता होगी - और var_dumpकारण खोजने के लिए जोड़ना अभी बहुत अधिक काम है। बल्कि डेटा को अपने दावे में लगाएं।

यदि आपका कोड इसके लिए बहुत जटिल है, तो इसे तब तक विभाजित करें जब तक कि आप एक स्तर तक न पहुंच जाएं जहां एक (एक कस्टम संदेश के साथ) आपको यह जानने के लिए पर्याप्त बताता है कि यह कहां टूट गया, क्यों और कैसे कोड को ठीक करना है।


1
मैं आपकी हर बात से 100% सहमत हूँ। मैं एकीकरण परीक्षणों को करने के लिए PHPUnit का उपयोग कर रहा हूं जो अंततः Google के XML एपीआई में से एक कहते हैं। सभी यूनिट परीक्षण पास हुए (एपीआई कॉल के साथ मजाक किया गया), लेकिन अंतिम परीक्षण (लाइव एपीआई कॉल के साथ) विफल रहा। यह पता चला कि यह Google API की गलती थी, लेकिन इस बीच, मैं कच्चे HTTP प्रतिक्रिया को डंप करना चाहता था।
जेस टेलफ़ोर्ड

2
क्या होगा यदि आपको अपने कोड को डिबग करने की आवश्यकता है जो आपने यहां उल्लिखित किया है?
डेविड मीस्टर

2
यही कारण है कि मुझे उत्तर पसंद नहीं हैं कि दूसरा अनुमान लगाता है कि उपयोगकर्ता क्या करना चाहते हैं। मैं यहां हूं क्योंकि मेरे पास परीक्षण है कि कैश क्लियर का इंतजार करें। 5 सेकंड कैश टीटल के साथ, इसका मतलब है कि मेरा परीक्षण ~ 16 सेकंड के लिए लटका हुआ प्रतीत होता है । मैं उपयोगकर्ता को कुछ नोटिस भेजना चाहूंगा कि नहीं, कुछ भी गलत नहीं है, हम केवल समय समाप्त होने का इंतजार कर रहे हैं। यदि लोग सिर्फ सवाल का जवाब दे सकते हैं, तो अन्य उपयोग के मामलों वाले लोगों के पास भी उनका जवाब होगा।
user151841

4

लार्वा 5 में आप डंप () का उपयोग कर सकते हैं, अंतिम प्रतिक्रिया से सामग्री को डंप कर सकते हैं।

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

देता है


4

जब phpunit निष्पादित करते हैं तो बस --verbose ध्वज का उपयोग करें ।

$ phpunit --verbose -c phpunit.xml 

इस पद्धति का लाभ यह है कि आपको परीक्षण कोड को बदलने की आवश्यकता नहीं है, आप स्ट्रिंग को प्रिंट कर सकते हैं, var_dump की ओ कुछ भी जो आप हमेशा चाहते हैं और यह केवल कंसोल में दिखाया जाएगा जब क्रिया मोड सेट किया गया हो।

आशा है कि ये आपकी मदद करेगा।


3

कुछ मामलों के लिए एक सांत्वना के लिए कुछ का उत्पादन करने के लिए कुछ का उपयोग कर सकता है

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();
    }
}

3

हैकिश, लेकिन काम करता है: डिबग आउटपुट के साथ एक अपवाद को इसके संदेश के रूप में फेंक दें।

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

पैदावार:

...
There was 1 error:

1) theTest::testOutput
Exception: hello

2

यह फिक्स्चर के बारे में PHPUnit डॉक्स से लिया गया था ।

यह आपको किसी भी बिंदु पर जानकारी को डंप करने की अनुमति देनी चाहिए जो कि फ़पुनिट परीक्षण जीवन चक्र को नष्ट कर रहा है।

__METHOD__आप जो भी आउटपुट देना चाहते हैं, बस नीचे दिए गए कोड में बदलें

उदाहरण ४.२: उपलब्ध सभी टेम्प्लेट विधियों को दिखाने वाला उदाहरण

<?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;
    }
}
?>

1

मैं अपने Testresults HTML पर आधारित है, इस मामले में यह सामग्री फ्लश करने के लिए उपयोगी था:

var_dump($array);
ob_flush();

एक दूसरी PHP मेथड है

flush() 

जो मैंने कोशिश नहीं की है।


1

PHPUnit आउटपुट को छुपा रहा है ob_start()। हम इसे अस्थायी रूप से अक्षम कर सकते हैं।

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

0

मुझे इस कोड को काम करने के लिए स्रोत कोड को संशोधित करना था, इसलिए आपको इस काम के लिए कंपोजर के लिए इस रीको के लिए 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);
    }
}

0

यहाँ 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 पर, रीयल टाइम में syslog संदेशों को स्ट्रीम करने के लिए, रन करें:

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

    ध्यान दें: STDERRस्थिर नहीं है अगर स्टड से PHP स्क्रिप्ट पढ़ रहा है । यहाँ वर्कअराउंड है

    नोट: इसके बजाय 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"

केवल क्रिया या डिबग मोड के दौरान संदेशों को ऊपर मुद्रित करने के लिए, देखें: क्या यह बताने का कोई तरीका है कि - एक परीक्षण में PHPUnit को --debug या --verbose पारित किया गया था?


हालाँकि यदि आउटपुट का परीक्षण करना परीक्षण का हिस्सा है, तो यह देखें कि: परीक्षण आउटपुट डॉक्स पृष्ठ।


-1

यदि आप Laravel का उपयोग करते हैं, तो आप संग्रहण / लॉग के तहत Laravel लॉग फ़ाइल में लॉग करने के लिए जानकारी () जैसे लॉगिंग फ़ंक्शन का उपयोग कर सकते हैं। तो यह आपके टर्मिनल में नहीं बल्कि लॉग फ़ाइल में दिखाई देगा।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.