Функции проверки наследования классов вернул из Helpers в BasicTestCase и отрефакторил

- `isSameClass()`
- `checkImplementsInterfaces()`
- `checkUsesTraits()` + переписана под наследование
This commit is contained in:
Anthony Axenov 2021-12-06 14:15:47 +08:00
parent b451c7dc68
commit a5c88cd7d3
3 changed files with 84 additions and 85 deletions

View File

@ -52,67 +52,4 @@ final class Helpers
} }
return $result; return $result;
} }
/**
* Проверяет идентичность двух классов
*
* @param object|string $class1
* @param object|string $class2
* @return bool
*/
public static function isSameClass(object|string $class1, object|string $class2): bool
{
return (is_object($class1) ? $class1::class : $class1) === (is_object($class2) ? $class2::class : $class2);
}
/**
* Тестирует наследование класса (объекта) от указанных классов
*
* @param object|string $class Объект или имя класса для проверки
* @param string[] $parents Имена классов-родителей
* @see https://www.php.net/manual/ru/function.class-parents.php
*/
public static function checkExtendsClasses(object|string $class, array $parents): bool
{
return self::checkClassesIntersection($parents, $class, 'class_parents');
}
/**
* Тестирует имплементацию классом (объектом) указанных интерфейсов
*
* @param object|string $actual Объект или имя класса для проверки
* @param string[] $interfaces Имена классов-интерфейсов
* @see https://www.php.net/manual/ru/function.class-implements.php
*/
public static function checkImplementsInterfaces(object|string $actual, array $interfaces): bool
{
return self::checkClassesIntersection($interfaces, $actual, 'class_implements');
}
/**
* Тестирует использование классом (объектом) указанных трейтов
*
* @param object|string $class
* @param string[] $traits
* @return bool
* @see https://www.php.net/manual/ru/function.class-uses.php
*/
public static function checkUsesTraits(array $traits, object|string $class): bool
{
return self::checkClassesIntersection($traits, $class, 'class_uses');
}
/**
* Проверяет пересечение классов указанной функцией SPL
*
* @param object|string $class Класс для проверки на вхождение, или объект, класс коего нужно проверить
* @param string[] $classes Массив классов, вхождение в который нужно проверить
* @param string $function class_parents|class_implements|class_uses
*/
protected static function checkClassesIntersection(array $classes, object|string $class, string $function): bool
{
$actual_classes = is_object($class) ? $function($class) : [$class::class];
return is_array($actual_classes)
&& !empty(array_intersect($classes, $actual_classes));
}
} }

View File

