小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

[PHPUnit]自動(dòng)生成PHPUnit測(cè)試骨架腳本

 bananarlily 2015-08-12

場(chǎng)景

在編寫(xiě)PHPUnit單元測(cè)試代碼時(shí),其實(shí)很多都是對(duì)各個(gè)類的各個(gè)外部調(diào)用的函數(shù)進(jìn)行測(cè)試驗(yàn)證,檢測(cè)代碼覆蓋率,驗(yàn)證預(yù)期效果。為避免增加開(kāi)發(fā)量,可以使用PHPUnit提供的phpunit-skelgen來(lái)生成測(cè)試骨架。只是一開(kāi)始我不知道有這個(gè)腳本,就自己寫(xiě)了一個(gè),大大地提高了開(kāi)發(fā)效率,也不用為另外投入時(shí)間去編寫(xiě)測(cè)試代碼而煩心。并且發(fā)現(xiàn)自定義的腳本比phpunit-skelgen更具人性化。所以在這里分享一下。


一個(gè)待測(cè)試的示例類

假如我們現(xiàn)在有一個(gè)簡(jiǎn)單的業(yè)務(wù)類,實(shí)現(xiàn)了加運(yùn)算,為了驗(yàn)證其功能,下面將會(huì)就兩種生成測(cè)試代碼的方式進(jìn)行說(shuō)明。

1
2
3
4
5
6
7
8
9
<?php
class Demo
{
    public function inc($left$right)
    {
        return $left $right;
    }
}

用phpunit-skelgen生成測(cè)試骨架

在安裝了phpunit-skelgen后,可以使用以下命令來(lái)生成測(cè)試骨架。

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

生成后,使用:

1
vim ./DemoTest.php

可查看到生成的測(cè)試代碼如下:

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 DemoTest extends 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.'
        );
    }
}

試運(yùn)行測(cè)試一下:

1
2
3
4
[test ~/tests]$phpunit ./DemoTest.php    
PHPUnit 3.7.29 by Sebastian Bergmann.
PHP Fatal error:  Class 'Demo' not found in ~/tests/DemoTest.php on line 18

可以看到?jīng)]有將需要的測(cè)試類包括進(jìn)來(lái)。當(dāng)然還有其他一些需要手工改動(dòng)的地方。


自定義的測(cè)試代碼生成腳本

現(xiàn)在改用自定義的腳本 來(lái)生成,雖然也有需要手工改動(dòng)的地方,但已經(jīng)盡量將需要改動(dòng)的代碼最小化,讓測(cè)試人員(很可能是開(kāi)發(fā)人員自己)更關(guān)注業(yè)務(wù)的測(cè)試。

先看一下Usage.

1
2
[test ~/tests]$php ./build_phpunit_test_tpl.php 
Usage: php ./build_phpunit_test_tpl.php <file_path> <class_name> [bootstrap] [author = dogstar]

然后可以使用:

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

來(lái)預(yù)覽看一下將要生成的測(cè)試代碼,如果沒(méi)有問(wèn)題可以使用:

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

將生成的測(cè)試代碼保存起來(lái)。注意:這里使用的是“_Test.php”后綴,以便和官方的區(qū)分??聪律傻拇a:

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
 *
 * 針對(duì) ./Demo.php Demo 類的PHPUnit單元測(cè)試
 *
 * @author: dogstar 20140630
 */
if (!class_exists('Demo')) {
    require dirname(__FILE__) . '/' './Demo.php';
}
class PhpUnderControl_Demo_Test extends 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);
    }
}

隨后,試運(yùn)行一下:

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)

測(cè)試通過(guò)了?。?!

起碼,我覺(jué)得生成的代碼在大多數(shù)默認(rèn)情況下是正常通過(guò)的話,可以給開(kāi)發(fā)人員帶上心理上的喜悅,從而很容易接受并樂(lè)意去進(jìn)行下一步的測(cè)試用例完善。

現(xiàn)在,開(kāi)發(fā)人員只須稍微改動(dòng)測(cè)試代碼就可以實(shí)現(xiàn)對(duì)業(yè)務(wù)的驗(yàn)證。如下示例:

1
2
3
4
5
6
7
8
9
    public function testIncBusinessData()
    {
        $left '1';
        $right '8';
        $rs $this->demo->inc($left$right);
        $this->assertEquals(9, $rs);
    }

然后再運(yùn)行,依然通過(guò)。


腳本源代碼

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
/**
 * 單元測(cè)試骨架代碼自動(dòng)生成腳本
 * 主要是針對(duì)當(dāng)前項(xiàng)目系列生成相應(yīng)的單元測(cè)試代碼,提高開(kāi)發(fā)效率
 *
 * 用法:
 * Usage: php ./build_phpunit_test_tpl.php <file_path> <class_name> [bootstrap] [author = dogstar]
 *
 * 1、針對(duì)全部public的函數(shù)進(jìn)行單元測(cè)試
 * 2、各個(gè)函數(shù)對(duì)應(yīng)返回格式測(cè)試與業(yè)務(wù)數(shù)據(jù)測(cè)試
 * 3、源文件加載(在沒(méi)有自動(dòng)加載的情況下)
 *
 * 備注:另可使用phpunit-skelgen進(jìn)行骨架代碼生成
 *
 * @author: dogstar 20140630
 * @version: 2.0.0
 */
if ($argc < 3) {
    die("Usage: php $argv[0] <file_path> <class_name> [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
 *
 * 針對(duì) $filePath $className 類的PHPUnit單元測(cè)試
 *
 * @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) . "_Test extends PHPUnit_Framework_TestCase
{
    public \$$objName;
    protected function setUp()
    {
        parent::setUp();
        \$this->$objName new $className();
    }
    protected function tearDown()
    {
    }
";
foreach ($methods as $method) {
    if($method->class != $classNamecontinue;
    $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($isConstructorcontinue;
    $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";


    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多