内容简介:本教程所有的PHPUnit测试基于日常我们的普通用到的测试:单元测试是针对程序的最小单元来进行正确性检验的测试工作,程序单元就是应用的最小可测试部件,一个单元可能是单个程序,类,对象,方法等
本教程所有的PHPUnit测试基于 PHPUnit6.5.9 版本, Lumen 5.5 框架
前置
日常我们的普通用到的测试:
- 代码直接echo,debug等方法测试 -> 跟踪细节断点型测试
- log日志辅助测试 -> 跟踪细节断点型测试
- 辅助工具,postman之类的做请求类测试->请求类测试
- 浏览器直接测试->浏览器测试
单元测试
单元测试是针对程序的最小单元来进行正确性检验的测试工作,程序单元就是应用的最小可测试部件,一个单元可能是单个程序,类,对象,方法等
单元测试是用来测试包或者程序的一部分代码或者一组代码的函数。测试的目的是确认目标代码在给定的场景下,有没有按照期望工作。
一个场景是正向路经测试,就是在正常执行的情况下,保证代码不产生错误的测试。这种测试可以用来确认代码可以成功地向数据库中插入一条工作记录。
另外一些单元测试可能会测试负向路径的场景,保证代码不仅会产生错误,而且是预期的错误。
这种场景下的测试可能是对数据库进行查询时没有找到任何结果,或者对数据库做了无效的更新。
在这两种情况下,测试都要验证确实产生了错误,且产生的是预期的错误。总之,不管如何调用或者执行代码,所写的代码行为都是可预期的
优点或改善解决问题
-
减少bug
通过运行单元测试可以直接测试各个功能的正确性,有bug可以直接发现并解决,如果要等到跟其他的功能对接,进行连贯测试,测试比较麻烦,而且bug不能及早的发现并解决
-
快速定位bug
如果是web项目的某一个功能,平常我们定位bug可能是页面输入值,后台断点,一步一步的需要bug位置,如果有编写单元测试,则可以直接修改数据,运行单元测试即可,快速有限
-
提高代码质量
如果每一个部件都是完美的,那么组合起来肯定也是完美的。整体代码质量就得到了保障
-
减少调试时间
当不知问题所在的时候,可能需要各种调试与运行,而如果所有的都有编写单元测试,那么可以直接运行单元测试,就能定位问题所在位置。
PHPUnit
PHPUnit是一个面向 PHP 程序员的测试框架,这是一个xUnit的体系结构的单元测试框架。
版本
| 主版本 | 初始版本 | PHP兼容性 | 支持 | 后台框架对应版本 |
|---|---|---|---|---|
| PHPUnit 8 | 2019年2月1日 | PHP 7.2, PHP 7.3, PHP 7.4 | 在2021年2月5日结束支持 | |
| PHPUnit 7 | 2018年2月2日 | PHP 7.1, PHP 7.2, PHP 7.3 | 在2020年2月7日结束支持 | |
| PHPUnit 6 | 2017年2月3日 | PHP 7.0, PHP 7.1, PHP 7.2 | 在2019年2月1日结束支持 | * |
| PHPUnit 5 | 2015年10月2日 | PHP 5.6, PHP 7.0, PHP 7.1 | 在2018年2月2日结束支持 | |
| PHPUnit 4 | 2014年3月7日 | PHP 5.3, PHP 5.4, PHP 5.5, PHP 5.6 | 在2017年2月3日结束支持 |
PHPUnit测试一个文件类的生命周期
流程测试代码
自动加载文件
<?php
/**
* 测试框架的自动加载测试文件类
* User: qikailin
*/
error_reporting(E_ALL ^ E_NOTICE);
require __DIR__ . '/../vendor/autoload.php';
define('WPT_TEST_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 = WPT_TEST_DIR_BASE . DIRECTORY_SEPARATOR . str_replace(["Test\\", "/", "\\"],
["", DIRECTORY_SEPARATOR, DIRECTORY_SEPARATOR], $class) . ".php";
if (file_exists($classFile)) {
include_once $classFile;
}
}, true, false);
PipeTest 流程代码
<?php
/**
* 测试类的每个测试方法都会运行一次 setUp() 和 tearDown() 模板方法(同时,每个测试方法都是在一个全新的测试类实例上运行的)。
* 另外,setUpBeforeClass() 与 tearDownAfterClass() 模板方法将分别在测试用例类的第一个测试运行之前和测试用例类的最后一个测试运行之后调用。
* 如果有需要共享的对象或变量,可以放在setUpBeforeClass,并设置为静态属性
* User: qikailin
*/
namespace Test\Cases\Headline;
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 ../../../vendor/bin/phpunit --bootstrap ../../bootstrap.php Cases/Demo/PipeTest.php
运行输出
PHPUnit 6.5.9 by Sebastian Bergmann and contributors. Test\Cases\Headline\PipeTest::setUpBeforeClass Test\Cases\Headline\PipeTest::setUp Test\Cases\Headline\PipeTest::assertPreConditions Test\Cases\Headline\PipeTest::testOne Test\Cases\Headline\PipeTest::assertPostConditions Test\Cases\Headline\PipeTest::tearDown .Test\Cases\Headline\PipeTest::setUp Test\Cases\Headline\PipeTest::assertPreConditions Test\Cases\Headline\PipeTest::testTwo Test\Cases\Headline\PipeTest::tearDown Test\Cases\Headline\PipeTest::onNotSuccessfulTest FTest\Cases\Headline\PipeTest::setUp Test\Cases\Headline\PipeTest::assertPreConditions Test\Cases\Headline\PipeTest::testThree Test\Cases\Headline\PipeTest::tearDown Test\Cases\Headline\PipeTest::onNotSuccessfulTest FTest\Cases\Headline\PipeTest::setUp Test\Cases\Headline\PipeTest::assertPreConditions Test\Cases\Headline\PipeTest::testFour Test\Cases\Headline\PipeTest::assertPostConditions Test\Cases\Headline\PipeTest::tearDown R 4 / 4 (100%)Test\Cases\Headline\PipeTest::tearDownAfterClass Time: 1.29 seconds, Memory: 6.00MB There were 2 failures: 1) Test\Cases\Headline\PipeTest::testTwo Failed asserting that false is true. /web/www/wpt/gt-api/tests/Cases/Demo/PipeTest.php:47 2) Test\Cases\Headline\PipeTest::testThree Failed asserting that false is true. /web/www/wpt/gt-api/tests/Cases/Demo/PipeTest.php:53 -- There was 1 risky test: 1) Test\Cases\Headline\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\Headline\PipeTest::setUpBeforeClass Test\Cases\Headline\PipeTest::setUp Test\Cases\Headline\PipeTest::assertPreConditions Test\Cases\Headline\PipeTest::testOne Test\Cases\Headline\PipeTest::assertPostConditions Test\Cases\Headline\PipeTest::tearDown Test\Cases\Headline\PipeTest::setUp Test\Cases\Headline\PipeTest::assertPreConditions Test\Cases\Headline\PipeTest::testTwo Test\Cases\Headline\PipeTest::tearDown Test\Cases\Headline\PipeTest::onNotSuccessfulTest Test\Cases\Headline\PipeTest::setUp Test\Cases\Headline\PipeTest::assertPreConditions Test\Cases\Headline\PipeTest::testThree Test\Cases\Headline\PipeTest::tearDown Test\Cases\Headline\PipeTest::onNotSuccessfulTest Test\Cases\Headline\PipeTest::setUp Test\Cases\Headline\PipeTest::assertPreConditions Test\Cases\Headline\PipeTest::testFour Test\Cases\Headline\PipeTest::assertPostConditions Test\Cases\Headline\PipeTest::tearDown Test\Cases\Headline\PipeTest::tearDownAfterClass
输出标识说明
. 当测试成功时输出。 F 当测试方法运行过程中一个断言失败时输出。 E 当测试方法运行过程中产生一个错误时输出。 R 当测试被标记为有风险时输出。 S 当测试被跳过时输出。 I 当测试被标记为不完整或未实现时输出。
参考
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
零售的哲学:7-Eleven便利店创始人自述
[日] 铃木敏文 / 顾晓琳 / 江苏文艺出版社 / 2014-12-1 / 36
全球最大的便利店连锁公司创始人——铃木敏文,结合40多年零售经验,为你讲述击中消费心理的零售哲学。铃木敏文的很多创新,现在已经成为商界常识,本书把那些不可思议的零售创新娓娓道来。关于零售的一切:选址、订货、销售、物流、管理……他一次又一次地在一片反对声中创造出零售界的新纪录。 翻开本书,看铃木敏文如何领导7-11冲破层层阻碍,成为世界第一的零售哲学。一起来看看 《零售的哲学:7-Eleven便利店创始人自述》 这本书的介绍吧!
在线进制转换器
各进制数互转换器
XML、JSON 在线转换
在线XML、JSON转换工具