本系列教程所有的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
<?php
namespace Test;
use Illuminate\Database\Eloquent\Factory;
class BaseCase extends TestCase
{
protected $seeder = false;
const DOMAIN = "http://xxx.com";
const API_URI = [];
const TOKEN = [
'local' => '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即可,具体在运行测试阶段看如何指定配置
<?xml version="1.0" encoding="UTF-8"?>
<phpunit
bootstrap="../../bootstrap.php"
convertErrorsToExceptions="true"
convertNoticesToExceptions="false"
convertWarningsToExceptions="false"
colors="true">
<filter>
<whitelist processuncoveredfilesfromwhitelist="true">
<directory suffix=".php">../../../app/Http/Controllers/Headline</directory>
<directory suffix=".php">../../../app/Http/Requests/Headline</directory>
<directory suffix=".php">../../../app/Models/Headline</directory>
<exclude><file>../../../app/Models/Headline/ArticleKeywordsRelationModel.php</file>
</exclude>
</whitelist>
</filter>
<testsuites>
<testsuite name="Headline Test Suite">
<directory>./</directory>
</testsuite>
</testsuites>
<php>
<ini name="date.timezone" value="PRC"/>
<env name="APP_ENV" value="DEV"/>
</php>
<logging>
<log type="coverage-html" target="logs/html/" lowUpperBound="35"
highLowerBound="70"/>
<log type="json" target="logs/logfile.json"/>
<log type="tap" target="logs/logfile.tap"/>
<log type="junit" target="logs/logfile.xml" logIncompleteSkipped="false"/>
<log type="testdox-html" target="logs/testdox.html"/>
<log type="testdox-text" target="logs/testdox.txt"/>
</logging>
<listeners>
<!--<listener class="\Test\Cases\Headline\Listeners\MyListener" file="./Listeners/MyListener.php">-->
<!--<arguments>-->
<!--<array>-->
<!--<element key="0">-->
<!--<string>Sebastian</string>-->
<!--</element>-->
<!--</array>-->
<!--<integer>22</integer>-->
<!--<string>April</string>-->
<!--<double>19.78</double>-->
<!--<null/>-->
<!--<object class="stdClass"/>-->
<!--</arguments>-->
<!--</listener>-->
<!--<listener class="\Test\Cases\Headline\Listeners\MyListener" file="./Listeners/MyListener.php">-->
<!--<arguments>-->
<!--<array>-->
<!--<element key="0">-->
<!--<string>Sebastian</string>-->
<!--</element>-->
<!--</array>-->
<!--<integer>22</integer>-->
<!--</arguments>-->
<!--</listener>-->
</listeners>
</phpunit>
测试用例案例
<?php
/**
* Created by PhpStorm.
* User: qikailin
* Date: 2019-01-29
* Time: 11:57
*/
namespace Test\Cases\Headline\Articles;
use App\Http\Controllers\Headline\ArticleController;
use App\Models\Headline\ArticleCategoryRelationModel;
use App\Models\Headline\ArticleContentModel;
use App\Models\Headline\ArticleKeywordsRelationModel;
use App\Models\Headline\ArticlesModel;
use Faker\Generator;
use Illuminate\Http\Request;
use Test\BaseCase;
class ArticleTest extends BaseCase
{
private static $model;
public static function setUpBeforeClass()
{
parent::setUpBeforeClass();
self::$model = new ArticlesModel();
}
/**
* 生成factory faker 数据构建模型对象
* @codeCoverageIgnore
*/
public function factory($factory)
{
$words = ["测试", "文章", "模糊", "搜索"];
$id = 262;
$factory->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
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。