- PVSM.RU - https://www.pvsm.ru -

Подготовка к собеседованиям по PHP с использованием тестов (phpt) из исходников PHP

При ручной сборке PHP (в данном случае рассматриваю версию 7.0.7) необходимо запустить команду make test перед make install, которая прогоняет все тесты в папке tests [1], после чего можно из командной строки отправить результат. Если просмотреть данную папку, то в ней сразу бросаются в глаза папки с наименованием classes, func, basic и т.д… Почему это интересно?

Дело в том, что на собеседованиях часто любят задавать вопросы как касающиеся каких — то синтаксических (довольно скучных задач (кросворды), вроде ++$i/$i++ находящихся в общем выражении), так и общих, например, ООП. Популярные моменты — это наследование интерфейсов, абстрактных классов, суть которых в общем то нарушить правильный ООП или выявить на особенностях (возможностях) глубину познания кандидатом. Вот именно эти моменты окрас и проверяют тесты, и поэтому, довольно полезно на мой взгляд просмотреть бегло тесты (в тестах пишется ожидаемый результат). Для большей убедительности попробовать выполнить аналогичный код. Прогуглить и узнать почему именно так реализовано (срабатывает) в PHP, а не по другому.

Вот для примера, базовый вопрос на собеседованиях и тест из исходников.

Файл: tests/classes/abstract_by_interface_001.phpt
--TEST--
ZE2 An abstract method may not be called
--FILE--
<?php

class Root {
}

interface MyInterface
{
        function MyInterfaceFunc();
}

abstract class Derived extends Root implements MyInterface {
}

class Leaf extends Derived
{
        function MyInterfaceFunc() {}
}

var_dump(new Leaf);

class Fails extends Root implements MyInterface {
}

?>
===DONE===
--EXPECTF--
object(Leaf)#%d (0) {
}

Fatal error: Class Fails contains 1 abstract method and must therefore be declared abstract or implement the remaining methods (MyInterface::MyInterfaceFunc) in %sabstract_by_interface_001.php on line %d

Как видно из описания, класс Fails упадет в фатальную ошибку, так как наследовал интерфейс MyInterface, но не произвел определение тела функции из интерфейса MyInterfaceFunc(). См. документацию по интерфейсам [2].

Перейдем, к следующем тесту:

Файл: tests/classes/abstract_by_interface_002.phpt

В данном случае этот же интерфейс MyInterface, имеет определение сигнатуры метода, объявленного как static.

interface MyInterface
{
        static function MyInterfaceFunc();
}

....

class Fails extends Root implements MyInterface {
}

?>
===DONE===
--EXPECTF--
object(Leaf)#%d (0) {
}

Fatal error: Class Fails contains 1 abstract method and must therefore be declared abstract or implement the remaining methods (MyInterface::MyInterfaceFunc) in %sabstract_by_interface_002.php on line %d

Как видно из ожидаемой ошибки, в данном случае, метод также должен быть определен в классе, наследующий данный интерфейс.

Или вот довольно частый вопрос, о том, можно ли в обычном классе определить абстрактный метод.

Файл: tests/classes/abstract_derived.phpt
--TEST--
ZE2 A derived class with an abstract method must be abstract
Производный класс с абстрактным методом должен быть абстрактным
--SKIPIF--
<?php if (version_compare(zend_version(), '2.0.0-dev', '<')) die('skip ZendEngine 2 needed'); ?>
--FILE--
<?php

class base {
}

class derived extends base {
        abstract function show();
}

?>
===DONE===
<?php exit(0); ?>
--EXPECTF--

Fatal error: Class derived contains 1 abstract method and must therefore be declared abstract or implement the remaining methods (derived::show) in %sabstract_derived.php on line %d

Или вот один замечательный тест:

Файл: tests/classes/abstract_redeclare.phpt
<?php

class pass {
        function show() {
                echo "Call to function show()n";
        }
}

class fail extends pass {
        abstract function show();
}

echo "Donen"; // Shouldn't be displayed
?>

Метод show(), не может быть переопределен абстрактным.

Перейдем в каталог тестов func и как, пример, тест с использованием static и постфиксным инкрементом/декрементом.

Файл: tests/func/002.phpt
--TEST--
Static variables in functions
--FILE--
<?php
function blah()
{
  static $hey=0,$yo=0;

  echo "hey=".$hey++.", ",$yo--."n";
}

blah();
blah();
blah();
if (isset($hey) || isset($yo)) {
  echo "Local variables became global :(n";
}
--EXPECT--
hey=0, 0
hey=1, -1
hey=2, -2

Напоследок, чтобы не сильно Вас утомлять, приведу интересный тест, по баге 28800 [3]

--TEST--
Bug #28800 (Incorrect string to number conversion for strings starting with 'inf')
--FILE--
<?php
        $strings = array('into', 'info', 'inf', 'infinity', 'infin', 'inflammable');
        foreach ($strings as $v) {
                echo ($v+0)."n";
        }
?>
--EXPECT--

На этом все, спасибо за отнятое время.

Автор: bizzonaru

Источник [4]


Сайт-источник PVSM.RU: https://www.pvsm.ru

Путь до страницы источника: https://www.pvsm.ru/php-2/132018

Ссылки в тексте:

[1] tests: https://github.com/php/php-src/tree/master/tests

[2] интерфейсам: http://php.net/manual/ru/language.oop5.interfaces.php

[3] 28800 : https://bugs.php.net/bug.php?id=28800

[4] Источник: https://habrahabr.ru/post/303116/?utm_source=habrahabr&utm_medium=rss&utm_campaign=best