何为单元测试:

指对软件中的基本单元进行测试,如函数、方法等,以检查其返回值或行为是否符合预期;实际中软件是很复杂的,由许多组件构成,执行流程连贯在一起,要进行单元片段的测试,就需要为其提供执行上下文(或者说参数)和环境(比如打桩模拟一些对象)来运行,并监控其行为和返回值,为此我们就需要写出做这件事情的程序代码,这样的代码叫做测试用例,许多测试用例有机结合在一起形成一个整体的测试,又叫做测试套件,被测试的程序代码叫做生产代码。phpunit这个软件就是用来帮助我们写测试用例并进行测试的。

php的单元测试:phpunit

在其官网有详细教程,这里介绍一些补充内容。
首先要明白phpunit软件本身就是由php语言实现,其使用是通过命令行进行的,并不是通过浏览器访问
明白这一点很重要,许多新人被卡在这里。很基础也很简单,但似乎没怎么被提及

想试一下单元测试很久了,但是一直没有合适的项目,而且中文网络上的PHPUnit教程要么太旧,要么太乱,所以总也没学会。最近准备把手头的项目重构一下,决定开始使用PHPUnit做单元测试,先照着PHPUnit的官网做了一下Tutorial,虽然已经很简单了,仍然被卡住几次,所以写篇文章记录一下。因为对PHP的包管理系统不熟悉,这篇文章会从安装开始。


1.安装

PHPUnit如果使用PHAR安装的话很简单。Phar归档就像Java的Jar,可以直接被PHP解释器执行。在*nix系统下,可以执行下面三条命令:

➜ wget https://phar.phpunit.de/phpunit.phar
➜ chmod +x phpunit.phar
➜ sudo mv phpunit.phar /usr/local/bin/phpunit

考虑到这次的重构会引入比较多类库,我选择了Composer做依赖管理。我在Windows上试过PhpStorm里的Composer,总是失败,感觉是网络不好的原因。这次在Ubuntu下安装很顺利,全局安装Composer之后,在命令行执行

composer global require phpunit/phpunit

全局安装PHPUnit。然后在 ~/.bashrc 文件末尾加一行 PATH=$PATH:/home/feng/.composer/vendor/bin(注意替换用户名),来将Composer的global bin目录加入PATH。

安装过后运行 phpunit --version看到版本信息则说明安装成功。

另外,装完以后我发现Ubuntu系统可以使用 apt-get install phpunit来安装,但我没有试过。

在Windows下我用的是XAMPP环境,其中已经内置PHPUnit了。如果要在命令提示符下使用的话,可以修改环境变量中的PATH,在里面加上 C:\xampp\php(或者你修改后的路径)。再打开命令提示符,运行phpunit --version看一下。


2.第一个测试

第一个Tutorial我使用的是PHPUnit官网上的Getting Started,这里写的比它还要简单一点。

项目的目录结构如下:


├── phpunit.xml
├── src
│ ├── autoload.php
│ └── Money.php
└── tests
└── MoneyTest.php

第一个文件是项目代码src/Money.php,内容如下:

<?php

class Money
{
private $amount; public function __construct($amount)
{
$this->amount = $amount;
} public function getAmount()
{
return $this->amount;
} public function negate()
{
return new Money(-1*$this->amount);
}
}

与之对应的单元测试是tests目录下的MoneyTest.php,注意单元测试文件名最好是*Test.php,这样以后指定tests目录便可以执行目录下的所有测试。

<?php

class MoneyTest extends PHPUnit_Framework_TestCase
{
public function testCanBeNegated()
{
$a = new Money(1); $b = $a->negate(); $this->assertEquals(-1, $b->getAmount());
}
}

代码很简单,$this->assertEquals(-1, $b->getAmount());即断言后一个参数的执行结果与前一个参数相等,其他不解释了。

现在,如果在MoneyTest.php里加一行include_once('../src/Money.php');。然后在项目根目录下执行phpunit tests/MoneyTest,就可以看到执行结果了。


