此脚本可以为已有的代码快速生成PHP的单元测试代码,用于辅助测试,以减少开发量。同时,也可以使用PHPUnit官方提供的phpunit-skelgen来达到同样的效果。只是自定义的生成脚本,更多地关注了用户的需求,以及方便修改扩展自己的需求。并且,新版中可以根据注
此脚本可以为已有的代码快速生成PHP的单元测试代码,用于辅助测试,以减少开发量。同时,也可以使用PHPUnit官方提供的phpunit-skelgen来达到同样的效果。只是自定义的生成脚本,更多地关注了用户的需求,以及方便修改扩展自己的需求。并且,新版中可以根据注释@testcase来自动生成简单的测试用例!欢迎试用,谢谢!
//$ cat ./build_phpunit_test_tpl.php
#!/usr/bin/env php
<?php
/**
* 单元测试骨架代码自动生成脚本
* 主要是针对当前项目系列生成相应的单元测试代码,提高开发效率
*
* 用法:
* Usage: php ./build_phpunit_test_tpl.php <file_path> <class_name> [bootstrap] [author = dogstar]
*
* 1、针对全部public的函数进行单元测试
* 2、可根据@testcase注释自动生成测试用例
*
* 备注:另可使用phpunit-skelgen进行骨架代码生成
*
* @author: dogstar 20150108
* @version: 4.0.0
*/
if ($argc < 3) {
echo "
Usage:
php $argv[0] <file_path> <class_name> [bootstrap] [author = dogstar]
Demo:
php ./build_phpunit_test_tpl.php ./Demo.php Demo > Demo_Test.php
";
die();
}
$filePath = $argv[1];
$className = $argv[2];
$bootstrap = isset($argv[3]) ? $argv[3] : null;
$author = isset($argv[4]) ? $argv[4] : 'dogstar';
if (!empty($bootstrap)) {
require $bootstrap;
}
require $filePath;
if (!class_exists($className)) {
die("Error: cannot find class($className). \n");
}
$reflector = new ReflectionClass($className);
$methods = $reflector->getMethods(ReflectionMethod::IS_PUBLIC);
date_default_timezone_set('Asia/Shanghai');
$objName = lcfirst(str_replace('_', '', $className));
$code = "<?php
/**
* PhpUnderControl_" . str_replace('_', '', $className) . "_Test
*
* 针对 $filePath $className 类的PHPUnit单元测试
*
* @author: $author " . date('Ymd') . "
*/
";
if (file_exists(dirname(__FILE__) . '/test_env.php')) {
$code .= "require_once dirname(__FILE__) . '/test_env.php';
";
} else {
$code .= "//require_once dirname(__FILE__) . '/test_env.php';
";
}
$initWay = "new $className()";
if (method_exists($className, '__construct')) {
$constructMethod = new ReflectionMethod($className, '__construct');
if (!$constructMethod->isPublic()) {
if (is_callable(array($className, 'getInstance'))) {
$initWay = "$className::getInstance()";
} else if(is_callable(array($className, 'newInstance'))) {
$initWay = "$className::newInstance()";
} else {
$initWay = 'NULL';
}
}
}
$code .= "
if (!class_exists('$className')) {
require dirname(__FILE__) . '/$filePath';
}
class PhpUnderControl_" . str_replace('_', '', $className) . "_Test extends PHPUnit_Framework_TestCase
{
public \$$objName;
protected function setUp()
{
parent::setUp();
\$this->$objName = $initWay;
}
protected function tearDown()
{
}
";
foreach ($methods as $method) {
if($method->class != $className) continue;
$fun = $method->name;
$Fun = ucfirst($fun);
if (strlen($Fun) > 2 && substr($Fun, 0, 2) == '__') continue;
$rMethod = new ReflectionMethod($className, $method->name);
$params = $rMethod->getParameters();
$isStatic = $rMethod->isStatic();
$isConstructor = $rMethod->isConstructor();
if($isConstructor) continue;
$initParamStr = '';
$callParamStr = '';
foreach ($params as $param) {
$default = '';
$rp = new ReflectionParameter(array($className, $fun), $param->name);
if ($rp->isOptional()) {
$default = $rp->getDefaultValue();
}
if (is_string($default)) {
$default = "'$default'";
} else if (is_array($default)) {
$default = var_export($default, true);
} else if (is_bool($default)) {
$default = $default ? 'true' : 'false';
} else if ($default === null) {
$default = 'null';
} else {
$default = "''";
}
$initParamStr .= "
\$" . $param->name . " = $default;";
$callParamStr .= '$' . $param->name . ', ';
}
$callParamStr = empty($callParamStr) ? $callParamStr : substr($callParamStr, 0, -2);
/** ------------------- 根据@return对结果类型的简单断言 ------------------ **/
$returnAssert = '';
$docComment = $rMethod->getDocComment();
$docCommentArr = explode("\n", $docComment);
foreach ($docCommentArr as $comment) {
if (strpos($comment, '@return') == false) {
continue;
}
$returnCommentArr = explode(' ', strrchr($comment, '@return'));
if (count($returnCommentArr) >= 2) {
switch (strtolower($returnCommentArr[1])) {
case 'bool':
case 'boolean':
$returnAssert = '$this->assertTrue(is_bool($rs));';
break;
case 'int':
$returnAssert = '$this->assertTrue(is_int($rs));';
break;
case 'integer':
$returnAssert = '$this->assertTrue(is_integer($rs));';
break;
case 'string':
$returnAssert = '$this->assertTrue(is_string($rs));';
break;
case 'object':
$returnAssert = '$this->assertTrue(is_object($rs));';
break;
case 'array':
$returnAssert = '$this->assertTrue(is_array($rs));';
break;
case 'float':
$returnAssert = '$this->assertTrue(is_float($rs));';
break;
}
break;
}
}
/** ------------------- 基本的单元测试代码生成 ------------------ **/
$code .= "
/**
* @group test$Fun
*/
public function test$Fun()
{"
. (empty($initParamStr) ? '' : "$initParamStr\n")
. "\n "
. ($isStatic ? "\$rs = $className::$fun($callParamStr);" : "\$rs = \$this->$objName->$fun($callParamStr);")
. (empty($returnAssert) ? '' : "\n\n " . $returnAssert . "\n")
. "
}
";
/** ------------------- 根据@testcase 生成测试代码 ------------------ **/
$caseNum = 0;
foreach ($docCommentArr as $comment) {
if (strpos($comment, '@testcase') == false) {
continue;
}
$returnCommentArr = explode(' ', strrchr($comment, '@testcase'));
if (count($returnCommentArr) > 1) {
$expRs = $returnCommentArr[1];
$callParamStrInCase = isset($returnCommentArr[2]) ? $returnCommentArr[2] : '';
$code .= "
/**
* @group test$Fun
*/
public function test{$Fun}Case{$caseNum}()
{"
. "\n "
. ($isStatic ? "\$rs = $className::$fun($callParamStrInCase);" : "\$rs = \$this->$objName->$fun($callParamStrInCase);")
. "\n\n \$this->assertEquals({$expRs}, \$rs);"
. "
}
";
$caseNum ++;
}
}
}
$code .= "
}";
echo $code;
echo "\n";
PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号