Browse Source

Started unit testing

2.1.0
Dustin Wilson 2 years ago
parent
commit
7fe6607692
  1. 3
      composer.json
  2. 1928
      composer.lock
  3. 70
      lib/Catcher.php
  4. 117
      run
  5. 24
      tests/bootstrap.php
  6. 103
      tests/cases/TestCatcher.php
  7. 22
      tests/phpunit.dist.xml

3
composer.json

@ -23,6 +23,7 @@
"ext-dom": "For HTMLHandler"
},
"require-dev": {
"mensbeam/html-dom": "^1.0"
"mensbeam/html-dom": "^1.0",
"phpunit/phpunit": "^9.5"
}
}

1928
composer.lock

File diff suppressed because it is too large

70
lib/Catcher.php

@ -8,8 +8,9 @@
declare(strict_types=1);
namespace MensBeam\Framework;
use MensBeam\Framework\Catcher\{
Handler,
PlainTextHandler,
ThrowableController,
Handler
};
@ -27,7 +28,11 @@ class Catcher {
public function __construct(Handler ...$handlers) {
$this->handlers = $handlers;
if (count($handlers) === 0) {
$handlers = [ new PlainTextHandler() ];
}
$this->pushHandler(...$handlers);
set_error_handler([ $this, 'handleError' ]);
set_exception_handler([ $this, 'handleThrowable' ]);
@ -36,6 +41,60 @@ class Catcher {
public function getHandlers(): array {
return $this->handlers;
}
public function pushHandler(Handler ...$handlers): void {
foreach ($handlers as $h) {
if (in_array($h, $this->handlers, true)) {
trigger_error("Handlers must be unique; skipping\n", \E_USER_WARNING);
continue;
}
$this->handlers[] = $h;
}
}
public function removeHandler(Handler ...$handlers): void {
foreach ($handlers as $h) {
foreach ($this->handlers as $k => $hh) {
if ($h === $hh) {
if (count($this->handlers) === 1) {
throw new \Exception("Removing handler will cause the Catcher to have zero handlers; there must be at least one\n");
}
unset($this->handlers[$k]);
$this->handlers = array_values($this->handlers);
continue 2;
}
}
}
}
public function setHandlers(Handler ...$handlers): void {
$this->handlers = [];
$this->pushHandler(...$handlers);
}
public function unshiftHandler(Handler ...$handlers): void {
$modified = false;
foreach ($handlers as $v => $h) {
if (in_array($h, $this->handlers, true)) {
trigger_error("Handlers must be unique; skipping\n", \E_USER_WARNING);
continue;
}
unset($handlers[$v]);
$modified = true;
}
if ($modified) {
$handlers = array_values($handlers);
}
$this->handlers = [ ...$handlers, ...$this->handlers ];
}
/**
* Converts regular errors into throwable Errors for easier handling; meant to be
@ -105,4 +164,11 @@ class Catcher {
}
}
}
public function __destruct() {
restore_error_handler();
restore_exception_handler();
register_shutdown_function(fn() => false);
}
}

117
run

@ -0,0 +1,117 @@
#!/usr/bin/env php
<?php
$cwd = __DIR__;
$codeDir = "$cwd/lib";
$testDir = "$cwd/tests";
function help($error = true): void {
$help = <<<USAGE
Usage:
run test [typical|quick|coverage|full] [additional_phpunit_options]
run --help
USAGE;
if ($error) {
fprintf(\STDERR, $help);
} else {
echo $help;
}
exit((int)$error);
}
function error(string $message): void {
fprintf(\STDERR, "ERROR: $message\n");
exit(1);
}
if (count($argv) === 1) {
help();
}
switch ($argv[1]) {
case 'test':
$opts = [
'--colors',
'--coverage-html='.escapeshellarg("$testDir/coverage")
];
$argv[2] = $argv[2] ?? '';
switch ($argv[2]) {
case '':
case 'typical':
$opts[] = '--exclude-group=optional';
break;
case 'quick':
$opts[] = '--exclude-group=optional,slow';
break;
case 'coverage':
$opts[] = '--exclude-group=optional,coverageOptional';
break;
case 'full':
break;
default:
help();
}
if (isset($argv[3])) {
$opts = [ ...$opts, array_slice($argv, 3) ];
}
$opts = implode(' ', $opts);
break;
case '-h':
case '--help':
help(false);
break;
default:
help();
}
$phpunitPath = escapeshellarg("$cwd/vendor/bin/phpunit");
$confPath = "$testDir/phpunit.dist.xml";
if (!file_exists($confPath)) {
$confPath = "$testDir/phpunit.xml";
if (!file_exists($confPath)) {
error('A phpunit configuration must be present at "tests/phpunit.dist.xml" or "tests/phpunit.xml"; aborting');
}
}
$confPath = escapeshellarg($confPath);
$cmd = [
escapeshellarg(\PHP_BINARY),
'-d opcache.enable_cli=0',
'-d zend.assertions=1'
];
if (!extension_loaded('xdebug')) {
if (file_exists("$extDir/xdebug.so")) {
$cmd[] = '-d extension=xdebug.so';
} else {
error('Xdebug is not installed on your system; aborting');
}
}
$cmd[] = '-d xdebug.mode=coverage,trace';
$cmd = implode(' ', $cmd);
$process = proc_open("$cmd $phpunitPath -c $confPath $opts", [
1 => ['pipe', 'w'],
2 => ['pipe', 'w']
], $pipes);
if ($process === false) {
error('Failed to execute phpunit');
}
$stderr = trim(stream_get_contents($pipes[2]));
$output = trim(stream_get_contents($pipes[1]));
fclose($pipes[1]);
fclose($pipes[2]);
proc_close($process);
echo "$output\n";
if ($stderr !== '') {
error($stderr);
}

24
tests/bootstrap.php

@ -0,0 +1,24 @@
<?php
/** @license MIT
* Copyright 2017 , Dustin Wilson, J. King et al.
* See LICENSE and AUTHORS files for details */
declare(strict_types=1);
namespace MensBeam\Framework;
ini_set('memory_limit', '-1');
ini_set('zend.assertions', '1');
ini_set('assert.exception', 'true');
error_reporting(\E_ALL);
$cwd = dirname(__DIR__);
$docRoot = "$cwd/tests/docroot";
require_once "$cwd/vendor/autoload.php";
if (function_exists('xdebug_set_filter')) {
if (defined('XDEBUG_PATH_INCLUDE')) {
xdebug_set_filter(\XDEBUG_FILTER_CODE_COVERAGE, \XDEBUG_PATH_INCLUDE, [ "$cwd/lib/" ]);
} else {
xdebug_set_filter(\XDEBUG_FILTER_CODE_COVERAGE, \XDEBUG_PATH_WHITELIST, [ "$cwd/lib/" ]);
}
}

103
tests/cases/TestCatcher.php

@ -0,0 +1,103 @@
<?php
/**
* @license MIT
* Copyright 2022 Dustin Wilson, et al.
* See LICENSE and AUTHORS files for details
*/
declare(strict_types=1);
namespace MensBeam\Framework\TestCase;
use MensBeam\Framework\Catcher;
use MensBeam\Framework\Catcher\{
PlainTextHandler,
HTMLHandler,
JSONHandler
};
class TestCatcher extends \PHPUnit\Framework\TestCase {
/**
* @covers \MensBeam\Framework\Catcher::__construct()
*
* @covers \MensBeam\Framework\Catcher::getHandlers()
* @covers \MensBeam\Framework\Catcher::pushHandler()
* @covers \MensBeam\Framework\Catcher::__destruct()
* @covers \MensBeam\Framework\Catcher\Handler::__construct()
*/
public function testMethod___construct(): void {
$c = new Catcher();
$this->assertSame('MensBeam\Framework\Catcher', $c::class);
$this->assertEquals(1, count($c->getHandlers()));
$c->__destruct();
$c = new Catcher(
new PlainTextHandler(),
new HTMLHandler(),
new JSONHandler()
);
$this->assertSame('MensBeam\Framework\Catcher', $c::class);
$this->assertEquals(3, count($c->getHandlers()));
$c->__destruct();
}
/**
* @covers \MensBeam\Framework\Catcher::pushHandler()
*
* @covers \MensBeam\Framework\Catcher::__construct()
* @covers \MensBeam\Framework\Catcher::__destruct()
* @covers \MensBeam\Framework\Catcher\Handler::__construct()
*/
public function testMethod_pushHandler__warning(): void {
set_error_handler(function($errno) {
$this->assertEquals(\E_USER_WARNING, $errno);
});
$h = new PlainTextHandler();
$c = new Catcher($h, $h);
$c->__destruct();
restore_error_handler();
}
/**
* @covers \MensBeam\Framework\Catcher::removeHandler()
*
* @covers \MensBeam\Framework\Catcher::__construct()
* @covers \MensBeam\Framework\Catcher::__destruct()
* @covers \MensBeam\Framework\Catcher\Handler::__construct()
*/
public function testMethod_removeHandler(): void {
$h = new HTMLHandler();
$c = new Catcher(
new PlainTextHandler(),
$h
);
$this->assertEquals(2, count($c->getHandlers()));
$c->removeHandler($h);
$this->assertEquals(1, count($c->getHandlers()));
$c->__destruct();
}
/**
* @covers \MensBeam\Framework\Catcher::removeHandler()
*
* @covers \MensBeam\Framework\Catcher::__construct()
* @covers \MensBeam\Framework\Catcher::__destruct()
* @covers \MensBeam\Framework\Catcher\Handler::__construct()
*/
public function testMethod_removeHandler__exception(): void {
try {
$h = [
new PlainTextHandler(),
new HTMLHandler(),
];
$c = new Catcher(...$h);
$c->removeHandler(...$h);
} catch (\Exception $e) {
$this->assertSame(\Exception::class, $e::class);
} finally {
$c->__destruct();
}
}
}

22
tests/phpunit.dist.xml

@ -0,0 +1,22 @@
<?xml version="1.0"?>
<phpunit
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/9.3/phpunit.xsd"
colors="true"
bootstrap="bootstrap.php"
convertErrorsToExceptions="false"
convertNoticesToExceptions="false"
convertWarningsToExceptions="false"
beStrictAboutTestsThatDoNotTestAnything="true"
forceCoversAnnotation="true">
<coverage processUncoveredFiles="true">
<include>
<directory suffix=".php">../lib</directory>
</include>
</coverage>
<testsuites>
<testsuite name="Main">
<file>cases/TestCatcher.php</file>
</testsuite>
</testsuites>
</phpunit>
Loading…
Cancel
Save