Overview

Namespaces

  • Budovy
  • Kdyby
    • BootstrapFormRenderer
      • DI
      • Latte
  • Nette
    • Application
      • Diagnostics
      • Responses
      • Routers
      • UI
    • Caching
      • Storages
    • ComponentModel
    • Database
      • Diagnostics
      • Drivers
      • Reflection
      • Table
    • DI
      • Config
        • Adapters
      • Diagnostics
      • Extensions
    • Diagnostics
    • Forms
      • Controls
      • Rendering
    • Http
      • Diagnostics
    • Iterators
    • Latte
      • Macros
    • Loaders
    • Localization
    • Mail
    • PhpGenerator
    • Reflection
    • Security
      • Diagnostics
    • Templating
    • Utils
  • NetteModule
  • Nextras
    • Datagrid
  • None
  • PHP
  • Tester
    • CodeCoverage
    • Runner
      • Output
  • Vodacek
    • Forms
      • Controls
  • WebLoader
    • Filter
    • Nette

Classes

  • CommandLine
  • Job
  • PhpExecutable
  • Runner
  • TestHandler

Interfaces

  • OutputHandler
  • Overview
  • Namespace
  • Class
  • Tree
  1: <?php
  2: 
  3: /**
  4:  * This file is part of the Nette Tester.
  5:  * Copyright (c) 2009 David Grudl (http://davidgrudl.com)
  6:  */
  7: 
  8: namespace Tester\Runner;
  9: 
 10: use Tester;
 11: 
 12: 
 13: /**
 14:  * Test runner.
 15:  *
 16:  * @author     David Grudl
 17:  */
 18: class Runner
 19: {
 20:     const
 21:         PASSED = 1,
 22:         SKIPPED = 2,
 23:         FAILED = 3;
 24: 
 25:     /** @var array  paths to test files/directories */
 26:     public $paths = array();
 27: 
 28:     /** @var int  run in parallel threads */
 29:     public $threadCount = 1;
 30: 
 31:     /** @var TestHandler */
 32:     public $testHandler;
 33: 
 34:     /** @var OutputHandler[] */
 35:     public $outputHandlers = array();
 36: 
 37:     /** @var PhpExecutable */
 38:     private $php;
 39: 
 40:     /** @var Job[] */
 41:     private $jobs;
 42: 
 43:     /** @var int */
 44:     private $jobCount;
 45: 
 46:     /** @var array */
 47:     private $results;
 48: 
 49:     /** @var bool */
 50:     private $interrupted;
 51: 
 52: 
 53:     public function __construct(PhpExecutable $php)
 54:     {
 55:         $this->php = $php;
 56:         $this->testHandler = new TestHandler($this);
 57:     }
 58: 
 59: 
 60:     /**
 61:      * Runs all tests.
 62:      * @return bool
 63:      */
 64:     public function run()
 65:     {
 66:         foreach ($this->outputHandlers as $handler) {
 67:             $handler->begin();
 68:         }
 69: 
 70:         $this->results = array(self::PASSED => 0, self::SKIPPED => 0, self::FAILED => 0);
 71:         $this->jobs = $running = array();
 72:         foreach ($this->paths as $path) {
 73:             $this->findTests($path);
 74:         }
 75:         $this->jobCount = count($this->jobs) + array_sum($this->results);
 76: 
 77:         $this->installInterruptHandler();
 78:         while (($this->jobs || $running) && !$this->isInterrupted()) {
 79:             for ($i = count($running); $this->jobs && $i < $this->threadCount; $i++) {
 80:                 $running[] = $job = array_shift($this->jobs);
 81:                 $job->run($this->threadCount <= 1 || (count($running) + count($this->jobs) <= 1));
 82:             }
 83: 
 84:             if (count($running) > 1) {
 85:                 usleep(Job::RUN_USLEEP); // stream_select() doesn't work with proc_open()
 86:             }
 87: 
 88:             foreach ($running as $key => $job) {
 89:                 if ($this->isInterrupted()) {
 90:                     break 2;
 91:                 }
 92: 
 93:                 if (!$job->isRunning()) {
 94:                     $this->testHandler->assess($job);
 95:                     unset($running[$key]);
 96:                 }
 97:             }
 98:         }
 99:         $this->removeInterruptHandler();
100: 
101:         foreach ($this->outputHandlers as $handler) {
102:             $handler->end();
103:         }
104:         return !$this->results[self::FAILED];
105:     }
106: 
107: 
108:     /**
109:      * @return void
110:      */
111:     private function findTests($path)
112:     {
113:         if (is_dir($path)) {
114:             foreach (glob("$path/*", GLOB_ONLYDIR) as $dir) {
115:                 $this->findTests($dir);
116:             }
117:             $path .= '/*.phpt';
118:         }
119:         foreach (glob($path) as $file) {
120:             if (is_file($file)) {
121:                 $this->testHandler->initiate(realpath($file));
122:             }
123:         }
124:     }
125: 
126: 
127:     /**
128:      * Appends new job to queue.
129:      * @return void
130:      */
131:     public function addJob(Job $job)
132:     {
133:         $this->jobs[] = $job;
134:     }
135: 
136: 
137:     /**
138:      * Get count of jobs.
139:      * @return int
140:      */
141:     public function getJobCount()
142:     {
143:         return $this->jobCount;
144:     }
145: 
146: 
147:     /**
148:      * Writes to output handlers.
149:      * @return void
150:      */
151:     public function writeResult($testName, $result, $message = NULL)
152:     {
153:         $this->results[$result]++;
154:         foreach ($this->outputHandlers as $handler) {
155:             $handler->result($testName, $result, $message);
156:         }
157:     }
158: 
159: 
160:     /**
161:      * @return PhpExecutable
162:      */
163:     public function getPhp()
164:     {
165:         return $this->php;
166:     }
167: 
168: 
169:     /**
170:      * @return array
171:      */
172:     public function getResults()
173:     {
174:         return $this->results;
175:     }
176: 
177: 
178:     /**
179:      * @return void
180:      */
181:     private function installInterruptHandler()
182:     {
183:         $this->interrupted = FALSE;
184: 
185:         if (extension_loaded('pcntl')) {
186:             $interrupted = & $this->interrupted;
187:             pcntl_signal(SIGINT, function() use (& $interrupted) {
188:                 pcntl_signal(SIGINT, SIG_DFL);
189:                 $interrupted = TRUE;
190:             });
191:         }
192:     }
193: 
194: 
195:     /**
196:      * @return void
197:      */
198:     private function removeInterruptHandler()
199:     {
200:         if (extension_loaded('pcntl')) {
201:             pcntl_signal(SIGINT, SIG_DFL);
202:         }
203:     }
204: 
205: 
206:     /**
207:      * @return bool
208:      */
209:     private function isInterrupted()
210:     {
211:         if (extension_loaded('pcntl')) {
212:             pcntl_signal_dispatch();
213:         }
214: 
215:         return $this->interrupted;
216:     }
217: 
218: }
219: 
API documentation generated by ApiGen 2.8.0