3.自动载入

但是,逐个添加include的方式太不方便,最好是能自动include所需的文件,PHPUnit提供了一个参数--bootstrap,可以使用项目的autoload文件。这里我自己写了一个最简单的autoload.php,只要4行。这个文件并不是PHPUnit专用的,应该放在src目录下。

<?php

function __autoload($class){
include $class.'.php';
} spl_autoload_register('__autoload');

当需要Money类时,就去include Money.php。写完__autoload()函数之后要用spl_autoload_register()注册上。

现在就可以去掉MoneyTest.php中的include语句,使用phpunit --bootstrap src/autoload.php tests/MoneyTest来执行测试了。

虽然可以自动载入,但是要执行的命令更长了。我们还可以写一个配置文件来为项目指定bootstrap,这样就不用每次都写在命令里了。

配置文件phpunit.xml放在项目根目录下。

<phpunit bootstrap="src/autoload.php">
</phpunit>

如果要执行MoneyTest,在项目根目录下执行:phpunit tests/MoneyTest
如果要执行tests目录下的所有测试,在项目根目录下执行:phpunit tests


Reference:

  1. Getting Started with PHPUnit – The PHP Testing Framework
  2. PHP: spl_autoload_register - Manual
  3. PHPUnit Bootstrap and Autoloading classes - Jess Telford
  4. Composer

标签: none

你可能会疑惑,上面的php代码是怎么回事呢?

那就是一个测试用例,简单的测试了一个数组操作,进行单元测试一般通过以下四步:

1. 针对生产代码类 Class 的测试写在类 ClassTest中。
2. ClassTest(通常)继承自 PHPUnit\Framework\TestCase。
3. 测试都是命名为 test* 的公用方法。也可以在方法的文档注释块(docblock)中使用 @test 标注将其标记为测试方法。
4. 在测试方法内,类似于 assertEquals()这样的断言方法用来对实际值与预期值的匹配做出断言判断。

这里你可能会有几个地方迷惑:

1、在注释块中使用的标注,php可以通过反射得到,程序可以利用得到的信息进行配置
2、上列中测试用例代码里面的TestCase类来自哪里?并没有被加载啊?
上文提到phpunit本身是用php语言写成的,打包成了phar供使用,phar是可执行的,执行时首先执行包里面的存根文件stub
你可以按照上文云客的另外一篇phar帖子介绍的方法提取还原phpunit.phar包,或者使用phpstorm这样的ide直接打开
在.phar/stub.php里你将看到存根代码,TestCase类就是在存根代码里面require的
“phpunit yunke”这条命令行代码将首先运行phpunit脚本,从存根文件开始执行,然后由phpunit加载测试用例代码
可以看出程序并不是从测试用例脚本开始执行的,现在明白TestCase类哪里来的了吧

通过以上内容再配合官网文档,新手应该可以顺利入门了

