This commit is contained in:
tmont 2009-06-22 06:13:44 +00:00
parent 06aaa82a09
commit 5ca59db858
7 changed files with 519 additions and 13 deletions

View File

@ -3,19 +3,17 @@
/**
* Autoloader
*
* @package Library
* @subpackage Utilities
* @version 1.0
* @since 1.0
* @package TUnit
* @version 1.0
* @since 1.0
*/
/**
* Bootstraps each NowhereConcave package via autoload
*
* @package Library
* @subpackage Utilities
* @version 1.0
* @since 1.0
* @package TUnit
* @version 1.0
* @since 1.0
*/
final class Autoloader {

View File

@ -1,11 +1,46 @@
<?php
/**
* PHP file iterators
*
* @package TUnit
* @author Tommy Montgomery
* @version 1.0
* @since 1.0
*/
/**
* Class for recursively iterating over PHP files
*
* @package TUnit
* @author Tommy Montgomery
* @version 1.0
* @since 1.0
*/
class RecursivePhpFileIterator extends RecursiveFilterIterator {
/**
* Constructor
*
* @author Tommy Montgomery
* @version 1.0
* @since 1.0
*
* @param mixed $dir
*/
public function __construct($dir) {
parent::__construct(new RecursiveDirectoryIterator($dir));
}
/**
* Defines acceptance criteria for iteration
*
* @author Tommy Montgomery
* @version 1.0
* @since 1.0
*
* @return bool
*/
public function accept() {
return
!$this->getInnerIterator()->isDot() &&
@ -15,12 +50,38 @@
}
/**
* Iterates over PHP files
*
* @package TUnit
* @author Tommy Montgomery
* @version 1.0
* @since 1.0
*/
class PhpFileIterator extends FilterIterator {
/**
* Constructor
*
* @author Tommy Montgomery
* @version 1.0
* @since 1.0
*
* @param string $dir
*/
public function __construct($dir) {
parent::__construct(new DirectoryIterator($dir));
}
/**
* Defines acceptance criteria for iteration
*
* @author Tommy Montgomery
* @version 1.0
* @since 1.0
*
* @return bool
*/
public function accept() {
return
!$this->getInnerIterator()->isDot() &&

View File

@ -1,11 +1,46 @@
<?php
/**
* RecursiveTestIterator
*
* @package TUnit
* @author Tommy Montgomery
* @version 1.0
* @since 1.0
*/
/**
* Class for recursively iterating over test results
*
* @package TUnit
* @author Tommy Montgomery
* @version 1.0
* @since 1.0
*/
class RecursiveTestIterator extends ArrayIterator implements RecursiveIterator {
/**
* Gets the children of the current iterator
*
* @author Tommy Montgomery
* @version 1.0
* @since 1.0
*
* @return self
*/
public function getChildren() {
return new self($this->current()->getTestResults());
}
/**
* Gets whether the current iterator has any children
*
* @author Tommy Montgomery
* @version 1.0
* @since 1.0
*
* @return mixed
*/
public function hasChildren() {
return $this->current() instanceof CombinedTestResult;
}

View File

@ -1,7 +1,37 @@
<?php
/**
* TestAccumulator
*
* @package TUnit
* @author Tommy Montgomery
* @version 1.0
* @since 1.0
*/
/**
* Accumulates test
*
* @package TUnit
* @author Tommy Montgomery
* @version 1.0
* @since 1.0
*/
class TestAccumulator {
/**
* Gets all tests in the specified paths
*
* @author Tommy Montgomery
* @version 1.0
* @since 1.0
* @uses getTestsFromDir()
* @uses getTestsFromFile()
*
* @param array $paths
* @param bool $recursive
* @return array An array of {@link Testable}s
*/
public static function getTests(array $paths, $recursive = true) {
$tests = array();
@ -17,6 +47,18 @@
return $tests;
}
/**
* Gets all tests in the specified directory
*
* @author Tommy Montgomery
* @version 1.0
* @since 1.0
* @uses getTestsFromFile()
*
* @param mixed $dir
* @param bool $recursive
* @return array
*/
public static function getTestsFromDir($dir, $recursive = true) {
$iterator = ($recursive) ? new RecursivePhpFileIterator($dir) : new PhpFileIterator($dir);
@ -31,6 +73,16 @@
return $tests;
}
/**
* Gets all tests from the specified file
*
* @author Tommy Montgomery
* @version 1.0
* @since 1.0
*
* @param string $file
* @return array
*/
public static function getTestsFromFile($file) {
$tests = array();

View File

@ -1,9 +1,44 @@
<?php
/**
* Util
*
* @package TUnit
* @author Tommy Montgomery
* @version 1.0
* @since 1.0
*/
/**
* Utilities
*
* @package TUnit
* @author Tommy Montgomery
* @version 1.0
* @since 1.0
*/
class Util {
/**
* Constructor
*
* @author Tommy Montgomery
* @version 1.0
* @since 1.0
* @ignore
*/
private function __construct() {}
/**
* Gets a human-readable version of an object
*
* @author Tommy Montgomery
* @version 1.0
* @since 1.0
*
* @param mixed $var
* @return string
*/
public static function export($var) {
switch (strtolower(gettype($var))) {
case 'object':
@ -26,6 +61,16 @@
}
}
/**
* Builds a parameter definition for a method
*
* @author Tommy Montgomery
* @version 1.0
* @since 1.0
*
* @param ReflectionMethod $method
* @return string
*/
public static function buildParameterDefinition(ReflectionMethod $method) {
$paramList = '';
foreach ($method->getParameters() as $i => $param) {
@ -56,6 +101,17 @@
return rtrim($paramList, ', ');
}
/**
* Repairs a parameter name from ReflectionParameter->getName()
*
* @author Tommy Montgomery
* @version 1.0
* @since 1.0
*
* @param string $name
* @param int $position
* @return string
*/
private static function repairParameterName($name, $position) {
if (empty($name)) {
$name = 'param' . $position;
@ -64,6 +120,17 @@
return $name;
}
/**
* Builds a parameter list suitable for eval()
*
* @author Tommy Montgomery
* @version 1.0
* @since 1.0
* @uses repairParameterName()
*
* @param ReflectionMethod $method
* @return string
*/
public static function buildParameterNameList(ReflectionMethod $method) {
$list = '';
foreach ($method->getParameters() as $param) {
@ -73,6 +140,16 @@
return rtrim($list, ', ');
}
/**
* Flattens a multi-dimensional array into one dimension
*
* @author Tommy Montgomery
* @version 1.0
* @since 1.0
*
* @param mixed $arr
* @return array
*/
public static function arrayFlatten($arr) {
$flattened = array();
if (is_array($arr)) {
@ -86,6 +163,17 @@
return $flattened;
}
/**
* DGets the number of all test suites, cases and methods
*
* @author Tommy Montgomery
* @version 1.0
* @since 1.0
* @uses mergeTestCount()
*
* @param array $tests
* @return array An array with keys "suite", "case" and "method"
*/
public static function countTests(array $tests) {
$counts = array(
'suite' => 0,
@ -108,6 +196,17 @@
return $counts;
}
/**
* Used by countTests()
*
* @author Tommy Montgomery
* @version 1.0
* @since 1.0
*
* @param array $arr1
* @param array $arr2
* @return array
*/
private static function mergeTestCount(array $arr1, array $arr2) {
$arr1['suite'] += $arr2['suite'];
$arr1['case'] += $arr2['case'];
@ -115,6 +214,19 @@
return $arr1;
}
/**
* Gets a method closure
*
* @author Tommy Montgomery
* @version 1.0
* @since 1.0
* @link http://php.net/manual/en/language.oop5.reflection.php#90964
*
* @param object $object
* @param string $method
* @throws InvalidArgumentException
* @return lambda
*/
public static function getClosure($object, $method) {
if (!is_object($object)) {
throw new InvalidArgumentException('1st argument must be an object');

View File

@ -1,7 +1,31 @@
<?php
/**
* Cli, Usage, CliSwitch, CliSwitchCollection
*
* @package TUnit
* @author Tommy Montgomery
* @version 1.0
* @since 1.0
*/
/**
* Cli helper
*
* @package TUnit
* @author Tommy Montgomery
* @version 1.0
* @since 1.0
*/
class Cli {
/**
* Constructor
*
* @author Tommy Montgomery
* @version 1.0
* @since 1.0
*/
private function __construct() {}
/**
@ -44,31 +68,106 @@
}
class CliSwitch {
/**
* Long name of the switch
*
* @var string
*/
public $longName;
/**
* Short name of the switch
*
* @var string
*/
public $shortName;
/**
* Shether this switch is required or optional
*
* @var bool
*/
public $required;
/**
* The value of the switch
*
* @var string
*/
public $value;
/**
* Description of the switch
*
* @var mixed
*/
public $description;
/**
* Constructor
*
* @author Tommy Montgomery
* @version 1.0
* @since 1.0
*
* @param string $longName
* @param string $shortName
* @param bool $required
* @param string $value
* @param string $description
*/
public function __construct($longName, $shortName = '', $required = true, $value = null, $description = '') {
$this->longName = $longName;
$this->shortName = $shortName;
$this->required = $required;
$this->value = $value;
$this->longName = $longName;
$this->shortName = $shortName;
$this->required = $required;
$this->value = $value;
$this->description = $description;
}
}
/**
* Represents a collection of {@link CliSwitch}es
*
* @package TUnit
* @author Tommy Montgomery
* @version 1.0
* @since 1.0
*/
class CliSwitchCollection implements IteratorAggregate {
/**
* @var array
*/
private $switches;
/**
* @var CliSwitch
*/
private $switchArg;
/**
* Constructor
*
* @author Tommy Montgomery
* @version 1.0
* @since 1.0
*/
public function __construct() {
$this->switches = array();
$this->switches = array();
$this->switchArg = null;
}
/**
* Adds a switch to the collection
*
* @author Tommy Montgomery
* @version 1.0
* @since 1.0
*
* @param CliSwitch $switch
* @return CliSwitchCollection
*/
public function addSwitch(CliSwitch $switch) {
if ($switch->longName === null) {
$this->switchArg = $switch;
@ -79,6 +178,16 @@
return $this;
}
/**
* Gets a switch by its short or long name
*
* @author Tommy Montgomery
* @version 1.0
* @since 1.0
*
* @param string $longOrShortName
* @return CliSwitch|null
*/
public function getSwitch($longOrShortName) {
foreach ($this->switches as $switch) {
if ($switch->longName == $longOrShortName || $switch->shortName == $longOrShortName) {
@ -89,6 +198,15 @@
return null;
}
/**
* Segregates the switches into required and optional
*
* @author Tommy Montgomery
* @version 1.0
* @since 1.0
*
* @return array Array with keys "required" and "optional"
*/
public function segregateSwitches() {
$switches = array(
'required' => array(),
@ -105,27 +223,102 @@
return $switches;
}
/**
* Gets the switch representing the arguments
*
* @author Tommy Montgomery
* @version 1.0
* @since 1.0
*
* @return CliSwitch
*/
public function getSwitchArg() {
return $this->switchArg;
}
/**
* Gets an iterator
*
* @author Tommy Montgomery
* @version 1.0
* @since 1.0
*
* @return ArrayIterator
*/
public function getIterator() {
return new ArrayIterator($this->switches);
}
}
/**
* Helpful class for printing usage
*
* @package TUnit
* @author Tommy Montgomery
* @version 1.0
* @since 1.0
*/
class Usage {
/**
* @var array
*/
private $switches;
/**
* Name of the program
*
* @var string
*/
private $name;
/**
* Name of the script
*
* @var string
*/
private $script;
/**
* Description of the program
*
* @var string
*/
private $description;
/**
* Copyright information
*
* @var string
*/
private $copyright;
/**
* @var int
*/
private $maxSwitchLength;
/**
* Max line length
*
* @var int
*/
const LINE_LENGTH = 80;
/**
* Constructor
*
* @author Tommy Montgomery
* @version 1.0
* @since 1.0
*
* @param string $name
* @param string $script
* @param string $description
* @param string $author
* @param string $date
*/
public function __construct($name, $script, $description, $author = null, $date = null) {
$this->switches = array(array(), array());
$this->maxSwitchLength = 0;
@ -138,6 +331,18 @@
: (($author !== null) ? "by $author" : '');
}
/**
* Magic function __get
*
* @author Tommy Montgomery
* @version 1.0
* @since 1.0
*
* @param mixed $key
* @throws InvalidArgumentException
* @return mixed
* @ignore
*/
public function __get($key) {
if ($key === 'switches') {
return $this->switches;
@ -146,6 +351,16 @@
throw new InvalidArgumentException('Invalid property');
}
/**
* Sets the switch collection
*
* @author Tommy Montgomery
* @version 1.0
* @since 1.0
* @uses CliSwitchCollection::getIterator()
*
* @param CliSwitchCollection $switches
*/
public function setSwitches(CliSwitchCollection $switches) {
$this->switches = $switches;
@ -165,6 +380,16 @@
}
}
/**
* Gets a string representation of this object
*
* @author Tommy Montgomery
* @version 1.0
* @since 1.0
* @uses CliSwitchCollection::segregateSwitches()
*
* @return string
*/
public function __toString() {
$this->maxSwitchLength += 2;
$usage = $this->name . "\n";

View File

@ -1,8 +1,31 @@
<?php
/**
* Entry point for console test runner
*
* @package TUnit
* @author Tommy Montgomery
* @version 1.0
* @since 1.0
*/
/**
* @see Cli
*/
require_once 'cli.php';
/**
* Bootstraps TUnit
*/
require_once dirname(dirname(__FILE__)) . '/bootstrap.php';
/**
* Prints usage
*
* @author Tommy Montgomery
* @version 1.0
* @since 1.0
*/
function usage() {
$usage = new Usage(
Product::NAME . ' ' . Product::VERSION . ' (' . Product::DATE . ')',