Access log output from unit tests

You are viewing revision #3 of this wiki article.
This version may not be up to date with the latest version.
You may want to view the differences to the latest version.

next (#4) »

  1. What is this good for?
  2. What you need
  3. How to use from a unit test

What is this good for?

Say, you want to write a test for a component which provides a caching feature. How would you know, that some method of your component returns a cached result? With the solution described here you can inspect all log outputs. So you could search the logs for accesses to the DB to really make sure, that the result was served from cache.

What you need

First create a simple log router class. All it does is to keep the log messages in memory and makes them available in a static variable. You could put this class into the components/ folder of your application:

<?php
class DebugLogRoute extends CLogRoute
{
    /**
     * @var array list of messages in this format:
     * array(
     *   [0] => message (string)
     *   [1] => level (string)
     *   [2] => category (string)
     *   [3] => timestamp (float, obtained by microtime(true)
     *  )
     */
    public static $messages=array();

    protected function processLogs($logs)
    {
        foreach($logs as $log)
            self::$messages[]=$log;
    }

    /**
     * Reset collected messages
     */
    public static function flushMessages()
    {
        self::$messages=array();
    }

    /**
     * @param string $pattern regex pattern to search for
     * @param mixed $l optional level to search for
     * @param mixed $c optional category to search for
     * @return bool wether message with given pattern, level and category was found
     */
    public static function hasMessage($pattern, $l=null, $c=null)
    {
        foreach(self::$messages as $m)
            if(preg_match($pattern, $m[0]) && ($l===null || $m[1]===$l) && ($c===null || $m[2]===$c))
                return true;

        return false;
    }
}

Add the above class to your test configuration in config/test.php:

<?php
'components'=>array(
    'log'=>array(
        'class'=>'CLogRouter',
        'routes'=>array(
            array('class'=>'DebugLogRoute')
        ),
    ),
    ...

How to use from a unit test

Now inside a unit test you can access the log messages like this:

<?php
public function testSomething()
{
    $logger = Yii::getLogger();

    // Flush all messages so far and reset debug log route
    $logger->flush(true);
    DebugLogRoute::flushMessages();

    // ... do tests and add log messages here ...

    $logger->flush(true);
    $logs=DebugLogRoute::$messages;

    // Inspect logs, for example:
    $this->assertTrue(
        DebugLogRoute::hasMessage('Serving .* from cache', 
        'trace',
        'system.caching.CApcCache'
    );

    DebugLogRoute::flushMessages();

    // ... more tests ...

    $logger->flush(true);
    $logs=DebugLogRoute::$messages;

    // ... inspect $logs ...
}
3 0
2 followers
Viewed: 15 325 times
Version: Unknown (update)
Category: Tips
Written by: Mike
Last updated by: Mike
Created on: Jun 14, 2012
Last updated: 11 years ago
Update Article

Revisions

View all history

Related Articles