资讯专栏INFORMATION COLUMN

你所不知的 PHP 断言(assert)

Pines_Cheng / 805人阅读

摘要:中的断言常用于调试,检查一个表达式或语句是否为。用的最多的场景就是单元测试,一般的单元测试框架都采用了断言。运行结果中的断言在中,采用函数对表达式进行断言。单元测试测试不通过测试不通过是不是跟我们用写单元测试很像

</>复制代码

  1. PHP 中的断言常用于调试,检查一个表达式或语句是否为 FALSE。本文带你重新认识 PHP assert() 函数的神(Qi)通(Yin)广(Ji)大(Qiao)。

    本文基于 PHP Version 7.1.28

什么是断言

编写程序时,常会做出一定的假设,那断言就是用来捕获假设的异常,我们也可以认为断言是异常的一种特殊形式。

断言一般用于程序执行结构的判断,不可让断言处理业务流程。用的最多的场景就是单元测试,一般的单元测试框架都采用了断言。

</>复制代码

  1. assert(1 == 2);
  2. // 运行结果:
  3. // Warning: assert(): assert(1 == 2) failed in /Users/shocker/Desktop/demo.php on line 25
PHP 中的断言

在 PHP 中,采用 assert() 函数对表达式进行断言。

</>复制代码

  1. // PHP 5
  2. assert ( mixed $assertion [, string $description ] ) : bool
  3. // PHP 7
  4. assert ( mixed $assertion [, Throwable $exception ] ) : bool
传统的断言方式 (PHP 5 & 7)

</>复制代码

  1. 参数 assertion 既支持表达式,也支持表达式字符串(某些特定的场景会用到,比如判断某个字符串表达式是否合法)

如果 assertion 是字符串,它将会被 assert() 当做 PHP 代码来执行。assertion 是字符串的优势是当禁用断言时它的开销会更小,并且在断言失败时消息会包含 assertion 表达式

断言这个功能应该只被用来调试。你应该用于完整性检查时测试条件是否始终应该为 TRUE,来指示某些程序错误,或者检查具体功能的存在(类似扩展函数或特定的系统限制和功能)。

断言不应该用于普通运行时操作,类似输入参数的检查。作为一个经验法则,在断言禁用时你的代码也应该能够正确地运行。

使用示例:

</>复制代码

  1. function my_assert_handler($file, $line, $code, $desc)
  2. {
  3. echo "Assertion Failed:
  4. File "{$file}"
  5. Line "{$line}"
  6. Code "{$code}"
  7. Desc "{$desc}"
  8. ";
  9. }
  10. // 设置回调函数
  11. assert_options(ASSERT_CALLBACK, "my_assert_handler");
  12. // 让一则断言失败
  13. assert("1 == 2", "1 不可能等于 2");

运行结果:

</>复制代码

  1. Assertion Failed:
  2. File "/Users/shocker/Desktop/demo.php"
  3. Line "29"
  4. Code "1 == 2"
  5. Desc "1 不可能等于 2"
支持异常的断言 (仅 PHP 7)

在 PHP 7 中,assert() 是一个语言结构,允许在不同环境中生效不同的措施,具体可见 zend.assertions 配置。

另外,还支持通过 AssertionError 捕获错误。

使用示例:

</>复制代码

  1. assert_options(ASSERT_EXCEPTION, 1); // 在断言失败时产生异常
  2. try {
  3. // 用 AssertionError 异常替代普通字符串
  4. assert(true == false, new AssertionError("True is not false!"));
  5. } catch (Throwable $e) {
  6. echo $e->getMessage();
  7. }

运行结果:

</>复制代码

  1. True is not false!
对断言行为进行控制

PHP 支持 assert_options() 函数对断言进行配置,也可用 ini 进行设置

</>复制代码

  1. 以下配置中,常量标志用于 assert_options() 函数进行配置,ini 设置用于 ini_set() 函数设置,效果一样
标志 INI 设置 默认值 描述
ASSERT_ACTIVE assert.active "1" 启用 assert() 断言
ASSERT_WARNING assert.warning "1" 为每个失败的断言产生一个 PHP 警告(warning)
ASSERT_BAIL assert.bail "0" 在断言失败时中止执行
ASSERT_QUIET_EVAL assert.quiet_eval "0" 在断言表达式求值时禁用 error_reporting
ASSERT_CALLBACK assert.callback NULL 断言失败时调用该回调函数
ASSERT_EXCEPTION assert.exception "0" 在断言失败时产生 AssertionError 异常 (自 PHP 7.0.0 起有效)

zend.assertions 是个特殊的配置(PHP >= 7.0.0 支持),控制不同运行环境下断言的行为,仅可用 ini_set() 进行设置。并且,设置了1就不能再设置为-1,反之亦然,其他不受限。

</>复制代码

  1. 1: 编译代码,并执行(开发模式)

  2. 0: 编辑代码,但运行时跳过

  3. -1: 不编译代码(生产模式)

