From 6bceb2b2db34d79c1add18dcd7964f90b041bfd0 Mon Sep 17 00:00:00 2001 From: logmanoriginal Date: Sun, 5 Aug 2018 00:39:53 +0200 Subject: [PATCH] [tests] Add unit test for bridge implementation Adds unit test for bridge implementations: - Custom functions must be in protected or private scope - getName() must return a valid string (non-empty) - getURI() must return a valid URI - Each bridge must define constants for NAME, URI, DESCRIPTION and MAINTAINER. CACHE_TIMEOUT and PARAMETERS are optional. The unit test is written for PHPUnit 6.x and will automatically be tested by Travis-CI for PHP 7.0 (see .travis.yml). Remarks: Unit tests for bridge data were scrapped in #378 for complexity reasons (tests would have to be maintained for each bridge). This unit test, however, is written for testing all bridges without taking specific implementation details into account. --- .travis.yml | 6 + phpunit.xml | 16 +++ tests/BridgeImplementationTest.php | 193 +++++++++++++++++++++++++++++ 3 files changed, 215 insertions(+) create mode 100644 phpunit.xml create mode 100644 tests/BridgeImplementationTest.php diff --git a/.travis.yml b/.travis.yml index f50e2b49..5c746a4d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,6 +9,9 @@ install: pear channel-update pear.php.net; pear install PHP_CodeSniffer; fi + - if [[ $TRAVIS_PHP_VERSION == "7.0" ]]; then + composer global require phpunit/phpunit ^6; + fi script: - phpenv rehash @@ -17,6 +20,9 @@ script: else phpcs . --standard=phpcs.xml --warning-severity=0 --extensions=php -p; fi + - if [[ $TRAVIS_PHP_VERSION == "7.0" ]]; then + phpunit --configuration=phpunit.xml --include-path=lib/; + fi matrix: fast_finish: true diff --git a/phpunit.xml b/phpunit.xml new file mode 100644 index 00000000..16a082de --- /dev/null +++ b/phpunit.xml @@ -0,0 +1,16 @@ + + + + + tests/BridgeImplementationTest.php + + + + diff --git a/tests/BridgeImplementationTest.php b/tests/BridgeImplementationTest.php new file mode 100644 index 00000000..aff2cb81 --- /dev/null +++ b/tests/BridgeImplementationTest.php @@ -0,0 +1,193 @@ +assertEmpty($method_names, $errmsg); + + } + + private function CheckBridgeGetNameDefaultValue($bridgeName){ + + if(in_array('BridgeAbstract', class_parents($bridgeName))) { // Is bridge + + if(!$this->isFunctionMemberOf($bridgeName, 'getName')) + return; + + $bridge = new $bridgeName(); + $abstract = new BridgeAbstractTest(); + + $message = $bridgeName . ': \'getName\' must return a valid name!'; + + $this->assertNotEmpty(trim($bridge->getName()), $message); + + } + + } + + // Checks whether the getURI function returns empty or default values + private function CheckBridgeGetURIDefaultValue($bridgeName){ + + if(in_array('BridgeAbstract', class_parents($bridgeName))) { // Is bridge + + if(!$this->isFunctionMemberOf($bridgeName, 'getURI')) + return; + + $bridge = new $bridgeName(); + $abstract = new BridgeAbstractTest(); + + $message = $bridgeName . ': \'getURI\' must return a valid URI!'; + + $this->assertNotEmpty(trim($bridge->getURI()), $message); + + } + + } + + private function CheckBridgePublicConstants($bridgeName){ + + // Assertion only works for BridgeAbstract! + if(in_array('BridgeAbstract', class_parents($bridgeName))) { + + $ref = new ReflectionClass($bridgeName); + $constants = $ref->getConstants(); + + $ref = new ReflectionClass('BridgeAbstract'); + $parent_constants = $ref->getConstants(); + + foreach($parent_constants as $key => $value) { + + $this->assertArrayHasKey($key, $constants, 'Constant ' . $key . ' missing in ' . $bridgeName); + + // Skip optional constants + if($key !== 'PARAMETERS' && $key !== 'CACHE_TIMEOUT') { + $this->assertNotEquals($value, $constants[$key], 'Constant ' . $key . ' missing in ' . $bridgeName); + } + + } + + } + + } + + private function isFunctionMemberOf($bridgeName, $functionName){ + + $bridgeReflector = new ReflectionClass($bridgeName); + $bridgeMethods = $bridgeReflector->GetMethods(); + $bridgeHasMethod = false; + + foreach($bridgeMethods as $method) { + + if($method->name === $functionName && $method->class === $bridgeReflector->name) { + return true; + } + + } + + return false; + + } + + public function testBridgeImplementation($bridgeName){ + + require_once('bridges/' . $bridgeName . '.php'); + + $this->CheckBridgePublicFunctions($bridgeName); + $this->CheckBridgePublicConstants($bridgeName); + $this->CheckBridgeGetNameDefaultValue($bridgeName); + $this->CheckBridgeGetURIDefaultValue($bridgeName); + + } + + public function count() { + return count(Bridge::listBridges()); + } + + public function run(TestResult $result = null) { + + if ($result === null) { + $result = new TestResult; + } + + foreach (Bridge::listBridges() as $bridge) { + + $bridge .= 'Bridge'; + + $result->startTest($this); + PHP_Timer::start(); + $stopTime = null; + + try { + $this->testBridgeImplementation($bridge); + } catch (AssertionFailedError $e) { + + $stopTime = PHP_Timer::stop(); + $result->addFailure($this, $e, $stopTime); + + } catch (Exception $e) { + + $stopTime = PHP_Timer::stop(); + $result->addError($this, $e, $stopTime); + + } + + if ($stopTime === null) { + $stopTime = PHP_Timer::stop(); + } + + $result->endTest($this, $stopTime); + + } + + return $result; + } +} + +class BridgeAbstractTest extends BridgeAbstract { + public function collectData(){} +}