php自动生成phpunit,[PHPUnit]自动生成PHPUnit测试骨架脚本

场景

在编写PHPUnit单元测试代码时,其实很多都是对各个类的各个外部调用的函数进行测试验证,检测代码覆盖率,验证预期效果。为避免增加开发量,可以使用PHPUnit提供的phpunit-skelgen来生成测试骨架。只是一开始我不知道有这个脚本,就自己写了一个,大大地提高了开发效率,也不用为另外投入时间去编写测试代码而烦心。并且发现自定义的脚本比phpunit-skelgen更具人性化。所以在这里分享一下。

一个待测试的示例类

假如我们现在有一个简单的业务类,实现了加运算,为了验证其功能,下面将会就两种生成测试代码的方式进行说明。

1

2

3

4

5

6

7

8

9<?php

class Demo

{

public function inc($left,$right)

{

return $left +$right;

}

}

用phpunit-skelgen生成测试骨架

在安装了phpunit-skelgen后,可以使用以下命令来生成测试骨架。

1phpunit-skelgen --test -- Demo ./Demo.php

生成后,使用:

1vim ./DemoTest.php

可查看到生成的测试代码如下:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40<?php

/**

* Generated by PHPUnit_SkeletonGenerator 1.2.1 on 2014-06-30 at 15:53:01.

*/

class DemoTestextends PHPUnit_Framework_TestCase

{

/**

* @var Demo

*/

protected $object;

/**

* Sets up the fixture, for example, opens a network connection.

* This method is called before a test is executed.

*/

protected function setUp()

{

$this->object =new Demo;

}

/**

* Tears down the fixture, for example, closes a network connection.

* This method is called after a test is executed.

*/

protected function tearDown()

{

}

/**

* @covers Demo::inc

* @todo   Implement testInc().

*/

public function testInc()

{

// Remove the following lines when you implement this test.

$this->markTestIncomplete(

'This test has not been implemented yet.'

);

}

}

试运行测试一下:

1

2

3

4[test ~/tests]$phpunit ./DemoTest.php

PHPUnit 3.7.29 by Sebastian Bergmann.

PHP Fatal error:  Class'Demo' not foundin ~/tests/DemoTest.php on line 18

可以看到没有将需要的测试类包括进来。当然还有其他一些需要手工改动的地方。

自定义的测试代码生成脚本

现在改用自定义的脚本 来生成,虽然也有需要手工改动的地方,但已经尽量将需要改动的代码最小化,让测试人员(很可能是开发人员自己)更关注业务的测试。

先看一下Usage.

1

2[test ~/tests]$php ./build_phpunit_test_tpl.php

Usage: php ./build_phpunit_test_tpl.php   [bootstrap] [author = dogstar]

然后可以使用:

1php ./build_phpunit_test_tpl.php ./Demo.php Demo

来预览看一下将要生成的测试代码,如果没有问题可以使用:

1php ./build_phpunit_test_tpl.php ./Demo.php Demo > ./Demo_Test.php

将生成的测试代码保存起来。注意:这里使用的是“_Test.php”后缀,以便和官方的区分。看下生成的代码:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54<?php

/**

* PhpUnderControl_AppAds_Test

*

* 针对 ./Demo.php Demo 类的PHPUnit单元测试

*

* @author: dogstar 20140630

*/

if (!class_exists('Demo')) {

require dirname(__FILE__) .'/' .'./Demo.php';

}

class PhpUnderControl_Demo_Testextends PHPUnit_Framework_TestCase

{

public $demo;

protected function setUp()

{

parent::setUp();

$this->demo =new Demo();

}

protected function tearDown()

{

}

/**

* @group returnFormat

*/

public function testIncReturnFormat()

{

$left ='';

$right ='';

$rs =$this->demo->inc($left,$right);

}

/**

* @depends testIncReturnFormat

* @group businessData

*/

public function testIncBusinessData()

{

$left ='';

$right ='';

$rs =$this->demo->inc($left,$right);

}

}

随后,试运行一下:

1

2

3

4

5

6

7

8[test ~/tests]$phpunit ./Demo_Test.php

PHPUnit 3.7.29 by Sebastian Bergmann.

..

Time: 1 ms, Memory: 2.50Mb

OK (2 tests, 0 assertions)

测试通过了!!!

起码,我觉得生成的代码在大多数默认情况下是正常通过的话,可以给开发人员带上心理上的喜悦,从而很容易接受并乐意去进行下一步的测试用例完善。

现在,开发人员只须稍微改动测试代码就可以实现对业务的验证。如下示例:

1

2

3

4

5

6

7

8

9public function testIncBusinessData()

{

$left ='1';

$right ='8';

$rs =$this->demo->inc($left,$right);

$this->assertEquals(9,$rs);

}

然后再运行,依然通过。

脚本源代码

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132<?php

/**

* 单元测试骨架代码自动生成脚本

* 主要是针对当前项目系列生成相应的单元测试代码,提高开发效率

*

* 用法:

* Usage: php ./build_phpunit_test_tpl.php   [bootstrap] [author = dogstar]

*

* 1、针对全部public的函数进行单元测试

* 2、各个函数对应返回格式测试与业务数据测试

* 3、源文件加载(在没有自动加载的情况下)

*

* 备注:另可使用phpunit-skelgen进行骨架代码生成

*

* @author: dogstar 20140630

* @version: 2.0.0

*/

if ($argc 

die("Usage: php $argv[0]   [bootstrap] [author = dogstar]\n");

}

$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_AppAds_Test

*

* 针对 $filePath $className 类的PHPUnit单元测试

*

* @author: $author " . date('Ymd') . "

*/

";

if (file_exists(dirname(__FILE__) .'/test_env.php')) {

$code .= "require_once dirname(__FILE__) .'/test_env.php';

";

}

$code .= "

if (!class_exists('$className')) {

require dirname(__FILE__) .'/' .'$filePath';

}

class PhpUnderControl_" . str_replace('_', '', $className) . "_Testextends PHPUnit_Framework_TestCase

{

public \$$objName;

protected function setUp()

{

parent::setUp();

\$this->$objName =new $className();

}

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) {

$initParamStr .= "

\$" . $param->name . " ='';";

$callParamStr .='$' .$param->name .', ';

}

$callParamStr =empty($callParamStr) ?$callParamStr :substr($callParamStr, 0, -2);

$code .= "

/**

* @group returnFormat

*/

public function test$Fun" . "ReturnFormat()

{" . (empty($initParamStr) ? '' : "$initParamStr\n") . '

' . ($isStatic "\$rs = $className::$fun($callParamStr);":"\$rs = \$this->$objName->$fun($callParamStr);") . "

}

";

$code .= "

/**

* @depends test$Fun" . "ReturnFormat

* @group businessData

*/

public function test$Fun" . "BusinessData()

{" . (empty($initParamStr) ? '' : "$initParamStr\n") . '

' . ($isStatic "\$rs = $className::$fun($callParamStr);":"\$rs = \$this->$objName->$fun($callParamStr);") . "

}

";

}

$code .= "

}";

echo $code;

echo "\n";

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值