开始使用PHPUnit单元测试的更多相关文章

  1. 第一次工作->笔记:在phpstrom2019上搭建phpunit单元测试环境,php环境使用docker

    前言:公司大佬让我开发一个工具,并合并到他的工具包中,使用的是github 说明:这里的php环境使用的是laradock.感兴趣的道友自行查找. 工具:php.phpstrom.phpunit.do ...

  2. PHPUnit单元测试中类protected/private方法测试

    这里首先有一个问题要考虑的是,这类方法是否要被测试? 理论上,这类方法都会被其它public类型的方法调用,只要对那些public的方法做充分的测试,就可以保证这些方法的可靠性,就没有必要再测了.好像 ...

  3. PHPUnit单元测试的简单使用

    何为单元测试: 指对软件中的基本单元进行测试,如函数.方法等,以检查其返回值或行为是否符合预期:实际中软件是很复杂的,由许多组件构成,执行流程连贯在一起,要进行单元片段的测试,就需要为其提供执行上下文 ...

  4. PHPUnit单元测试

    单元测试 PHPUnit <?php /** * 定义一个用来被测试的类RemoteConnect * @author json * */ class RemoteConnect{ public ...

  5. 基于Netbeans的PHPUnit单元测试环境搭建

    一.配置 PHPUnit截至2015-10-16,稳定版已更新至5.0.6,要求使用PHP v5.6及以上的环境才能使用. PHPUnit的4.8系列要求在PHP v5.3.3以上环境使用. Netb ...

  6. PHPUNIT 单元测试

    在windows上的安装可以参考其手册 首先下载phpunit.phar文件 1. 为php的二进制可执行文件建立 一个目录,如C:\bin 2. 将C:\bin添加到系统环境变量中, 3. 打开命令 ...

  7. Lumen开发:phpunit单元测试

    先来直接运行,cmd先进入根目录,然后进入tests或是test文件夹 运行命令行:..\vendor\bin\phpunit ExampleTest.php laravel/lumen中集成了PHP ...

  8. phpunit 单元测试框架-代码覆盖率

    "phpize not found" 的解决办法: apt-get install php5-dev http://jeffreysambells.com/2010/04/08/r ...

  9. PHPUnit 单元测试教程

    一.官网下载对应 PHP 版本的代码库 https://phpunit.de/getting-started-with-phpunit.html 二.安装 PHPUnit 官网提供了两种方法安装 1. ...

随机推荐

  1. 如何完成域名和ip地址的绑定

    首先,我们要知道什么是域名绑定,所谓域名绑定就是是指已选定的域名与服务器主机的空间绑定,实在是在域名注册查询上设置或者WEB服务器上设置,使一个域名被指导向一特定空间,从而使访问者访问你的域名的时候就 ...

  2. dedecms后台系统基本参数标题

    1,站点设置 2,核心设置 3,附件设置 4,会员设置 6,性能选项 7,其它选项 8,模块设置 在E:\wamp\www\dededln\back\inc\configgroup.txt

  3. Eclipse版本

    Eclipse  3.1  IO 木卫一,伊奥                       2005Eclipse  3.2  Callisto 木卫四,卡里斯托        2006Eclipse ...

  4. 修改ncnn的openmp异步处理方法 附C++样例代码

    ncnn刚发布不久,博主在ios下尝试编译. 遇上了openmp的编译问题. 寻找各种解决方案无果,亲自操刀. 采用std::thread 替换 openmp. ncnn项目地址: https://g ...

  5. TCP三次握手机制中的seq和ack

    TCP连接的三次握手:第一次(A--->B),SYN=1,seq=x第二次(B--->A),SYN=1,ACK=1,seq=y,ack=x+1 第三次(A--->B),ACK=1,s ...

  6. php实现监控在线服务应用程序小栗子

    下面我就给大家举个栗子(例子) 某单位需要实现监控服务器状态,和监控服务器应用网站,还有需要监控服务器的中间件,数据库状态监控.听到这个任务是不是恨透头疼,这想起来是不是头疼.还好有系统可用,但是我现 ...

  7. vs Code 运行一个本地WEB服务器

    VS Code作为前端开发工具,值得推荐,用上之后,爱不释手 当我们建立一个全静态的前端项目时,如果需要将整个项目运行起来也非常简单,两步即可: 1.安装npm install -g live-ser ...

  8. linux ngix安装

    因为我完全按照第一篇参考文章从上到下一步步安装导致有些安装失败最后重装的,过程有点乱,就没自己总结please read the follow articles Linux 安装Nginx详细图解教程 ...

  9. php中HTTP_X_FORWARDED_FOR 和 REMOTE_ADDR的使用

    1.REMOTE_ADDR:浏览当前页面的用户计算机的ip地址2.HTTP_X_FORWARDED_FOR: 浏览当前页面的用户计算机的网关3.HTTP_CLIENT_IP:客户端的ip 在PHP 中 ...

  10. jspf与jsp的区别

    如果想把一个jspf的文件引入(incurred)到一个jsp页面中,只能使用"@include"指令引入 如果使用<jsp:include>引入,jspf文件中的内容 ...