@ -57,7 +57,7 @@ class KktMonitorTest extends BasicTestCase
$client = new KktMonitor(); $client = new KktMonitor();
$this->assertIsObject($client); $this->assertIsObject($client);
$this->assertIsSameClass(KktMonitor::class, $client); $this->assertIsSameClass(KktMonitor::class, $client);
$this->assertExtendsClasses($client, [AtolClient::class]); $this->assertExtendsClasses([AtolClient::class], $client);
} }
/** /**
@ -78,7 +78,7 @@ class KktMonitorTest extends BasicTestCase
$client = new KktMonitor(false, 'login', 'password', []); $client = new KktMonitor(false, 'login', 'password', []);
$this->assertIsObject($client); $this->assertIsObject($client);
$this->assertIsSameClass($client, KktMonitor::class); $this->assertIsSameClass($client, KktMonitor::class);
$this->assertExtendsClasses($client, [AtolClient::class]); $this->assertExtendsClasses([AtolClient::class], $client);
} }
/** /**

View File

@ -81,60 +81,122 @@ class BasicTestCase extends TestCase
} }
} }
//------------------------------------------------------------------------------------------------------------------
/** /**
* Тестирует идентичность двух классов * Тестирует идентичность двух классов
* *
* @param object|string $expected * @param object|string $expected Ожидаемый класс
* @param object|string $actual * @param object|string $actual Фактический класс
*/ */
public function assertIsSameClass(object|string $expected, object|string $actual): void public function assertIsSameClass(object|string $expected, object|string $actual): void
{ {
$this->assertTrue(Helpers::isSameClass($expected, $actual)); $this->assertTrue($this->checkisSameClass($expected, $actual));
}
/**
* Проверяет идентичность двух классов
*
* @param object|string $class1
* @param object|string $class2
* @return bool
*/
private function checkisSameClass(object|string $class1, object|string $class2): bool
{
return (is_object($class1) ? $class1::class : $class1)
=== (is_object($class2) ? $class2::class : $class2);
} }
/** /**
* Тестирует наследование класса (объекта) от указанных классов * Тестирует наследование класса (объекта) от указанных классов
* *
* @param object|string $class * @param array $expected Массив ожидаемых имён классов-родителей
* @param string[] $parents * @param object|string $actual Объект или имя класса для проверки
*/ */
public function assertExtendsClasses(object|string $class, array $parents): void public function assertExtendsClasses(array $expected, object|string $actual): void
{ {
$this->assertTrue(Helpers::checkExtendsClasses($class, $parents)); $this->assertTrue($this->checkExtendsClasses($expected, $actual));
}
/**
* Проверяет наследование класса (объекта) от указанных классов
*
* @param string[] $parents Имена классов-родителей
* @param object|string $class Объект или имя класса для проверки
*/
private function checkExtendsClasses(array $parents, object|string $class): bool
{
return !empty(array_intersect($parents, is_object($class) ? class_parents($class) : [$class]));
} }
/** /**
* Тестирует имплементацию классом (объектом) указанных интерфейсов * Тестирует имплементацию классом (объектом) указанных интерфейсов
* *
* @param object|string $class * @param string[] $expected Массив ожидаемых имён интерфейсов
* @param string[] $interfaces * @param object|string $actual Объект или имя класса для проверки
*/ */
public function assertImplementsInterfaces(object|string $class, array $interfaces): void public function assertImplementsInterfaces(array $expected, object|string $actual): void
{ {
$this->assertTrue(Helpers::checkImplementsInterfaces($class, $interfaces)); $this->assertTrue($this->checkImplementsInterfaces($expected, $actual));
}
/**
* Проверяет имплементацию классом (объектом) указанных интерфейсов
*
* @param string[] $interfaces Имена классов-интерфейсов
* @param object|string $class Объект или имя класса для проверки
* @see https://www.php.net/manual/ru/function.class-implements.php
*/
private function checkImplementsInterfaces(array $interfaces, object|string $class): bool
{
return !empty(array_intersect($interfaces, is_object($class) ? class_implements($class) : [$class]));
} }
/** /**
* Тестирует использование классом (объектом) указанных трейтов * Тестирует использование классом (объектом) указанных трейтов
* *
* @param object|string $class * @param string[] $expected Массив ожидаемых имён трейтов
* @param string[] $traits * @param object|string $actual Объект или имя класса для проверки
*/ */
public function assertUsesTraits(object|string $class, array $traits): void public function assertUsesTraits(array $expected, object|string $actual): void
{ {
$this->assertTrue(Helpers::checkUsesTraits($traits, $class)); $this->assertTrue($this->checkUsesTraits($expected, $actual));
}
/**
* Проверяет использование классом (объектом) указанных трейтов (исключает родителей)
*
* @param string[] $traits Массив ожидаемых имён трейтов
* @param object|string $class Объект или имя класса для проверки
* @return bool
* @see https://www.php.net/manual/ru/function.class-uses.php#110752
*/
private function checkUsesTraits(array $traits, object|string $class): bool
{
$found_traits = [];
$check_class = is_object($class) ? $class::class : $class;
do {
$found_traits = array_merge(class_uses($check_class, true), $found_traits);
} while ($check_class = get_parent_class($check_class));
foreach ($found_traits as $trait => $same) {
$found_traits = array_merge(class_uses($trait, true), $found_traits);
}
return !empty(array_intersect(array_unique($found_traits), $traits));
} }
/** /**
* Тестирует, является ли объект коллекцией * Тестирует, является ли объект коллекцией
* *
* @param mixed $expected * @param mixed $value
*/ */
public function assertIsCollection(mixed $expected): void public function assertIsCollection(mixed $value): void
{ {
$this->assertIsObject($expected); $this->assertIsObject($value);
$this->assertIsIterable($expected); $this->assertIsIterable($value);
$this->assertIsSameClass($expected, Collection::class); $this->assertTrue(
$this->checkisSameClass(Collection::class, $value) ||
$this->checkExtendsClasses([Collection::class], $value)
);
} }
//------------------------------------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------------------------------------