PHPUnit实践二(生命周期)

8次阅读

共计 5082 个字符,预计需要花费 13 分钟才能阅读完成。

本系列教程所有的 PHPUnit 测试基于 PHPUnit6.5.9 版本,Lumen 5.5 框架
PHPUnit 测试一个文件类的生命周期

理解 PHPUnit 加载机制(Lumen 版)

PHPUnit 自动测试文件会自动加载引入(include file)
PHPUnit 去启动 setUp 方法,Lumen 里重写了 setUp,加载了 bootstrap/app.php
app.php 加载了 composer 的 autoload,借此你项目所有自动加载环境都有了,不过不包含 tests 目录

至此我们引入了我们需要构建自己的自动加载类
增加 tests 的自动加载
我们需要给 tests 下的测试用例创建类似下面的结构
├── BaseCase.php 重写过 Lumen 基类的测试基类,用于我们用这个基类做测试基类,后续会说明
├── bootstrap.php tests 自动加载文件
├── Cases 测试用例目录
│   └── Demo 测试模块
│   ├── logs 日志输出目录
│      ├── PipeTest.php PHPUnit 流程测试用例
│   ├── phpunit.xml phpunit 配置文件 xml
│   └── README.md 本模块测试用例说明
├── ExampleTest.php 最原始测试 demo
└── TestCase.php Lumen 自带的测试基类
tests 自动加载文件代码
<?php
/**
* 测试框架的自动加载测试文件类
* User: qikailin
*/
error_reporting(E_ALL ^ E_NOTICE);
require __DIR__ . ‘/../vendor/autoload.php’;

define(‘MY_TESTS_DIR_BASE’, realpath(dirname(__FILE__)));

set_include_path(implode(PATH_SEPARATOR, array(
WPT_TEST_DIR_BASE,
get_include_path()
)));

spl_autoload_register(function ($class) {

$classFile = MY_TESTS_DIR_BASE . DIRECTORY_SEPARATOR . str_replace([“Test\\”, “/”, “\\”],
[“”, DIRECTORY_SEPARATOR, DIRECTORY_SEPARATOR], $class) . “.php”;

if (file_exists($classFile)) {
include_once $classFile;
}

}, true, false);
phpunit.xml
自动加载配置 bootstrap 文件
<?xml version=”1.0″ encoding=”UTF-8″?>

<phpunit
bootstrap=”../../bootstrap.php”
convertErrorsToExceptions=”true”
convertNoticesToExceptions=”false”
convertWarningsToExceptions=”false”
colors=”true”>
</phpunit>
流程测试代码
PipeTest 流程代码
<?php
/**
* 测试类的每个测试方法都会运行一次 setUp() 和 tearDown() 模板方法(同时,每个测试方法都是在一个全新的测试类实例上运行的)。
* 另外,setUpBeforeClass() 与 tearDownAfterClass() 模板方法将分别在测试用例类的第一个测试运行之前和测试用例类的最后一个测试运行之后调用。
* 如果有需要共享的对象或变量,可以放在 setUpBeforeClass,并设置为静态属性
* User: qikailin
*/
namespace Test\Cases\Demo;

use Test\BaseCase;

class PipeTest extends BaseCase
{
public static function setUpBeforeClass()
{
fwrite(STDOUT, __METHOD__ . “\n”);
}

public function setUp()
{
fwrite(STDOUT, __METHOD__ . “\n”);
}

/**
* 测试方法的前置执行,setUp 之后
*/
protected function assertPreConditions()
{
fwrite(STDOUT, __METHOD__ . “\n”);
}

public function testOne()
{
fwrite(STDOUT, __METHOD__ . “\n”);
$this->assertTrue(true);
}

public function testTwo()
{
fwrite(STDOUT, __METHOD__ . “\n”);
// 两个交换下顺序可以看下效果
// 正常执行成功 assert 可以继续执行,失败的会跳出方法
$this->assertArrayHasKey(‘d’, [‘d’=>1, ‘e’=>2]);
$this->assertTrue(false);
}

public function testThree()
{
fwrite(STDOUT, __METHOD__ . “\n”);
$this->assertTrue(false);
}

public function testFour()
{
fwrite(STDOUT, __METHOD__ . “\n”);
}

/**
* 测试方法成功后的后置执行,tearDown 之前
*/
protected function assertPostConditions()
{
fwrite(STDOUT, __METHOD__ . “\n”);
}

public function tearDown()
{
fwrite(STDOUT, __METHOD__ . “\n”);
}

public static function tearDownAfterClass()
{
fwrite(STDOUT, __METHOD__ . “\n”);
}

/**
* 不成功后拦截方法
* 必须重新抛出错误,如果不抛出错误,断言会当成成功了
*/
public function onNotSuccessfulTest(\Throwable $e)
{
fwrite(STDOUT, __METHOD__ . “\n”);
// 必须重新抛出错误,如果不抛出错误,断言会当成成功了
throw $e;
}
}
运行
# 你可以把 vendor/bin 加入到环境变量 PATH
cd tests/Demo
../../../vendor/bin/phpunit
运行输出
PHPUnit 6.5.9 by Sebastian Bergmann and contributors.

