其实一开始我内心是想做单元测试(unit testing)的,但时间久了,也不想了。
  要想通过PHP编程成为技术领域的专家,其实功夫在PHP之外。数据库至少得看几本书,xml至少得看一本书,单元测试至少得看一本书,软件工程至少看一本,数据结构与算法至少看一本,*nix至少得看一本,Web服务器至少看一本,佛经得看一本,道德经得看一本,易经可能也得看一本,等等,不停的看下去。
  概念
  要写单元测试,必须要有一些基本概念。这些概念PHP是不会教给你的。
  我们先从百度百科中吸取一点营养。
  工厂在组装一台电视机之前,会对每个元件都进行测试,这是单元测试。
  单元测试,是指对软件中的小可测试单元进行检查和验证。对于单元测试中单元的含义,一般来说,要根据实际情况去判定其具体含义,如C语言中单元指一个函数,Java里单元指一个类,图形化的软件中可以指一个窗口或一个菜单等。总的来说,单元是人为规定的小的被测功能模块。单元测试是在软件开发过程中要进行的低级别的测试活动,软件的独立单元将在与程序的其他部分相隔离的情况下进行测试。
  单元测试是由程序员自己来完成,终受益的也是程序员自己。程序员有责任编写功能代码,同时也有责任为自己的代码编写单元测试。执行单元测试,是为了证明这段代码的行为和我们期望的一致。
  --百度百科
  安装
  PHPUnit目前稳定版已到了4.6,网上很多的姿势都已失效。比如,发行方式,以前都是用Pear进行安装,现在呢,直接是Phar包或者Composer的方式依赖安装。
  wget https://phar.phpunit.de/phpunit.phar
  ? chmod +x phpunit.phar
  ? sudo mv phpunit.phar /usr/local/bin/phpunit
  ? phpunit --version
  {
  "require-dev": {
  "phpunit/phpunit": "4.6.*"
  }
  }
  但另一个对初学者很关键的东东phpunit-skelgen没有包含在这个包里,而且很难找到下载地址:https://phar.phpunit.de/phpunit-skelgen.phar
  wget https://phar.phpunit.de/phpunit-skelgen.phar
  chmod +x phpunit-skelgen.phar
  mv phpunit-skelgen.phar /usr/local/bin/phpunit-skelgen
  解决的问题
  在开发过程中,当需要对软件的内部结构进行更改时,你实际上是要在不影响其可见行为的情况下让它更加容易理解、更加易于修改,测试套件对于安全地进行这些所谓的重构而言是非常宝贵的。否则,你可能在重组过程中将系统搞坏而不自知。
  在使用单元测试来确认重构的转换步骤中确实保持原有行为并且没有引入错误时,以下情况有助于改进项目的编码与设计:
  所有单元测试均正确运行。
  代码传达其设计原则。
  代码没有冗余。
  代码所包含的类和方法的数量降至低。
  当需要向系统内添加新的功能时,首先为其编写测试。然后,当测试能够正常运行标志着开发完成了。
  优点
  1、它是一种验证行为。
  程序中的每一项功能都是测试来验证它的正确性。它为以后的开发提供支援。算是开发后期,我们也可以轻松的增加功能或更改程序结构,而不用担心这个过程中会破坏重要的东西。而且它为代码的重构提供了保障。这样,我们可以更自由的对程序进行改进。
  2、它是一种设计行为。
  编写单元测试将使我们从调用者观察、思考。特别是先写测试(test-first),迫使我们把程序设计成易于调用和可测试的,即迫使我们解除软件中的耦合。
  3、它是一种编写文档的行为。
  单元测试是一种无价的文档,它是展示函数或类如何使用的佳文档。这份文档是可编译、可运行的,并且它保持新,永远与代码同步。
  4、它具有回归性。
  自动化的单元测试避免了代码出现回归,编写完成之后,可以随时随地的快速运行测试。
  实践
  什么时候测试?
  单元测试越早越好,早到什么程度?
  极限编程(Extreme Programming,或简称XP)讲究TDD,即测试驱动开发,先编写测试代码,再进行开发。在实际的工作中,可以不必过分强调先什么后什么,重要的是高效和感觉舒适。
  从经验来看,先编写产品函数的框架,然后编写测试函数,针对产品函数的功能编写测试用例,然后编写产品函数的代码,每写一个功能点都运行测试,随时补充测试用例。
  所谓先编写产品函数的框架,是指先编写函数空的实现,有返回值的直接返回一个合适值,编译通过后再编写测试代码,这时,函数名、参数表、返回类型都应该确定下来了,所编写的测试代码以后需修改的可能性比较小。
  由谁测试?
  单元测试与其他测试不同,单元测试可看作是编码工作的一部分,应该由程序员完成,也是说,经过了单元测试的代码才是已完成的代码,提交产品代码时也要同时提交测试代码。测试部门可以作一定程度的审核。
  请一定要看完官方文档:。
  要进行充分的单元测试,一般来说应专门编写测试代码,并与产品代码隔离。但对于初学者来说,总是会有点别扭,因为感觉额外做了很多工作,影响开发效率。其实像phpunit也是支持在类方法的文档注释块(docblock)中使用 @test 标注将其标记为测试方法的。这样,彻底贯彻我们代码即文档的思想。
  <?php
  class Calculator
  {
  /**
  * @assert (0, 0) == 0
  * @assert (0, 1) == 1
  * @assert (1, 0) == 1
  * @assert (1, 1) == 2
  * @assert (1, 2) == 4
  */
  public function add($a, $b)
  {
  return $a + $b;
  }
  }
  现实难题
  我们到底要测什么?算法?一般很少。
  大都是在编写业务功能。而且大多数是基于数据库的系统开发。这是我们实施PHP单元测试大的难点所在。需要整合PHPUnit的DBUnit测试,也是一开始得学习DBUnit的知识。
  在各种编程语言中,许多入门与中级的单元测试范例都暗示着这样一种信息:很容易用简单的测试来对应用程序的逻辑进行测试。但是对于以数据库为中心的应用程序而言,这与现实相去甚远。一旦开始使用诸如 Wordpress、TYPO3、或 Symfony(配合 Doctrine 或 Propel)之类的东西,很容易在用 PHPUnit 时碰到超多问题:正是由于这些库和数据库之间实在耦合的太紧密了。
  你大概会在日常工作面对的项目中经历这一幕。你打算把你那或生疏或纯熟的 PHPUnit 技能用到工作中去,结果被以下问题之一卡住了:
  待测方法执行了一个相当大的 JOIN 操作,并且得到的数据用于计算某些重要的结果。
  业务逻辑中混合执行了 SELECT、INSERT、UPDATE 和 DELETE 语句。
  为了给待测方法建立合理的初始数据,需要在两个以上(可能远超过)表里设置测试数据。