Tag Archives: PHP

Identifing Slow PHPUnit Tests

Note: this is for PHPUnit 3.5 or less. We’re restricted by a platform limitation from upgrading etc etc.

I wanted to find out which unit tests were taking a long time to run and to try and get our build time down a little. I believe that unit tests should not take longer then 2 seconds to run. Not the entire suite, that’s silly. Each test. Ideally, it’d be less then a second but, hey we don’t live in a perfect world.

So I implemented a Test Listener. The listener checks the timing provided by PHP Unit against constants set and can fail our CI Build if you check in a slow test. Enough rambling, here’s the code.

In your phpunit.xml add the following:

  <listeners>
    <listener class="TestTimesListener" file="./TestTimesListener.php" />
  </listeners>

Create the file TestTimesListener.php right next to it, or in the directory of your choice.


<?php
class TestTimesListener implements PHPUnit_Framework_TestListener
{
    /**
     * Anything above this threshold is deemed slow
     * @var float $seconds
     */
    const MAX_EXECUTION_TIME = 0.2;

    /**
     * Absolute max time we should allow a unit test to run.
     * @var float $seconds
     */
    const FAIL_IF_LONGER_THAN = 2.0;

    /**
     * Helper variables for assinting with naming 
     * @var string
     */
    private $_currentSuite;
    private $_fullTestName;

    public function startTest(PHPUnit_Framework_Test $test)
    {
        $this->_fullTestName = $this->_currentSuite->getName() . "::" . $test->getName();
    }

    public function endTest(PHPUnit_Framework_Test $test, $time)
    {
        if ($time > self::MAX_EXECUTION_TIME) {
            printf(
                PHP_EOL . "%s took %f seconds" . PHP_EOL, 
                $this->_fullTestName,
                $time
            );
            
            if ($time >= self::FAIL_IF_LONGER_THAN) {
                $test->fail(
                    sprintf(
                        "%s is too slow, it takes %f seconds", 
                        $this->_fullTestName,
                        $time
                    )
                );
            }
        }
    }

    public function addError(PHPUnit_Framework_Test $test, Exception $e, $time)
    {
    }
    
    public function addFailure(PHPUnit_Framework_Test $test, PHPUnit_Framework_AssertionFailedError $e, $time)
    {
    }
    
    public function addIncompleteTest(PHPUnit_Framework_Test $test, Exception $e, $time)
    {
    }
    
    public function addSkippedTest(PHPUnit_Framework_Test $test, Exception $e, $time)
    {
    }
    
    public function startTestSuite(PHPUnit_Framework_TestSuite $suite)
    {
        $this->_currentSuite = $suite;
    }

    public function endTestSuite(PHPUnit_Framework_TestSuite $suite) 
    {
    }
}

Now, set those thresholds to something nice and low and run your test suites!

Parse email addresses from text file to a csv in 4 lines

$matches = array();
$log = file_get_contents('your-text-file');
$match = preg_match_all("/[a-z0-9!_{|}~-]+(?:\.[a-z0-9?^_{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?/", $log, $matches, PREG_PATTERN_ORDER);
file_put_contents('out.csv', implode(PHP_EOL, array_unique($matches[0])));

Almost Perfect Rackspace Cloud .htaccess for PHP

Dear Reader(s?)

If you use Rackspace Cloud hosting you’ll recognise that thier PHP configuration is gash and you’ll be pulling your hair out trying to figure out why *some* ini_sets fail and sessions just don’t work at all, making you miserable. If you’re not and your hair is intact, good for you.

I learnt through trial and error so here’s what my current .htaccess file for Rackspace looks like

One thing to note is I use the Zend Framework alot, hence the write rules.

#Zend Framework Specific.

RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} -s [OR]
RewriteCond %{REQUEST_FILENAME} -l [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^.*$ - [NC,L]
RewriteRule ^.*$ index.php [NC,L]

php_value session.gc_probability 1
php_value session.gc_divisor 100
php_value session.gc_maxlifetime 3600
php_value session.save_path /mnt/stor1-wc2-dfw1/654321/12356/www.sitename.com/web/sessions

php_value max_execution_time 3600
php_value upload_max_filesize 100M
php_value post_max_size 220M
php_value memory_limit 256M
php_value magic_quotes_gpc Off

So bit sucky that you have to do that, but credit where credit is due, their live chat support is great. Instant answers to anything you can’t find in their cloud hosting wiki.

Another quality reference page to check is the .htaccess faqs page too, before you start buggin their support agents 😉