2014-02-14 7 views
7

Gibt es eine Möglichkeit, einen Test für die Ausgabe auszuführen, die durch einen Aufruf von 'error_log (' Message ')' erzeugt wurde, wenn Unit-Tests mit phpunit durchgeführt wurden?Gibt es eine Möglichkeit, die Ausgabe in PHPUnit-Tests auf error_log zu "erwarten"?

Beispielcode, einer meiner Funktionen prüft eine Kreditkarte mit einem Luhn-Algorithmus:

if($checkLuhn && ($this->_luhn_check($cardNumber) == false)) { 
    error_log(__METHOD__ . " cardNumber failed luhn algorithm check."); 
    return false; 
} 

$ checkLuhn ein boolean in vergangen ist es zu sagen, ob die Prüfung zu tun, die _luhn_check() true zurück, wenn Die $ cardNumber wird übergeben. Problem ist, ich habe mehr als einen Test in dieser Funktion, die falsch zurückgeben kann. Ich kann assertEquals für den Rückgabewert verwenden, aber auch überprüfen, warum der Fehler ausgelöst wurde.

Kannst du error_log überschreiben oder die Syslog-Ausgabe irgendwie in einem Komponententest erfassen?

+1

Gibt es da eine Ausnahme? 'This -> _ luhn_check ($ cardNumber)'? Wenn ja, können Sie diese Ausnahme erhalten und in Ihrem Test protokollieren. – Jhn

+2

Ich denke, dass Sie eine gewisse Abstraktionsebene bei Ihrer Fehlererkennung/Protokollierung vermissen. Wenn Sie eine Klasse zum Protokollieren aller Fehler verwenden, müssen Sie diese Klasse nur bei Ihren Tests vortäuschen. Dann würden Sie diese Klasse auch testen, um zu überprüfen, ob sie wie erwartet funktioniert. Was Sie hier testen möchten, ist, dass der Fehler ausgelöst wird, nicht was passiert, wenn ein Fehler ausgelöst wird. – gontrollez

+0

Ich stimme mit @gontrollez überein, die Protokollierung sollte unbedingt aus dem Code herausgenommen und als Dienst eingeführt werden. Sie werden in der Lage sein, bessere (und einfachere) Tests zu schreiben, und Sie erhalten viel Flexibilität und können in mehr als ein Protokoll schreiben. –

Antwort

6

Es gibt ein paar verschiedene Möglichkeiten, wo error_log() Daten sendet.

Zuerst ist es genauso wie error_log(), es irgendwo anders zu senden. Ein Beispiel wäre:

error_log('This is a message from error_log()', 3, '/dev/stdout'); 

Das verwendet die destination option for error_log().

Ein anderer Ansatz besteht darin, die error_log ini setting in PHP zu überschreiben. Das würde ungefähr so ​​aussehen:

$cur_error_log = ini_get('error_log'); 
ini_set('error_log', '/dev/stdout'); 
error_log('This is a message from error_log()'); 
ini_set('error_log', $cur_error_log); 

Von den zwei Optionen bevorzuge ich im Allgemeinen die Zieloption in error_log(), wenn möglich.

Von dort könnten Sie expectOutputString() von PHPUnit verwenden, um nach den Daten zu suchen, die von error_log() gesendet wurden.

+0

Sie müssen nicht 'ini_get' verwenden, da' ini_set' den vorherigen Wert zurückgibt: http://php.net/manual/en/function.ini-set.php – DanielM

0

Sie die uopz Erweiterung von Zend verwenden können, wie diese Funktionen zu überlasten. Ich benutze sie die ganze Zeit. Hier ein Beispiel:

/** 
* Requires the following set in php.ini: 
* - zend_extension=php_uopz.dll; 
* - uopz.overloads=1 
* 
* @author Aap Noot 
*/ 
class MyClass extends PHPUnit_Framework_TestCase { 
    public static $error_log = array(); 

    /** 
    * Overload error_log function 
    * @see PHPUnit_Framework_TestCase::setUpBeforeClass() 
    */ 
    public static function setUpBeforeClass() { 
     uopz_backup ("error_log"); 
     uopz_function ("error_log", function ($message, $message_type = null, $destination = null, $extra_headers = null) { 
      // We are only interested in the message 
      MyClass::$error_log[] = $message; 
     }); 
     parent::setUpBeforeClass(); 

    /** 
    * Restore function(s) 
    * @see PHPUnit_Framework_TestCase::tearDownAfterClass() 
    */ 
    public static function tearDownAfterClass() { 
     uopz_restore ("error_log"); 
     parent::tearDownAfterClass(); 
    } 

    /** 
    * Set up per test case 
    * @see PHPUnit_Framework_TestCase::setUp() 
    */ 
    protected function setUp() { 
     parent::setUp(); 
     MyClass::$error_log = array(); 
    } 

    /** 
    * Test error log 
    * MyClass::$error_log should be an array with the error message 
    */ 
    public function testErrorLog() { 
     // Test response 
     error_log("This message will be captured"); 

     // Test error log 
     $this->assertNotEmpty(MyClass::$error_log); 
    } 
} 
Verwandte Themen