第 1 章 安装 PHPUnit

需求

PHPUnit 6.5 需要 PHP 7,强烈推荐使用最新版本的 PHP。

PHPUnit 需要使用 domjson 扩展,它们通常是默认启用的。

PHPUnit 还需要 pcrereflectionspl 扩展。这些标准扩展默认启用,并且除非修改 PHP 的构建系统和 C 源代码,否则无法禁用它们。

代码覆盖率分析报告功能需要 Xdebug(2.5.0以上)与 tokenizer 扩展。生成 XML 格式的报告需要有 xmlwriter 扩展。

PHP 档案包 (PHAR)

要获取 PHPUnit,最简单的方法是下载 PHPUnit 的 PHP 档案包 (PHAR),它将 PHPUnit 所需要的所有必要组件(以及某些可选组件)捆绑在单个文件中:

要使用 PHP档案包(PHAR)需要有 phar 扩展。

如果启用了 Suhosin 扩展,需要在 php.ini 中允许执行 PHAR:

  1. suhosin.executor.include.whitelist = phar

如果要全局安装 PHAR:

  1. $ wget https://phar.phpunit.de/phpunit-6.5.phar
  2. $ chmod +x phpunit-6.5.phar
  3. $ sudo mv phpunit-6.5.phar /usr/local/bin/phpunit
  4. $ phpunit --version
  5. PHPUnit x.y.z by Sebastian Bergmann and contributors.

也可以直接使用下载的 PHAR 文件:

  1. $ wget https://phar.phpunit.de/phpunit-6.5.phar
  2. $ php phpunit-6.5.phar --version
  3. PHPUnit x.y.z by Sebastian Bergmann and contributors.

Windows

