phpUnit初学者

Qua*_*mis 3 php testing phpunit

我是如何开始使用phpUnit作为我已经制作的一堆函数和类的测试框架?


编辑:是的,我已经阅读了文档.基本上我在遵循BankAccount示例时尝试过测试.但我得到错误:

Warning: require_once(PHP/CodeCoverage/Filter.php) [function.require-once]: failed to open stream: No such file or directory in [...]/unitTest/phpunit.php on line 38.

此外,php脚本似乎从#!/usr/bin/env php表示它们应该从控制台运行开始.我宁愿从浏览器运行这些...

假设我有一个f1()返回字符串的函数.应该如何进行测试?我错过了什么吗?

Wou*_*elo 10

简要介绍测试框架

PHPUnit提供了一个简单的框架,用于创建测试套件以自动测试函数和类.PHPUnit的灵感来自JUnit,它由Kent Beck和Erich Gamma创建,作为极限编程的工具.XP的一个规则是尽可能经常地尽早测试小型软件组件,这样您就不必在设置和测试依赖于类的大型应用程序时修复API中的错误和错误.虽然单元测试是XP中的基本规则之一,但您不必切换到XP以从PHPUnit中受益.PHPUnit是一个测试类或一组函数的好工具,可以简化开发周期并帮助您避免无休止的调试会话.

工作常规

通常,你会写一个类,使用echo()或做一些非系统的测试var_dump().在此之后,您在应用程序中使用该类,并希望一切正常.要从PHPUnit中受益,您应该重新考虑这个流程.最好的方法是这样做:

  1. 设计你的类/ API
  2. 创建一个测试套件
  3. 实现类/ API
  4. 运行测试套件
  5. 修复失败或错误并再次转到#4

看起来这可能需要很多时间,但这种印象是错误的.使用PHPUnit创建测试套件只需几分钟,并且只运行测试套件几秒钟.

设计一个班级

让我们从一个小例子开始:一个字符串类.首先,我们创建一组函数声明来处理字符串:

---- string.php ----

<?php
class String
{
    //contains the internal data
    var $data;

    // constructor
    function String($data) {
        $this->data = $data;
    }

    // creates a deep copy of the string object
    function copy() {
    }

    // adds another string object to this class
    function add($string) {
    }

    // returns the formated string
    function toString($format) {
    }
}
?>
Run Code Online (Sandbox Code Playgroud)

创建测试套件

现在我们可以创建一个测试套件,它检查字符串类的每个函数.测试套件是从PHPUnit_TestCase继承的普通PHP类,包含测试函数,由函数名中的前导'test'标识.在测试函数中,必须将期望值与要测试的函数的结果进行比较.此比较的结果必须委托给函数,该函数assert*()-family决定函数是否通过测试.

---- testcase.php ----

<?php

require_once 'string.php';
require_once 'PHPUnit.php';

class StringTest extends PHPUnit_TestCase
{
    // contains the object handle of the string class
    var $abc;

    // constructor of the test suite
    function StringTest($name) {
       $this->PHPUnit_TestCase($name);
    }

    // called before the test functions will be executed
    // this function is defined in PHPUnit_TestCase and overwritten
    // here
    function setUp() {
        // create a new instance of String with the
        // string 'abc'
        $this->abc = new String("abc");
    }

    // called after the test functions are executed
    // this function is defined in PHPUnit_TestCase and overwritten
    // here
    function tearDown() {
        // delete your instance
        unset($this->abc);
    }

    // test the toString function
    function testToString() {
        $result = $this->abc->toString('contains %s');
        $expected = 'contains abc';
        $this->assertTrue($result == $expected);
    }

    // test the copy function
    function testCopy() {
      $abc2 = $this->abc->copy();
      $this->assertEquals($abc2, $this->abc);
    }

    // test the add function
    function testAdd() {
        $abc2 = new String('123');
        $this->abc->add($abc2);
        $result = $this->abc->toString("%s");
        $expected = "abc123";
        $this->assertTrue($result == $expected);
    }
  }
?>
Run Code Online (Sandbox Code Playgroud)

第一次试运行

现在,我们可以进行第一次测试.确保所有路径都正确,然后执行此PHP程序.

---- stringtest.php ----

<?php

require_once 'testcase.php';
require_once 'PHPUnit.php';

$suite  = new PHPUnit_TestSuite("StringTest");
$result = PHPUnit::run($suite);

echo $result -> toString();
?>
Run Code Online (Sandbox Code Playgroud)

如果从命令行调用此脚本,您将获得以下输出:

TestCase stringtest->testtostring() failed: expected true, actual false
TestCase stringtest->testcopy() failed: expected , actual Object
TestCase stringtest->testadd() failed: expected true, actual false
Run Code Online (Sandbox Code Playgroud)

每个函数都没有通过测试,因为你的字符串函数没有返回我们定义为期望值的函数.

如果要通过浏览器调用脚本,则必须将脚本放在正确的html页面中,$result->toHTML()而不是调用$result->toString().

履行

好的,让我们从我们的字符串类的实现开始.

---- string.php ----

<?php
class String
{
    //contains the internal data
    var $data;

    // constructor
    function String($data) {
        $this->data = $data;
    }

    // creates a deep copy of the string object
    function copy() {
        $ret = new String($this->data);
        return $ret;
    }

    // adds another string object to this class
    function add($string) {
        $this->data = $this->data.$string->toString("%ss");
    }

    // returns the formated string
    function toString($format) {
        $ret = sprintf($format, $this->data);
        return $ret;
    }
}
?>
Run Code Online (Sandbox Code Playgroud)

实现完成后我们可以再次运行测试:

~>
php -f stringtest.php

TestCase stringtest->testtostring() passed
TestCase stringtest->testcopy() passed
TestCase stringtest->testadd() failed: expected true, actual false
Run Code Online (Sandbox Code Playgroud)

D'哦!最后一次测试失败了!我们犯了打字错误.将string.php中的第16行更改为

<?php
$this->data = $this->data.$string->toString("%s");
?> 
Run Code Online (Sandbox Code Playgroud)

并再次运行测试:

~>
php -f stringtest.php

TestCase stringtest->testtostring() passed
TestCase stringtest->testcopy() passed
TestCase stringtest->testadd() passed
Run Code Online (Sandbox Code Playgroud)

一切都好了!

结论

测试三个简单函数似乎有很多工作吗?不要忘记,这是一个小例子.考虑更大,更复杂的API,如商店应用程序中的数据库抽象或篮子类.PHPUnit是一个很好的工具,用于检测类实现中的错误.

通常,您需要重新实现或重构在几个不同应用程序中使用的大类.没有测试套件,你在其中一个依赖于你的类的应用程序中破坏某些东西的可能性非常高.感谢单元测试,您可以为您的类创建一个测试套件,然后重新实现您的类,并确保只要新类通过测试,依赖于类的应用程序将起作用.

使用来源:http://pear.php.net

  • 为什么要复制手册的很大一部分?仅仅链接到相关文本还不够吗?吴 (2认同)