本系列教程全部的PHPUnit測試基於PHPUnit6.5.9版本,Lumen 5.5框架php
模塊下的目錄是符合Lumen的模塊結構的
如:Controllers、Models、Logics等是Lumen模塊目錄下的結構目錄
若是有本身的目錄同級分配便可,如我這裏的Requestshtml
├── 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配置
<?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; } }
本文件是咱們單獨爲某些正在測試的測試用例,直接編寫的xml,能夠不用來回測試,已經測試成功的測試用例了,最後所有編寫完測試用例,再用正式phpunit.xml便可,具體在運行測試階段看如何指定配置json
<?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
PHPUnit 5.0 官方中文手冊bootstrap