整体上说,在 Windows 下安装 PHAR 和手工在 Windows 下安装 Composer 是一样的过程:

  • 为 PHP 的二进制可执行文件建立一个目录,例如 C:\bin

  • ;C:\bin 附加到 PATH 环境变量中(相关帮助

  • 下载 https://phar.phpunit.de/phpunit-6.5.phar 并将文件保存到 C:\bin\phpunit.phar

  • 打开命令行(例如,按 Windows+R » 输入 cmd » ENTER)

  • 建立外包覆批处理脚本(最后得到 C:\bin\phpunit.cmd):

  1. C:\Users\username> cd C:\bin
  2. C:\bin> echo @php "%~dp0phpunit.phar" %* > phpunit.cmd
  3. C:\bin> exit
  • 新开一个命令行窗口,确认一下可以在任意路径下执行 PHPUnit:
  1. C:\Users\username> phpunit --version
  2. PHPUnit x.y.z by Sebastian Bergmann and contributors.

对于 Cygwin 或 MingW32 (例如 TortoiseGit) shell 环境,可以跳过第五步。 取而代之的是,把文件保存为 phpunit (没有 .phar 扩展名),然后用 chmod 775 phpunit 将其设为可执行。

校验 PHPUnit PHAR 发行包

由 PHPUnit 项目分发的所有官方代码发行包都由发行包管理器进行签名。在 phar.phpunit.de 上有 PGP 签名和 SHA1 散列值可用于校验。

下面的例子详细说明了如何对发行包进行校验。首先下载 phpunit.phar 和与之对应的单独 PGP 签名 phpunit.phar.asc

  1. wget https://phar.phpunit.de/phpunit.phar
  2. wget https://phar.phpunit.de/phpunit.phar.asc

用单独的签名(phpunit.phar)对 PHPUnit 的 PHP 档案包(phpunit.phar.asc)进行校验:

  1. gpg phpunit.phar.asc
  2. gpg: Signature made Sat 19 Jul 2014 01:28:02 PM CEST using RSA key ID 6372C20A
  3. gpg: Can't check signature: public key not found

在本地系统中没有发行包管理器的公钥(6372C20A)。为了能进行校验,必须从某个密钥服务器上取得发行包管理器的公钥。其中一个服务器是 pgp.uni-mainz.de。所有密钥服务器是链接在一起的,因此连接到任一密钥服务器都可以。

  1. gpg --keyserver pgp.uni-mainz.de --recv-keys 0x4AA394086372C20A
  2. gpg: requesting key 6372C20A from hkp server pgp.uni-mainz.de
  3. gpg: key 6372C20A: public key "Sebastian Bergmann <sb@sebastian-bergmann.de>" imported
  4. gpg: Total number processed: 1
  5. gpg: imported: 1 (RSA: 1)

现在已经取得了条目名称为"Sebastian Bergmann <sb@sebastian-bergmann.de>"的公钥。不过无法检验这个密钥确实是由名叫 Sebastian Bergmann 的人创建的。但是可以先试着校验发行包的签名:

  1. gpg phpunit.phar.asc
  2. gpg: Signature made Sat 19 Jul 2014 01:28:02 PM CEST using RSA key ID 6372C20A
  3. gpg: Good signature from "Sebastian Bergmann <sb@sebastian-bergmann.de>"
  4. gpg: aka "Sebastian Bergmann <sebastian@php.net>"
  5. gpg: aka "Sebastian Bergmann <sebastian@thephp.cc>"
  6. gpg: aka "Sebastian Bergmann <sebastian@phpunit.de>"
  7. gpg: aka "Sebastian Bergmann <sebastian.bergmann@thephp.cc>"
  8. gpg: aka "[jpeg image of size 40635]"
  9. gpg: WARNING: This key is not certified with a trusted signature!
  10. gpg: There is no indication that the signature belongs to the owner.
  11. Primary key fingerprint: D840 6D0D 8294 7747 2937 7831 4AA3 9408 6372 C20A

此时,签名已经没问题了,但是这个公钥还不能信任。签名没问题意味着文件未被篡改。可是由于公钥加密系统的性质,还需要再校验密钥 6372C20A 确实是由真正的 Sebastian Bergmann 创建的。

任何攻击者都能创建公钥并将其上传到公钥服务器。他们可以建立一个带恶意的发行包,并用这个假密钥进行签名。这样,如果尝试对这个损坏了的发行包进行签名校验,由于密钥是“真”密钥,校验将成功完成。因此,需要对这个密钥的真实性进行校验。如何对公钥的真实性进行校验已经超出了本文档的范畴。

有个比较谨慎的做法是创建一个脚本来管理 PHPUnit 的安装,在运行测试套件之前校验 GnuPG 签名。例如:

  1. #!/usr/bin/env bash
  2. clean=1 # 是否在测试完成之后删除 phpunit.phar ?
  3. aftercmd="php phpunit.phar --bootstrap bootstrap.php src/tests"
  4. gpg --fingerprint D8406D0D82947747293778314AA394086372C20A
  5. if [ $? -ne 0 ]; then
  6. echo -e "\033[33mDownloading PGP Public Key...\033[0m"
  7. gpg --recv-keys D8406D0D82947747293778314AA394086372C20A
  8. # Sebastian Bergmann <sb@sebastian-bergmann.de>
  9. gpg --fingerprint D8406D0D82947747293778314AA394086372C20A
  10. if [ $? -ne 0 ]; then
  11. echo -e "\033[31mCould not download PGP public key for verification\033[0m"
  12. exit
  13. fi
  14. fi
  15.  
  16. if [ "$clean" -eq 1 ]; then
  17. # 如果存在就清理掉
  18. if [ -f phpunit.phar ]; then
  19. rm -f phpunit.phar
  20. fi
  21. if [ -f phpunit.phar.asc ]; then
  22. rm -f phpunit.phar.asc
  23. fi
  24. fi
  25.  
  26. # 抓取最新的发行版和对应的签名
  27. if [ ! -f phpunit.phar ]; then
  28. wget https://phar.phpunit.de/phpunit.phar
  29. fi
  30. if [ ! -f phpunit.phar.asc ]; then
  31. wget https://phar.phpunit.de/phpunit.phar.asc
  32. fi
  33.  
  34. # 在运行前先校验
  35. gpg --verify phpunit.phar.asc phpunit.phar
  36. if [ $? -eq 0 ]; then
  37. echo
  38. echo -e "\033[33mBegin Unit Testing\033[0m"
  39. # 运行测试套件
  40. `$after_cmd`
  41. # 清理
  42. if [ "$clean" -eq 1 ]; then
  43. echo -e "\033[32mCleaning Up!\033[0m"
  44. rm -f phpunit.phar
  45. rm -f phpunit.phar.asc
  46. fi
  47. else
  48. echo
  49. chmod -x phpunit.phar
  50. mv phpunit.phar /tmp/bad-phpunit.phar
  51. mv phpunit.phar.asc /tmp/bad-phpunit.phar.asc
  52. echo -e "\033[31mSignature did not match! PHPUnit has been moved to /tmp/bad-phpunit.phar\033[0m"
  53. exit 1
  54. fi

Composer

如果用 Composer 来管理项目的依赖关系,只要在项目的 composer.json 文件中简单地加上对 phpunit/phpunit 的依赖关系即可:

  1. composer require --dev phpunit/phpunit ^6.5

可选的组件包

有以下可选组件包可用:

PHP_Invoker

一个工具类,可以用带有超时限制的方式调用可调用内容。当需要在严格模式下保证测试的超时限制时,这个组件包是必须的。

PHPUnit 的 PHAR 分发中已经包含了此组件包。可以用以下命令来经由 Composer 安装此组件包:


  1. composer require dev phpunit/php-invoker


DbUnit

移植到 PHP/PHPUnit 上的 DbUnit 用于提供对数据库交互测试的支持。

PHPUnit 的 PHAR 分发中已经包含了此组件包。可以用以下命令来经由 Composer 安装此组件包:


  1. composer require dev phpunit/dbunit


原文: https://phpunit.de/manual/6.5/zh_cn/installation.html