PHPUnit实践三(构建模块化的测试单元)

本系列教程所有的PHPUnit测试基于PHPUnit6.5.9版本,Lumen 5.5框架

目录结构

模块下的目录是符合Lumen的模块结构的
如:Controllers、Models、Logics等是Lumen模块目录下的结构目录
如果有自己的目录同级分配即可,如我这里的Requests

整体结构

├── BaseCase.php 重写过Lumen基类的测试基类,用于我们用这个基类做测试基类,后续会说明
├── bootstrap.php tests自动加载文件
├── Cases 测试用例目录
│   └── Headline 某测试模块
│       ├── logs 日志输出目录
│       ├── PipeTest.php PHPUnit流程测试用例
│       ├── phpunit.xml phpunit配置文件xml
│       └── README.md 本模块测试用例说明
├── ExampleTest.php 最原始测试demo
└── TestCase.php Lumen自带的测试基类

某模块的目录结构

Headline  //某测试模块测试用例目录
├── Cache
├── Controllers
│   ├── ArticleTest.php
│   ├── ...
├── Listeners
│   └── MyListener.php
├── Logics
├── Models
│   ├── ArticleTest.php
│   ├── ...
├── README.md
├── Requests
│   ├── ArticleTest.php
│   ├── ...
├── logs //日志和覆盖率目录
│   ├── html
│   │   ├── ...
│   │   └── index.html
│   ├── logfile.xml
│   ├── testdox.html
│   └── testdox.txt
├── phpunit-debug-demo.xml   //phpunit.xml案例
├── phpunit-debug.xml        //改名后测试用的
└── phpunit.xml              //正式用的xml配置

BaseCase.php

 'token*',
        'dev' => 'token*',
        'prod' => '' //如果测试真实请填写授权token
    ];

    /**
     * 重写setUp
     */
    public function setUp()
    {
        parent::setUp();

        $this->seeder = false;
        if (method_exists($this, 'factory')) {
            $this->app->make('db');
            $this->factory($this->app->make(Factory::class));

            if (method_exists($this, 'seeder')) {
                if (!method_exists($this, 'seederRollback')) {
                    dd("请先创建seederRollback回滚方法");
                }
                $this->seeder = true;
                $this->seeder();
            }
        }
    }

    /**
     * 重写tearDown
     */
    public function tearDown()
    {
        if ($this->seeder && method_exists($this, 'seederRollback')) {
            $this->seederRollback();
        }

        parent::tearDown();
    }

    /**
     * 获取地址
     * @param string $apiKey
     * @param string $token
     * @return string
     */
    protected function getRequestUri($apiKey = 'list', $token = 'dev', $ddinfoQuery = true)
    {
        $query = "?token=" . static::TOKEN[strtolower($token)];
        if ($ddinfoQuery) {
            $query = $query . "&" . http_build_query(static::DDINFO);
        }

        return $apiUri = static::DOMAIN . static::API_URI[$apiKey] . $query;
    }
}

phpunit-debug-demo.xml

本文件是我们单独为某些正在测试的测试用例,直接编写的xml,可以不用来回测试,已经测试成功的测试用例了,最后全部编写完测试用例,再用正式phpunit.xml即可,具体在运行测试阶段看如何指定配置




    
        
            ../../../app/Http/Controllers/Headline
            ../../../app/Http/Requests/Headline
            ../../../app/Models/Headline
            ../../../app/Models/Headline/ArticleKeywordsRelationModel.php
            
        
    

    
        
            ./
        
    

    
        
        
    

    
        
        
        
        
        
        
    

    
        
            
                
                    
                        
                    
                
                
                
                
                
                
            
        
        
            
                
                    
                        
                    
                
                
            
        
    

测试用例案例

define(ArticlesModel::class, function (Generator $faker) use (&$id, $words) {
            $id++;
            return [
                'id' => $id,
                'uri' => $faker->lexify('T???????????????????'),
                'title' => $id == 263 ? "搜索" : $words[rand(0, sizeof($words) - 1)],
                'authorId' => 1,
                'state' => 1,
                'isUpdated' => 0,
            ];
        });
    }

    /**
     * 生成模拟的数据,需seederRollback 成对出现
     */
    public function seeder()
    {
        $articles = factory(ArticlesModel::class, 10)->make();
        foreach ($articles as $article) { // 注意: article为引用对象,不是copy
            if ($article->isRecommend) {
                $article->recommendTime = time();
            }
            $article->save();
        }
    }

    /**
     * getArticleList 测试数据
     * @return array
     */
    public function getArticleListDataProvider()
    {
        return [
            [1, "搜索", 1, 10, 1],
            [2, "搜索", 1, 10, 0],
            [2, null, 1, 10, 0],
            [3, "搜索", 1, 10, 0],
            [1, null, 1, 10, 1],
            [2, null, 1, 10, 0],
            [3, null, 1, 10, 0],
        ];
    }

    /**
     * @dataProvider getArticleListDataProvider
     */
    public function testGetArticleList($type, $searchText, $page, $pageSize, $expceted)
    {
        $rst = self::$model->getArticleList($type, $searchText, $page, $pageSize);

        $this->assertGreaterThanOrEqual($expceted, sizeof($rst));

        $rst = self::$model->getArticleCount($type, $searchText);

        $this->assertGreaterThanOrEqual($expceted, $rst);
    }

    /**
     * addArticle 测试数据
     * @return array
     */
    public function addArticleDataProvider()
    {
        return [
            [
                [
                    'id' => 273,
                    'uri' => 'dddddddddd0123'
                ],
                'save',
                0
            ],
            [
                [
                    'id' => 274,
                    'uri' => 'dddddddddd123'
                ],
                'publish',
                0
            ],
            [
                [
                    'id' => 275,
                    'uri' => 'dddddddddd456'
                ],
                'preview',
                0
            ],
        ];
    }

    /**
     * @dataProvider addArticleDataProvider
     */
    public function testAdd($data, $action, $expected)
    {
        $rst = self::$model->addArticle($data, $action);

        if ($rst) {
            self::$model::where('id', $rst)->delete();
        }

        $this->assertGreaterThanOrEqual($expected, $rst);
    }

    public function testGetArticleInfo()
    {
        $rst = self::$model->getArticleInfo(263, 0);

        $this->assertGreaterThanOrEqual(1, sizeof($rst));

        $rst = self::$model->getArticleInfo(2000, 1);

        $this->assertEquals(0, sizeof($rst));
    }


    /**
     * 回滚模拟的数据到初始状态
     */
    public function seederRollback()
    {
        self::$model::where('id', '>=', 263)->where('id', '<=', 272)->delete();
    }
}

运行测试

cd {APPROOT}/tests/Cases/Headline
# mv phpunit-debug-custom.xml -> phpunit-debug.xml
../../../vendor/bin/phpunit --verbose -c phpunit-debug.xml

参考

PHPUnit 5.0 官方中文手册

你可能感兴趣的:(单元测试,模块化,lumen,phpunit,php)