版本的不兼容

PHP >= 5.4.8,description 可作为第四个参数提供给 ASSERT_CALLBACK 模式里的回调函数

在 PHP 5 中,参数 assertion 必须是可执行的字符串,或者运行结果为布尔值的表达式

在 PHP 7 中,参数 assertion 可以是任意表达式,并用其运算结果作为断言的依据

在 PHP 7 中,参数 exception 可以是个 Throwable 对象,用于捕获表达式运行错误或断言结果为失败。(当然 assert.exception 需开启)

PHP >= 7.0.0,支持 zend.assertionsassert.exception 相关配置及其特性

PHP >= 7.2 版本开始,参数 assertion 不再支持字符串

</>复制代码

  1. 详见 PHP 7.2.x 中废弃的功能

</>复制代码

  1. Deprecated: assert(): Calling assert() with a string argument is deprecated

应用场景 调试输出

先看示例:

</>复制代码

  1. assert("1 == 2", "1 不可能等于 2");

运行结果:

</>复制代码

  1. Warning: assert(): 1 不可能等于 2: "1 == 2" failed in /Users/shocker/Desktop/demo.php on line 10

类似于:

</>复制代码

  1. $expression = 1 == 2;
  2. if (!($expression)) {
  3. echo "1 不可能等于 2
  4. ";
  5. var_dump($expression);
  6. echo __FILE__ . "
  7. ";
  8. }

但是,我们无法得知 $expression 的具体表达式,也无法得知具体的执行行数。

单元测试

</>复制代码

  1. function arraySum(array $nums) {
  2. $sum = 0;
  3. foreach ($nums as $n) {
  4. $sum += $n;
  5. }
  6. return $sum;
  7. }
  8. assert(arraySum([1, 2, 3]) == 6, "arraySum() 测试不通过:");
  9. assert(is_numeric(arraySum([1, 2, 3])), "arraySum() 测试不通过:");

是不是跟我们用 PHPUnit 写单元测试很像

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/31627.html

相关文章

  • 【modernPHP专题(11)】断言ASSERT

    摘要:可以在任何时候启用和禁用断言验证,因此可以在测试时启用断言,而在部署时禁用断言。会检查指定的并在结果为时采取适当的行动视而定。中的断言向后兼用并增强之前的的方法。它使得在生产环境中启用断言为零成本,并且提供当断言失败时抛出特定异常的能力。 简述 编写代码时,我们总是会做出一些假设,断言就是用于在代码中捕捉这些假设,可以将断言看作是异常处理的一种高级形式。程序员断言在程序中的某个特定点该...

    WalkerXu 评论0 收藏0
  • 16.java异常处理

    摘要:不受检查异常为编译器不要求强制处理的异常,检查异常则是编译器要求必须处置的异常。潜在的异常处理器是异常发生时依次存留在调用栈中的方法的集合。当运行时系统遍历调用栈而未找到合适的异常处理器,则运行时系统终止。异常处理涉及到五个关键字,分别是。 概念 程序运行时,发生的不被期望的事件,它阻止了程序按照程序员的预期正常执行,这就是异常。 异常是程序中的一些错误,但并不是所有的错误都是异常,并...

    asce1885 评论0 收藏0
  • 【Node Hero】9. Node.js 单元测试

    摘要:基本上,测试金字塔描述你应该编写单元测试集成测试和端到端测试。集成测试要比端到端测试多,单元测试甚至要更多一些。应用程序单元测试编写单元测试,是为了看看给定的模块单元是否工作。 本文转载自:众成翻译译者:网络埋伏纪事链接:http://www.zcfy.cc/article/1754原文:https://blog.risingstack.com/node-hero-node-js-un...

    104828720 评论0 收藏0
  • phpunit PHP单元测试利器

    摘要:是的单元测试框架。单元测试在软件开发中越来越受到重视,测试先行编程极限编程和测试驱动开发在实践中被广泛。利用单元测试,也可以实现契约式设计。现在第二个测试也能通过啦你也可以使用契约式设计的风格,只需使用类提供的静态断言方法编写契约条件。 PHPUnit是PHP的单元测试框架。单元测试在软件开发中越来越受到重视,测试先行编程、极限编程和测试驱动开发在实践中被广泛。利用单元测试,也可以实现...

    wyk1184 评论0 收藏0
  • Python中不尽如人意断言Assertion

    摘要:为何不尽如人意中的断言用起来非常简单,你可以在后面跟上任意判断条件,如果断言失败则会抛出异常。中的断言可读性很好,而且智能提示也很方便你通过轻松完成各种断言语句。而且它的断言信息简洁明了,不多不少。 Python Assert 为何不尽如人意 Python中的断言用起来非常简单,你可以在assert后面跟上任意判断条件,如果断言失败则会抛出异常。 >>> assert 1 + 1 ==...

    The question 评论0 收藏0

发表评论

0条评论

Pines_Cheng

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<