PHP code
  1. <?php
  2. /**
  3.  * Copyright (c) 2009, Laurent Laville <pear@laurent-laville.org>
  4.  *
  5.  * All rights reserved.
  6.  *
  7.  * Redistribution and use in source and binary forms, with or without
  8.  * modification, are permitted provided that the following conditions
  9.  * are met:
  10.  *
  11.  *     * Redistributions of source code must retain the above copyright
  12.  *       notice, this list of conditions and the following disclaimer.
  13.  *     * Redistributions in binary form must reproduce the above copyright
  14.  *       notice, this list of conditions and the following disclaimer in the
  15.  *       documentation and/or other materials provided with the distribution.
  16.  *     * Neither the name of the authors nor the names of its contributors
  17.  *       may be used to endorse or promote products derived from this software
  18.  *       without specific prior written permission.
  19.  *
  20.  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  21.  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  22.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  23.  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
  24.  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  25.  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  26.  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  27.  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  28.  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  29.  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  30.  * POSSIBILITY OF SUCH DAMAGE.
  31.  *
  32.  * PHP version 5
  33.  *
  34.  * @category PEAR
  35.  * @package  PEAR_TestListener
  36.  * @author   Laurent Laville <pear@laurent-laville.org>
  37.  * @license  http://www.opensource.org/licenses/bsd-license.php  BSD
  38.  * @version  CVS: $Id:$
  39.  * @link     http://pear.laurent-laville.org/pepr/PEAR_TestListener
  40.  * @since    File available since Release 0.1.0
  41.  */
  42.  
  43. require_once 'PHPUnit/Framework/TestListener.php';
  44. require_once 'Log.php';
  45. require_once 'Event/Dispatcher.php';
  46.  
  47. /**
  48.  * The base Listener for test log/progress launched through the PEAR Test Runner
  49.  *
  50.  * @category PEAR
  51.  * @package  PEAR_TestListener
  52.  * @author   Laurent Laville <pear@laurent-laville.org>
  53.  * @license  http://www.opensource.org/licenses/bsd-license.php  BSD
  54.  * @version  Release: @package_version@
  55.  * @link     http://pear.laurent-laville.org/pepr/PEAR_TestListener
  56.  * @since    Class available since Release 0.1.0
  57.  */
  58. class PEAR_TestListener implements PHPUnit_Framework_TestListener
  59. {
  60.     /**
  61.      * @var object Instance of PEAR::Log
  62.      */
  63.     protected $logger;
  64.  
  65.     /**
  66.      * @var integer test suite assertions count
  67.      */
  68.     protected $numAssertions = 0;
  69.  
  70.     /**
  71.      * PEAR_TestListener ZE2 class constructor
  72.      *
  73.      * @param object $logger     An instance of PEAR::Log_composite
  74.      * @param object $dispatcher (optional) An instance of PEAR::Event_Dispatcher
  75.      */
  76.     public function __construct(Log_composite $logger,
  77.         Event_Dispatcher $dispatcher = null
  78.     ) {
  79.         $this->logger = $logger;
  80.  
  81.         if (!isset($dispatcher)) {
  82.             $dispatcher = Event_Dispatcher::getInstance();
  83.         }
  84.         $dispatcher->addObserver(array($this, 'update'));
  85.     }
  86.  
  87.     /**
  88.      * Logs an error occurred.
  89.      *
  90.      * @param PHPUnit_Framework_Test $test Current test case
  91.      * @param Exception              $e    Exception thrown by test
  92.      * @param float                  $time Time elapsed
  93.      *
  94.      * @return void
  95.      */
  96.     public function addError(PHPUnit_Framework_Test $test,
  97.         Exception $e,
  98.         $time
  99.     ) {
  100.         $this->logger->log(
  101.             sprintf(
  102.                 "Error while running test '%s'. %s",
  103.                 $test->getName(), $e->getMessage()
  104.             ),
  105.             PEAR_LOG_ERR
  106.         );
  107.     }
  108.  
  109.     /**
  110.      * Logs a failure occurred.
  111.      *
  112.      * @param PHPUnit_Framework_Test                 $test Current test case
  113.      * @param PHPUnit_Framework_AssertionFailedError $e    Exception thrown by test
  114.      * @param float                                  $time Time elapsed
  115.      *
  116.      * @return void
  117.      */
  118.     public function addFailure(PHPUnit_Framework_Test $test,
  119.         PHPUnit_Framework_AssertionFailedError $e,
  120.         $time
  121.     ) {
  122.         $this->logger->log(
  123.             sprintf(
  124.                 "Test '%s' failed. %s",
  125.                 $test->getName(), $e->getMessage()
  126.             ),
  127.             PEAR_LOG_CRIT
  128.         );
  129.     }
  130.  
  131.     /**
  132.      * Logs an incomplete test.
  133.      *
  134.      * @param PHPUnit_Framework_Test $test Current test case
  135.      * @param Exception              $e    Exception thrown by test
  136.      * @param float                  $time Time elapsed
  137.      *
  138.      * @return void
  139.      */
  140.     public function addIncompleteTest(PHPUnit_Framework_Test $test,
  141.         Exception $e,
  142.         $time
  143.     ) {
  144.         $this->logger->log(
  145.             sprintf(
  146.                 "Test '%s' is incomplete. %s",
  147.                 $test->getName(), $e->getMessage()
  148.             ),
  149.             PEAR_LOG_WARNING
  150.         );
  151.     }
  152.  
  153.     /**
  154.      * Logs a skipped test.
  155.      *
  156.      * @param PHPUnit_Framework_Test $test Current test case
  157.      * @param Exception              $e    Exception thrown by test
  158.      * @param float                  $time Time elapsed
  159.      *
  160.      * @return void
  161.      */
  162.     public function addSkippedTest(PHPUnit_Framework_Test $test,
  163.         Exception $e,
  164.         $time
  165.     ) {
  166.         $this->logger->log(
  167.             sprintf(
  168.                 "Test '%s' has been skipped. %s",
  169.                 $test->getName(), $e->getMessage()
  170.             ),
  171.             PEAR_LOG_WARNING
  172.         );
  173.     }
  174.  
  175.     /**
  176.      * Logs a test suite started.
  177.      *
  178.      * @param PHPUnit_Framework_TestSuite $suite Test suite
  179.      *
  180.      * @return void
  181.      */
  182.     public function startTestSuite(PHPUnit_Framework_TestSuite $suite)
  183.     {
  184.         $this->logger->log(
  185.             sprintf(
  186.                 "TestSuite '%s' started.", $suite->getName()
  187.             ),
  188.             PEAR_LOG_INFO
  189.         );
  190.     }
  191.  
  192.     /**
  193.      * Logs a test suite ended.
  194.      *
  195.      * @param PHPUnit_Framework_TestSuite $suite Test suite
  196.      *
  197.      * @return void
  198.      */
  199.     public function endTestSuite(PHPUnit_Framework_TestSuite $suite)
  200.     {
  201.         $this->logger->log(
  202.             sprintf(
  203.                 "TestSuite '%s' ended.", $suite->getName()
  204.             ),
  205.             PEAR_LOG_INFO
  206.         );
  207.     }
  208.  
  209.     /**
  210.      * Logs a test started.
  211.      *
  212.      * @param PHPUnit_Framework_Test $test Test case
  213.      *
  214.      * @return void
  215.      */
  216.     public function startTest(PHPUnit_Framework_Test $test)
  217.     {
  218.         $this->logger->log(
  219.             sprintf(
  220.                 "Test '%s' started.", $test->getName()
  221.             ),
  222.             PEAR_LOG_INFO
  223.         );
  224.     }
  225.  
  226.     /**
  227.      * Logs a test ended.
  228.      *
  229.      * @param PHPUnit_Framework_Test $test Test case
  230.      * @param float                  $time Time elapsed
  231.      *
  232.      * @return void
  233.      */
  234.     public function endTest(PHPUnit_Framework_Test $test, $time)
  235.     {
  236.         if (method_exists($test, 'getNumAssertions')) {
  237.             $this->numAssertions += $test->getNumAssertions();
  238.         }
  239.  
  240.         $this->logger->log(
  241.             sprintf(
  242.                 "Test '%s' ended.", $test->getName()
  243.             ),
  244.             PEAR_LOG_INFO
  245.         );
  246.     }
  247.  
  248.     /**
  249.      * Implements the SplObserver interface
  250.      *
  251.      * Called when a subject notify us of an event.
  252.      *
  253.      * @param mixed $subject SplSubject or Event_Dispatcher object
  254.      *                       that send us notification
  255.      *
  256.      * @return void
  257.      */
  258.     public function update($subject)
  259.     {
  260.         try {
  261.             list($notifyName, $notifyInfo, $notifyObj)
  262.                 = $this->splSubjectAdapter($subject);
  263.         }
  264.         catch (InvalidArgumentException $e) {
  265.             return;
  266.         }
  267.  
  268.         switch ($notifyName) {
  269.         case 'endTestSuite':
  270.             $result   = $notifyObj;
  271.             $preamble = 'TestSuite'
  272.                       . ' was ' . ($result->wasSuccessful() ? '' : 'not ')
  273.                       . 'successful.';
  274.  
  275.             $run = sprintf(
  276.                 "%s%s%s%s%s%s.",
  277.                 $this->getCountString($result->count(), 'Test'),
  278.                 $this->getCountString($this->numAssertions, 'Assertion'),
  279.                 $this->getCountString($result->failureCount(), 'Failure'),
  280.                 $this->getCountString($result->errorCount(), 'Error'),
  281.                 $this->getCountString(
  282.                     $result->notImplementedCount(), 'Incomplete', false
  283.                 ),
  284.                 $this->getCountString($result->skippedCount(), 'Skipped', false)
  285.             );
  286.             $this->logger->log($preamble . ltrim($run, ','), PEAR_LOG_NOTICE);
  287.             break;
  288.         }
  289.     }
  290.  
  291.     /**
  292.      * Adapter to translate either a SplSubject or Event_Dispatcher instance
  293.      * into a common array data type
  294.      *
  295.      * @param mixed $subject SplSubject or Event_Dispatcher object
  296.      *                       that send us notification
  297.      *
  298.      * @return array Data hash that contains
  299.      *               first the event name, second the subject additionnal data,
  300.      *               and third instance of subject itself
  301.      * @throws InvalidArgumentException If $subject is invalid object instance
  302.      */
  303.     protected function splSubjectAdapter($subject)
  304.     {
  305.         if ($subject instanceof Event_Notification) {
  306.             $notifyName = $subject->getNotificationName();
  307.             $notifyInfo = $subject->getNotificationInfo();
  308.             $notifyObj  = $subject->getNotificationObject();
  309.  
  310.         } elseif ($subject instanceof SplSubject) {
  311.             if (method_exists($subject, 'getNotification')) {
  312.                 $event = $subject->getNotification();
  313.                 $notifyName = (isset($event['name'])) ? $event['name'] : null;
  314.                 $notifyInfo = (isset($event['info'])) ? $event['info'] : null;
  315.                 $notifyObj  = $subject;
  316.             }
  317.         }
  318.         if (!isset($notifyName) || !isset($notifyInfo)) {
  319.             throw new InvalidArgumentException(
  320.                 'No observer event name or event info data found.'
  321.             );
  322.         }
  323.         return array($notifyName, $notifyInfo, $notifyObj);
  324.     }
  325.  
  326.     /**
  327.      * Print categorize formatted result of test suite
  328.      *
  329.      * CREDITS to PHPUnit3 (PHPUnit/TextUI/ResultPrinter.php)
  330.      *
  331.      * @param int    $count  Number of result in category
  332.      * @param string $name   Name of the result category
  333.      * @param bool   $plural (optional) If string can have plural or not
  334.      *
  335.      * @return string
  336.      */
  337.     protected function getCountString($count, $name, $plural = true)
  338.     {
  339.         if ($count > 0) {
  340.             $string = sprintf(
  341.                 ', %s: %d',
  342.                 $name . ($plural ? (($count == 1) ? '' : 's') : ''),
  343.                 $count
  344.             );
  345.         } else {
  346.             $string = '';
  347.         }
  348.         return $string;
  349.     }
  350. }
  351. ?>
generated by Generic Syntax Highlighter - GeSHi