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

PHPUnit测试一个文件类的生命周期

理解PHPUnit加载机制(Lumen版)

  1. PHPUnit自动测试文件会自动加载引入(include file)
  2. PHPUnit去启动setUp方法,Lumen里重写了setUp,加载了bootstrap/app.php
  3. 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"?><phpunitbootstrap="../../bootstrap.php"convertErrorsToExceptions="true"convertNoticesToExceptions="false"convertWarningsToExceptions="false"colors="true">
</phpunit>

流程测试代码

TestCase.php

# 代码头部添加 命令空间Test
namespace Test;

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::tearDownAfterClassTime: 1.29 seconds, Memory: 6.00MBThere were 2 failures:1) Test\Cases\Demo\PipeTest::testTwo
Failed asserting that false is true./xxx/tests/Cases/Demo/PipeTest.php:472) 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 assertionsFAILURES!
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 官方文档

PHPUnit实践二(生命周期)相关推荐

  1. IIS 7.0的ASP.NET应用程序生命周期概述

    小结于:http://msdn.microsoft.com/zh-cn/library/bb470252(v=vs.100).aspx IIS 7.0的ASP.NET应用程序生命周期概述 (一)结构概 ...

  2. 深度挖掘 Laravel 生命周期

    本文首发于个人博客 深度挖掘 Laravel 生命周期,转载请注明出处. 这篇文章我们来聊聊 「Laravel 生命周期」 这个主题.虽然网络上已经有很多关于这个主题的探讨,但这个主题依然值得我们去研 ...

  3. Vue的过滤器,生命周期的钩子函数和使用Vue-router

    一.过滤器 1.局部过滤器 在当前组件内部使用过滤器 给某些数据 添油加醋 //声明 filters:{'过滤器的名字':function(val,a,b){//a 就是alax ,val就是当前的数 ...

  4. 【vue】vue中axios的使用及vue生命周期详解_07

    目录 一. axios请求 二. 生命周期

  5. 微信小程序 网络请求接口 及 生命周期

    前言:前期我们对微信小程序有些基本了解,像标签,样式,组件....等. 今天我们继前期进行继续的了解 一. 网络请求 HTTP(HyperText Transfer Protocol)是一套计算机通过 ...

  6. React组件(进阶--生命周期 )

    目录 一.生命周期 - 概述 二.生命周期 - 挂载阶段 三.生命周期 - 更新阶段 四.生命周期 - 卸载阶段 文章推荐: 1.JSX基础(入门) 2.React组件(入门) 3.React组件动状 ...

  7. EF Core上下文DbContext相关配置和生命周期

    一. 配置相关 1. 数据库连接字符串的写法 (1).账号密码:Server=localhost;Database=EFDB01;User ID=sa;Password=123456; (2).win ...

  8. PPT 下载 | 神策数据孙文亮:客户全生命周期管理从方法到实践全解析

    在以"场景赋能·驱动有数"为主题的神策 2018 数据驱动大会现场,神策数据技术经理孙文亮发表了名为<客户全生命周期管理从方法到实践>的主题演讲. 温馨提示:点击文末阅 ...

  9. 用户增长 - BG/NBD概率模型预测用户生命周期LTV(二)

    文章目录 1 理论 1.1 BG / NBD概率模型介绍 1.2 Gamma-Gamma模型 2 实践案例 2.1 lifetimes实践案例一:在线零售业务的交易 2.1.1 数据解读 2.1.2 ...

最新文章

  1. Spring 通过工厂方法(Factory Method)来配置bean
  2. eeglab教程系列(2)-加载、显示数据
  3. python在财务中的应用实训报告-DATATOM | 大数据实训
  4. C++ 可以把变量当成函数用~~
  5. Debug system:无法显示数据
  6. matlab 2010 win7 64位,64位WIN7系统怎么安装Matlab2010
  7. 【快应用篇01】快应用它来了!带你了解什么是快应用!
  8. inputn函数与input函数的区别
  9. JDK8新特性之Optional
  10. Qt 事件处理机制 (上篇)
  11. w7如何调出计算机图标来,W7电脑系统怎么显示桌面图标
  12. NOI OpenJudge 8469 特殊密码锁 Label贪心
  13. 动态生成ContextMenuStrip
  14. 测试Live Write的发布功能
  15. 如何安装uclient_uclient软件下载|
  16. html返回顶部动画,基于JavaScript实现回到页面顶部动画代码
  17. 通俗讲解光线追踪原理,一文理清各类光线追踪
  18. ajax学员信息php,PHP开源AJAX框架
  19. 世界人工智能大会即将举办 AI机器人帮你分类垃圾
  20. 力天创见排队客流统计

热门文章

  1. iOS单例创建的一点疑惑
  2. iOS开发之UIMenuController的基本使用
  3. MBG 相关资源链接
  4. 说说JSON和JSONP,也许你会豁然开朗
  5. Debian 7(Wheezy)下配置Open×××
  6. CentOS 6.x使用yum快速安装MySQL 5.5
  7. 关于mtl_transactions_interface表序列
  8. HDU-1042 N! 大数乘法 (C语言)
  9. RAC 实例 迁移到 单实例 -- 使用导出导入
  10. MSP430学习笔记