1<?php 2/* 3 * This file is part of PHPUnit. 4 * 5 * (c) Sebastian Bergmann <sebastian@phpunit.de> 6 * 7 * For the full copyright and license information, please view the LICENSE 8 * file that was distributed with this source code. 9 */ 10 11/** 12 * Base class for test listeners that interact with an issue tracker. 13 */ 14abstract class PHPUnit_Extensions_TicketListener implements PHPUnit_Framework_TestListener 15{ 16 /** 17 * @var array 18 */ 19 protected $ticketCounts = []; 20 21 /** 22 * @var bool 23 */ 24 protected $ran = false; 25 26 /** 27 * An error occurred. 28 * 29 * @param PHPUnit_Framework_Test $test 30 * @param Exception $e 31 * @param float $time 32 */ 33 public function addError(PHPUnit_Framework_Test $test, Exception $e, $time) 34 { 35 } 36 37 /** 38 * A failure occurred. 39 * 40 * @param PHPUnit_Framework_Test $test 41 * @param PHPUnit_Framework_AssertionFailedError $e 42 * @param float $time 43 */ 44 public function addFailure(PHPUnit_Framework_Test $test, PHPUnit_Framework_AssertionFailedError $e, $time) 45 { 46 } 47 48 /** 49 * Incomplete test. 50 * 51 * @param PHPUnit_Framework_Test $test 52 * @param Exception $e 53 * @param float $time 54 */ 55 public function addIncompleteTest(PHPUnit_Framework_Test $test, Exception $e, $time) 56 { 57 } 58 59 /** 60 * Risky test. 61 * 62 * @param PHPUnit_Framework_Test $test 63 * @param Exception $e 64 * @param float $time 65 */ 66 public function addRiskyTest(PHPUnit_Framework_Test $test, Exception $e, $time) 67 { 68 } 69 70 /** 71 * Skipped test. 72 * 73 * @param PHPUnit_Framework_Test $test 74 * @param Exception $e 75 * @param float $time 76 */ 77 public function addSkippedTest(PHPUnit_Framework_Test $test, Exception $e, $time) 78 { 79 } 80 81 /** 82 * A test suite started. 83 * 84 * @param PHPUnit_Framework_TestSuite $suite 85 */ 86 public function startTestSuite(PHPUnit_Framework_TestSuite $suite) 87 { 88 } 89 90 /** 91 * A test suite ended. 92 * 93 * @param PHPUnit_Framework_TestSuite $suite 94 */ 95 public function endTestSuite(PHPUnit_Framework_TestSuite $suite) 96 { 97 } 98 99 /** 100 * A test started. 101 * 102 * @param PHPUnit_Framework_Test $test 103 */ 104 public function startTest(PHPUnit_Framework_Test $test) 105 { 106 if (!$test instanceof PHPUnit_Framework_WarningTestCase) { 107 if ($this->ran) { 108 return; 109 } 110 111 $name = $test->getName(false); 112 $tickets = PHPUnit_Util_Test::getTickets(get_class($test), $name); 113 114 foreach ($tickets as $ticket) { 115 $this->ticketCounts[$ticket][$name] = 1; 116 } 117 118 $this->ran = true; 119 } 120 } 121 122 /** 123 * A test ended. 124 * 125 * @param PHPUnit_Framework_Test $test 126 * @param float $time 127 */ 128 public function endTest(PHPUnit_Framework_Test $test, $time) 129 { 130 if (!$test instanceof PHPUnit_Framework_WarningTestCase) { 131 if ($test->getStatus() == PHPUnit_Runner_BaseTestRunner::STATUS_PASSED) { 132 $ifStatus = ['assigned', 'new', 'reopened']; 133 $newStatus = 'closed'; 134 $message = 'Automatically closed by PHPUnit (test passed).'; 135 $resolution = 'fixed'; 136 $cumulative = true; 137 } elseif ($test->getStatus() == PHPUnit_Runner_BaseTestRunner::STATUS_FAILURE) { 138 $ifStatus = ['closed']; 139 $newStatus = 'reopened'; 140 $message = 'Automatically reopened by PHPUnit (test failed).'; 141 $resolution = ''; 142 $cumulative = false; 143 } else { 144 return; 145 } 146 147 $name = $test->getName(false); 148 $tickets = PHPUnit_Util_Test::getTickets(get_class($test), $name); 149 150 foreach ($tickets as $ticket) { 151 // Remove this test from the totals (if it passed). 152 if ($test->getStatus() == PHPUnit_Runner_BaseTestRunner::STATUS_PASSED) { 153 unset($this->ticketCounts[$ticket][$name]); 154 } 155 156 // Only close tickets if ALL referenced cases pass 157 // but reopen tickets if a single test fails. 158 if ($cumulative) { 159 // Determine number of to-pass tests: 160 if (count($this->ticketCounts[$ticket]) > 0) { 161 // There exist remaining test cases with this reference. 162 $adjustTicket = false; 163 } else { 164 // No remaining tickets, go ahead and adjust. 165 $adjustTicket = true; 166 } 167 } else { 168 $adjustTicket = true; 169 } 170 171 $ticketInfo = $this->getTicketInfo($ticket); 172 173 if ($adjustTicket && in_array($ticketInfo['status'], $ifStatus)) { 174 $this->updateTicket($ticket, $newStatus, $message, $resolution); 175 } 176 } 177 } 178 } 179 180 /** 181 * @param mixed $ticketId 182 * 183 * @return mixed 184 */ 185 abstract protected function getTicketInfo($ticketId = null); 186 187 /** 188 * @param string $ticketId 189 * @param string $newStatus 190 * @param string $message 191 * @param string $resolution 192 */ 193 abstract protected function updateTicket($ticketId, $newStatus, $message, $resolution); 194} 195