Возможно ли для PHP написать дополнительные функции PHP, такие как макрос Lisp? - PullRequest
2 голосов
/ 06 января 2012

Я пишу платформу для модульного тестирования и хочу иметь возможность динамически генерировать функцию на основе каждой функции в тестируемом веб-сервисе.Динамическая функция будет генерироваться со стандартными (правильными) значениями для каждого аргумента в веб-сервисе, и их можно будет легко заменить неправильными значениями для тестирования ошибок.аккуратно передавайте один неверный аргумент или любое количество неверных аргументов за раз, чтобы проверить все ошибки, обнаруживаемые в веб-службе.

Мой главный вопрос: возможно ли это даже с помощью php?Если это невозможно, есть ли альтернатива?

РЕДАКТИРОВАТЬ : Я не ищу юнит-тест, я пытаюсь учиться на практике.Я не ищу совета по этому примеру кода, это просто быстрый пример того, что я хотел бы сделать.Я просто хочу знать, возможно ли это.

Ответы [ 4 ]

2 голосов
/ 06 января 2012

Я бы не стал сначала это делать, поскольку в PHP нет встроенной поддержки макросов. Но, вероятно, что-то в этом направлении:

function function1($param1, $param2)
{
    return  sprintf("param1: %d, param2: '%s'\n", $param1, $param2);
}

/* Macro: basically a port of your macro as a function */

$testFunctionGenerator = function($callback, array $defVals = array())
{
    $defVals = array_values($defVals); // list, not hash
    return function() use ($callback, $defVals)
    {
        $callArgs = func_get_args();
        $expectedOutput = array_shift($callArgs);

        $callArgs += $defVals;

        return $expectedOutput == call_user_func_array($callback, $callArgs);
    };
};

/* Use */

$arrayOfDefVals = array(123, 'foo');

$function1Test = $testFunctionGenerator('function1', $arrayOfDefVals);

var_dump($function1Test("param1: 456, param2: 'foo'\n", 456)); # bool(true)

Возможно, это полезно, см. Анонимные функции & Документы , func_get_args & Документы , оператор массива объединения & Docs и call_user_func_array & Docs .

2 голосов
/ 06 января 2012

Ну, для начала, вы можете установить параметры по умолчанию в функциях:

function function1Test($expectedOutput, $testArg1=123, $testArg2='foo') {
   ...
}

Кроме того, я не совсем уверен, чего вы пытаетесь достичь с помощью этого "генератора функций" ...

0 голосов
/ 07 января 2012

Если это функция, к которой у вас есть доступ к файлу (то есть она не является частью стандартной библиотеки PHP и у вас есть права на чтение из файла), вы можете сделать что-то вроде этого:

Предположим, что мыесть такая функция, расположенная в каком-то файле.Файл должен быть включен (т. Е. Функция должна быть во внутренней таблице символов PHP):

function my_original_function($param1, $param2)
{
    echo "$param1 $param2 \n";
}

Используйте класс ReflectionFunction, чтобы получить подробную информацию об этой функции и о том, где она определена: http://us2.php.net/manual/en/class.reflectionfunction.php.

$ expression = new ReflectionFunction ('my_original_function');

Далее вы можете использовать экземпляр отражения, чтобы получить путь к этому файлу, номер первой / последней строки функции ипараметры функции:

$file_path = $reflection->getFileName();
$start_line = $reflection->getStartLine();
$end_line = $reflection->getEndLine();
$params = $reflection->getParameters();

Используя их, вы можете:

  1. прочитать функцию из файла в строку
  2. переписать первую строкучтобы изменить имя функции, используя известное имя функции в качестве ссылки
  3. переписать первую строку, чтобы изменить значения параметров по умолчанию, используя $ params в качестве ссылки
  4. записать строку измененной функции в файл
  5. включает файл
  6. Вуаля!Теперь у вас есть новая доступная функция.

В зависимости от того, что вы на самом деле пытаетесь достичь, вы также можете просто использовать ReflectionFunction :: getClosure (), чтобы получитьзакрывающая копия функции, назначьте ее любой переменной и определите параметры там.См .: http://us.php.net/manual/en/functions.anonymous.php. Или вы можете создать несколько экземпляров ReflectionFunctions и вызвать ReflectionFunction :: invoke () / invokeArgs () с нужным набором параметров.См .: http://us2.php.net/manual/en/reflectionfunction.invokeargs.php или http://us2.php.net/manual/en/reflectionfunction.invoke.php

0 голосов
/ 06 января 2012

Прочитайте о call_user_func и func_get_args

Этот пример из руководства должен привести вас на правильный путь:

<?php
call_user_func(function($arg) { print "[$arg]\n"; }, 'test'); /* As of PHP 5.3.0 */
?>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...