2014-02-14 3 views
7

Есть ли способ запустить тест на выходе, созданный при вызове 'error_log («Сообщение») при выполнении модульных тестов с помощью phpunit?Есть ли способ «ожидать» вывода для error_log в тестах PHPUnit?

Пример кода, один из моих функций проверяет кредитную карту с помощью алгоритма Лун:

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

$ checkLuhn является булевой прошло, чтобы сказать ему, делать ли чек, то _luhn_check() возвращает истину, если пробегает $ cardNumber. Проблема в том, что у меня есть более одного теста в этой функции, который может возвращать false. Я могу использовать assertEquals для возвращаемого значения, но также хочу проверить, почему была выбрана ошибка.

Можете ли вы переопределить error_log или иначе захватить вывод syslog в модульном тесте?

+1

Есть ли в вашем '$ this -> _ luhn_check ($ cardNumber) исключение? Если это так, вы можете получить это исключение и зарегистрировать его в своем тесте. – Jhn

+2

Я думаю, что у вас отсутствует некоторый уровень абстракции при обнаружении/регистрации ошибок. Если вы используете класс для регистрации всех ошибок, вам просто нужно высмеять этот класс в своих тестах. Затем вы также проверите этот класс, чтобы проверить, что работает как ожидалось. Что вы хотите проверить здесь, так это то, что ошибка запускается, а не то, что происходит при возникновении ошибки. – gontrollez

+0

Я согласен с @gontrollez, регистрация должна обязательно быть абстрагирована из кода и представлена ​​как услуга. Вы сможете писать лучшие (и более простые) тесты, плюс вы получите большую гибкость и сможете писать более одного журнала. –

ответ

6

Существует несколько различных способов направления туда, где error_log() отправляет данные.

Прежде всего, как error_log(), чтобы отправить его где-нибудь еще. Примером может служить:

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

Используется destination option for error_log().

Другим подходом является переопределение error_log ini setting in PHP. Это будет выглядеть примерно так:

$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); 

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

Оттуда вы можете использовать expectOutputString() из PHPUnit, чтобы искать данные, отправленные с error_log().

+0

Вам не нужно использовать 'ini_get', поскольку' ini_set' возвращает предыдущее значение: http://php.net/manual/en/function.in-set.php – DanielM

0

Я не мог заставить это работать с error_log, но смог проверить ошибку с помощью trigger_error. Попробуйте использовать аннотации.

* @expectedException PHPUnit_Framework_Exception 
* @expectedExceptionMessageRegExp /failed/ 

https://phpunit.de/manual/current/en/appendixes.annotations.html#appendixes.annotations.expectedException

Смотрите также:

How to execute code after trigger_error(..., E_USER_WARNING) in unit test (PHPUnit)?

0

Вы можете использовать расширение uopz от Zend перегружать функции, как эти. Я использую их все время. Вот пример:

/** 
* 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); 
    } 
} 
Смежные вопросы