Test\Cases\Demo\PipeTest::setUpBeforeClass
Test\Cases\Demo\PipeTest::setUp
Test\Cases\Demo\PipeTest::assertPreConditions
Test\Cases\Demo\PipeTest::testOne
Test\Cases\Demo\PipeTest::assertPostConditions
Test\Cases\Demo\PipeTest::tearDown
.Test\Cases\Demo\PipeTest::setUp
Test\Cases\Demo\PipeTest::assertPreConditions
Test\Cases\Demo\PipeTest::testTwo
Test\Cases\Demo\PipeTest::tearDown
Test\Cases\Demo\PipeTest::onNotSuccessfulTest
FTest\Cases\Demo\PipeTest::setUp
Test\Cases\Demo\PipeTest::assertPreConditions
Test\Cases\Demo\PipeTest::testThree
Test\Cases\Demo\PipeTest::tearDown
Test\Cases\Demo\PipeTest::onNotSuccessfulTest
FTest\Cases\Demo\PipeTest::setUp
Test\Cases\Demo\PipeTest::assertPreConditions
Test\Cases\Demo\PipeTest::testFour
Test\Cases\Demo\PipeTest::assertPostConditions
Test\Cases\Demo\PipeTest::tearDown
R 4 / 4 (100%)Test\Cases\Demo\PipeTest::tearDownAfterClass

Time: 1.29 seconds, Memory: 6.00MB

There were 2 failures:

1) Test\Cases\Demo\PipeTest::testTwo
Failed asserting that false is true.

/xxx/tests/Cases/Demo/PipeTest.php:47

2) Test\Cases\Demo\PipeTest::testThree
Failed asserting that false is true.

/xxx/tests/Cases/Demo/PipeTest.php:53

There was 1 risky test:

1) Test\Cases\Demo\PipeTest::testFour
This test did not perform any assertions

FAILURES!
Tests: 4, Assertions: 4, Failures: 2, Risky: 1.

Generating code coverage report in HTML format … done
整理流程输出
Test\Cases\Demo\PipeTest::setUpBeforeClass
Test\Cases\Demo\PipeTest::setUp
Test\Cases\Demo\PipeTest::assertPreConditions
Test\Cases\Demo\PipeTest::testOne
Test\Cases\Demo\PipeTest::assertPostConditions
Test\Cases\Demo\PipeTest::tearDown
Test\Cases\Demo\PipeTest::setUp
Test\Cases\Demo\PipeTest::assertPreConditions
Test\Cases\Demo\PipeTest::testTwo
Test\Cases\Demo\PipeTest::tearDown
Test\Cases\Demo\PipeTest::onNotSuccessfulTest
Test\Cases\Demo\PipeTest::setUp
Test\Cases\Demo\PipeTest::assertPreConditions
Test\Cases\Demo\PipeTest::testThree
Test\Cases\Demo\PipeTest::tearDown
Test\Cases\Demo\PipeTest::onNotSuccessfulTest
Test\Cases\Demo\PipeTest::setUp
Test\Cases\Demo\PipeTest::assertPreConditions
Test\Cases\Demo\PipeTest::testFour
Test\Cases\Demo\PipeTest::assertPostConditions
Test\Cases\Demo\PipeTest::tearDown
Test\Cases\Demo\PipeTest::tearDownAfterClass
总结
一个测试类文件,从 setUpBeforeClass 加载,且仅此加载一次每个测试方法都会走的过程:setUp->assertPreConditions-> 测试方法 ->[assert 成功执行:assertPostConditions]->tearDown->[assert 执行失败:onNotSuccessfulTest,且本方法需要抛出错误] 本个测试类文件执行 tearDownAfterClass 结束
参考
PHPUnit 6.5 官方文档

正文完
 0