<?php
namespace gnomephp\testsuite;
/**
* If you want to write your own unit tests this is the class to extend.
* You can extend this class and start creating protected methods for your test cases.
* All Test classes can be routed to, this means that it's a flexible solution to test pieces
* of your code.
*
*
* @author peec
*
*/
abstract class TestController extends \gnomephp\mvc\CoreController{
/**
* Holds temporary cases per method.
* Goes empty after each method test and applies it to cases
*
* @var array
*/
protected $tempCases = array();
/**
* Cases that are implementing gnomephp\testsuite\CaseInterface
* @var array
*/
protected $cases = array();
/**
* This will go to a string or array of expected exceptions per method test.
*
* @var mixed
*/
protected $expectException = null;
/**
* Controllers that should be added to the process.
*/
protected $relativeControllers = array();
/**
* Empty setup method, can be overridden to run addTestController methods.
*/
public function setup(){
}
/**
* Adds another test controller to this instance,
* this means that one controller can test many controllers at the same time.
* @param mixed $controller Array of controller names ( fully namespaced ) or just one controller as string.
*/
public function addTestController($controller){
if (is_array($controller)){
foreach($controller as $c){
$this->relativeControllers[] = $c;
}
}else{
$this->relativeControllers[] = $controller;
}
}
/**
* Core method that runs all the tests and validates them.
*/
final public function runMethods(){
$this->setup();
$return = array(
'cases' => array(),
'failtest' => 0,
'testFinished' => 0,
'testCount' => 0,
'totalTestCount' => 0,
'testName' => get_class($this),
'exceptions' => 0
);
$errorCases = array();
foreach($this->relativeControllers as $c){
$c = new $c();
$ar = $c->runMethods();
$return['cases'] = array_merge($return['cases'], $ar['cases']);
$return['failtest'] += $ar['failtest'];
$return['testFinished'] += $ar['testFinished'];
$return['testCount'] += $ar['testCount'];
$return['totalTestCount'] += $ar['totalTestCount'];
$return['exceptions'] += $ar['exceptions'];
}
// Get methods.
$factory = new \ReflectionObject($this);
$methods = $factory->getMethods(\ReflectionMethod::IS_PROTECTED);
// Render result.
foreach($methods as $method){
$method = $method->getName();
if ($method != 'test' && $method != 'expectException' && $method != 'browser'){
try{
$this->$method();
$this->cases[$method] = $this->tempCases;
$this->tempCases = array();
}catch(\Exception $e){
if ($this->expectException !== null && (
((is_string($this->expectException) || is_object($this->expectException))&& $e instanceof $this->expectException)
||
(is_array($this->expectException) && in_array(get_class($e), $this->expectException))
)
){
$return['exceptions']++;
$return['testCount']++;
$return['testFinished']++;
}else{
$errorCases[$method][] = new TestException('Unexpected Exception', $e);
$return['failtest']++;
$return['exceptions']++;
$return['testCount']++;
}
}
}
$this->expectException = null;
}
$return['totalTestCount'] += count($methods) - 3;
foreach($this->cases as $method => $values){
$return['testCount']++;
foreach($values as $case){
if ($case->validate()){
$return['testFinished']++;
}else{
$return['failtest']++;
$errorCases[$method][] = $case;
}
}
}
$return['cases'] = array_merge($return['cases'], $errorCases);
return $return;
}
/**
* Index method to be routed too.
*/
final public function index(){
$ar = $this->runMethods();
foreach($ar as $key => $val){
$this->view->assign($key, $val);
}
$this->view->render('testsuite/index');
}
/**
* This can test a value ( variable ) against assert methods in the TestValue class.
*
* @param mixed $value The input value to test for
* @param string $name Name or alias of what we are testing.
* @return gnomephp\testsuite\TestValue
*/
protected function test($value, $name=null){
$o = new TestValue($value, $name);
$this->tempCases[] = $o;
return $o;
}
/**
* This returns a virtual browser and you can test the html output against
* the url you want to test.
*
* @param string $url The url of the page to test.
* @return gnomephp\testsuite\TestBrowser
*/
protected function browser($url){
if (!function_exists('curl_init'))die("Curl is needed for some of these unit tests. Please install the php-curl extension for PHP.");
$o = new TestBrowser($url);
$this->tempCases[] = $o;
return $o;
}
/**
* If you expect exceptions, this should be set to the exception you expect to get.
* @param mixed $exception array of exceptions or just a string/instance of the exception.
*/
protected function expectException($exception){
$this->expectException = $exception;
}
}