CliClass.php
<?php
namespace Taeluf\Tester;
class Cli {
protected $testDir;
protected $config;
protected $autoload;
protected $directAutoload;
protected $testDirs = [];
protected $pwd;
/** cli args **/
protected $args = [];
public function __construct($workingDir, $cliArgs){
$this->args = $this->parseCliArgs($cliArgs);
$this->pwd = $workingDir;
$dir = $workingDir;
$bn = basename($dir);
$testDir = null;
if ($bn=='test'||$bn=='tests'){
$testDir = $dir;
//we're IN the test directory
} else if (is_dir($target=$dir.'/test/') || is_dir($target=$dir.'/tests/')){
$testDir = $target;
}
if ($testDir==null){
echo "We couldn't find your test directory. Expecting 'test' or 'tests'. This should be run from the test directory or its parent directory.";
}
$this->testDir = $testDir;
$configPathList = [
$testDir.'/tlf-test.json',
$testDir.'/config.json',
$dir.'/.config/tlf-test.json',
];
$config = $testDir.'/tlf-test.json';
$this->config = [];
foreach ($configPathList as $path){
if (!file_exists($path))continue;
$this->config = json_decode(file_get_contents($path),true);
break;
}
// $this->config = file_exists($config) ? json_decode(file_get_contents($config), true) : [];
}
protected function parseCliArgs($cliArgs){
$out = [];
foreach ($cliArgs as $index=>$arg){
if (substr($arg,0,1)=='-')$nextArgKey = substr($arg,1);
else $out[$nextArgKey][] = $arg;
}
return $out;
}
public function autoload(){
//autoload files from the root/src dir or root/code or just root/
// I'm gonna have to scan for class names
// So that minimal configuration is required. That's kinda the point.
// So I'll probably want to output a classmap file
// which... might mean integrating with my autoloader lib which isn't a full lib yet.
// or I can set a system-wide autoloader... I like that idea too
// var_dump($this->autoload);
require_once($this->autoload);
}
public function loadConfig(){
$path = dirname(__DIR__).'/user-settings/system.json';
$configs = [];
if (!file_exists($path)){
$didFinish = $this->buildConfigFromInput();
if (!$didFinish)return false;
$configs['autoload'] = $this->autoload;
file_put_contents($path, json_encode($configs));
}
$configs = json_decode(file_get_contents($path),true);
$this->autoload = $configs['autoload'];
return true;
}
public function loadProjectConfig(){
$this->testDirs = $this->config['testDirs'] ?? ['.'];
$this->directAutoload = $this->config['autoload'] ?? [];
}
public function buildConfigFromInput(){
echo "Enter absolute path to a global autoload file: ";
$line = trim(fgets(STDIN));
if (!is_file($line)){
echo "File path invalid";
return false;
}
$this->autoload = $line;
return true;
}
public function runTests(){
$this->autoload();
$parent = $this->testDir;
$testDirs = $this->testDirs;
if (($key=array_search('.',$testDirs))!==false){
$testDirs[$key] = '';
}
// print_r($testDirs);
$testDirs = array_map(
function($relDir) use ($parent){
$dir = str_replace(['///','//'],'/',$parent.'/'.$relDir);
if (substr($dir,-1)=='/')$dir = substr($dir,0,-1);
return $dir;
}, $testDirs);
foreach ($this->directAutoload as $relPath){
require_once($this->testDir.'/'.$relPath);
}
chdir($parent);
$testSet = \Taeluf\Tester\Utility::runDirectory($testDirs, $this->testDir, $this->args);
//maybe do something here with the array???
return $testSet;
}
public function cliOutput($testSet){
ob_start();
echo "\n";
$testCount = [];
$totalPass = 0;
$totalFail = 0;
$testNameToExpand = $this->args['test'][0] ?? null;
$testsToExpand = [];
foreach ($testSet as $dir=>$classes){
echo "dir $dir\n";
foreach($classes as $class=>$info){
echo "class $class\n";
if (count($info['tests'])==0)echo " No Tests";
ob_start();
foreach ($info['tests'] as $testName => $result){
echo " ";
$r = $result;
if ($r['disabled']){
echo "//";
} else if ($r['result']){
echo "+";
$totalPass++;
} else {
$totalFail++;
echo "-";
}
$testName = substr($testName,strlen('test'));
if ($testName==$testNameToExpand){
$testsToExpand[] = $result;
}
echo " $testName";
echo "\n";
}
}
}
echo "\n";
if (count($testsToExpand)>0){
echo "\n\nHighlighted Tests: \n";
foreach ($testsToExpand as $t){
$passStr = $t['error']==''? ($t['result'] ? 'pass' : 'fail') : 'error';
echo " # ".$t['method'].": $passStr\n";
$out = explode("\n", $t['output']);
$indent = " ";
$out = $indent.implode("\n$indent",$out);
echo $out."\n\n";
if ($passStr=='error'){
$error = (array)$t['error'];
// echo var_export($error, true);
$errorString = $error["\0Error\0string"] ?? $error["\0Exception\0string"];
$errorString = explode("\n", $errorString);
$errorString = $indent.implode("\n$indent", $errorString);
echo $errorString;
}
}
}
echo "Passing: $totalPass tests";
echo "\nFailing: $totalFail tests";
echo "\n";
return ob_get_clean();
}
public function htmlOutput($testSet){
ob_start();
$testCount = [];
$testDir = realpath($this->pwd);
foreach ($testSet as $dir=>$classes){
$dir = realpath($dir);
$relDir = $dir;
$prefix = substr($dir,0,strlen($testDir));
if ($prefix===$testDir)$relDir = substr($dir,strlen($testDir)+1);
$pad = " ";
echo "<h1>Dir: $relDir</h1>\n";
echo "$pad<section>";
// echo "Tests in '$dir'\n";
foreach($classes as $class=>$info){
echo "$pad$pad<h2>$class</h2>";
foreach ($info['tests'] as $testName => $result){
echo $result['html'];
// echo " ";
// $r = $result;
// if ($r['disabled'])echo "//";
// else if ($r['result'])echo "+";
// else echo "-";
// echo " $testName";
// echo "\n";
}
}
echo "$pad</section>";
}
$htmlOut = ob_get_clean();
return $htmlOut;
}
public function writeTestResults($html){
$outFile = $this->testDir.'/TestResults.html';
file_put_contents($outFile, $html);
$outFile = realpath($outFile);
echo "\nSee file://$outFile for extended output";
echo "\n\n";
}
}