automated-testssymfony1lime-unittest

Test that each page doesn't exceed allowed SQL count in Symfony?


I wish I could have an isSQLCountLessThan() function or something.

$browser = new sfTestFunctional(new sfBrowser());
$browser
  ->get('/some/page')
  ->with('response')->begin()
    ->isStatusCode(200)
    // ...
    ->isSQLCountLessThan(20) // imagine how cool :)
  ->end();

Is there a way to have such?


Solution

  • I once created tester for this purpose. It's based on how it's done in web debug toolbar (sfWebDebugPanelDoctrine class).

    I extended sfTesterDoctrine so it behaves the same. Only assertion method is added to check query count.

    You could also overwrite debug() method to show query statistics.

    <?php
    /*
     * (c) 2010 Jakub Zalas
     *
     * For the full copyright and license information, please view the LICENSE
     * file that was distributed with this source code.
     */
    
    /**
     * @package     zTestPlugin
     * @subpackage  test
     * @author      Jakub Zalas <jakub@zalas.pl>
     */
    class zTesterDoctrine extends sfTesterDoctrine
    {
      /**
       * @param integer $limit 
       * @return sfTestFunctionalBase|sfTester
       */
      public function assertSqlCountLessThan($limit)
      {
        $queryCount = $this->countDoctrineEvents();
    
        $this->tester->cmp_ok($queryCount, '<', (int) $limit, sprintf('There are less than "%d" SQL queries performed', $limit));
    
        return $this->getObjectToReturn();
      }
    
      /**
       * @return integer
       */
      protected function countDoctrineEvents()
      {
        return count($this->getDoctrineEvents());
      }
    
      /**
       * @return array
       */
      protected function getDoctrineEvents()
      {
        if (!$databaseManager = $this->browser->getContext()->getDatabaseManager())
        {
          throw new LogicConnection('The current context does not include a database manager.');
        }
    
        $events = array();
        foreach ($databaseManager->getNames() as $name)
        {
          $database = $databaseManager->getDatabase($name);
          if ($database instanceof sfDoctrineDatabase && $profiler = $database->getProfiler())
          {
            foreach ($profiler->getQueryExecutionEvents() as $event)
            {
              $events[$event->getSequence()] = $event;
            }
          }
        }
    
        ksort($events);
    
        return $events;
      }
    }
    

    Example usage:

    $browser = new sfTestFunctional(new sfBrowser());
    $browser->setTester('doctrine', 'zTesterDoctrine');
    
    $browser
      ->get('/some/page')
      ->with('response')->begin()
        ->isStatusCode(200)
      ->end()
      ->with('doctrine')->begin()
        ->assertSqlCountLessThan(20) // imagine how cool :)
      ->end()
    ->end();