我到处都读到它们有多棒,但由于某些原因,我似乎无法弄清楚我到底应该测试一些东西.有人可能会发布一段示例代码以及他们将如何测试它?如果不是太麻烦:)
有一个第三个"框架",它更容易学习 - 甚至比简单测试更容易,它被称为phpt.
可以在这里找到一本入门书:http: //qa.php.net/write-test.php
编辑:刚看到您的示例代码请求.
假设您在名为lib.php的文件中具有以下函数:
非常简单直接,返回您传入的参数.那么让我们看看这个函数的测试,我们将调用测试文件foo.phpt:
--TEST-- foo() function - A basic test to see if it works. :) --FILE-- --EXPECT-- string(11) "Hello World"
简而言之,我们提供$bar
带有值的参数,"Hello World"
以及var_dump()
函数调用的响应foo()
.
要运行此测试,请使用: pear run-test path/to/foo.phpt
这需要在您的系统上安装PEAR,这在大多数情况下非常常见.如果您需要安装它,我建议安装最新版本.如果您需要帮助进行设置,请随时询问(但提供操作系统等).
您可以使用两个框架进行单元测试.Simpletest和PHPUnit,我更喜欢.阅读有关如何在PHPUnit主页上编写和运行测试的教程.这很简单,也很好描述.
您可以通过更改编码样式来使单元测试更有效.
我建议浏览Google测试博客,特别是关于编写可测试代码的帖子.
我自己动手,因为我没有时间学习别人的做事方式,这需要大约20分钟的时间来写,10个以适应它在这里发布.
单元测试对我来说非常有用.
这有点长,但它解释了自己,底部有一个例子.
/** * Provides Assertions **/ class Assert { public static function AreEqual( $a, $b ) { if ( $a != $b ) { throw new Exception( 'Subjects are not equal.' ); } } } /** * Provides a loggable entity with information on a test and how it executed **/ class TestResult { protected $_testableInstance = null; protected $_isSuccess = false; public function getSuccess() { return $this->_isSuccess; } protected $_output = ''; public function getOutput() { return $_output; } public function setOutput( $value ) { $_output = $value; } protected $_test = null; public function getTest() { return $this->_test; } public function getName() { return $this->_test->getName(); } public function getComment() { return $this->ParseComment( $this->_test->getDocComment() ); } private function ParseComment( $comment ) { $lines = explode( "\n", $comment ); for( $i = 0; $i < count( $lines ); $i ++ ) { $lines[$i] = trim( $lines[ $i ] ); } return implode( "\n", $lines ); } protected $_exception = null; public function getException() { return $this->_exception; } static public function CreateFailure( Testable $object, ReflectionMethod $test, Exception $exception ) { $result = new self(); $result->_isSuccess = false; $result->testableInstance = $object; $result->_test = $test; $result->_exception = $exception; return $result; } static public function CreateSuccess( Testable $object, ReflectionMethod $test ) { $result = new self(); $result->_isSuccess = true; $result->testableInstance = $object; $result->_test = $test; return $result; } } /** * Provides a base class to derive tests from **/ abstract class Testable { protected $test_log = array(); /** * Logs the result of a test. keeps track of results for later inspection, Overridable to log elsewhere. **/ protected function Log( TestResult $result ) { $this->test_log[] = $result; printf( "Test: %s was a %s %s\n" ,$result->getName() ,$result->getSuccess() ? 'success' : 'failure' ,$result->getSuccess() ? '' : sprintf( "\n%s (lines:%d-%d; file:%s)" ,$result->getComment() ,$result->getTest()->getStartLine() ,$result->getTest()->getEndLine() ,$result->getTest()->getFileName() ) ); } final public function RunTests() { $class = new ReflectionClass( $this ); foreach( $class->GetMethods() as $method ) { $methodname = $method->getName(); if ( strlen( $methodname ) > 4 && substr( $methodname, 0, 4 ) == 'Test' ) { ob_start(); try { $this->$methodname(); $result = TestResult::CreateSuccess( $this, $method ); } catch( Exception $ex ) { $result = TestResult::CreateFailure( $this, $method, $ex ); } $output = ob_get_clean(); $result->setOutput( $output ); $this->Log( $result ); } } } } /** * a simple Test suite with two tests **/ class MyTest extends Testable { /** * This test is designed to fail **/ public function TestOne() { Assert::AreEqual( 1, 2 ); } /** * This test is designed to succeed **/ public function TestTwo() { Assert::AreEqual( 1, 1 ); } } // this is how to use it. $test = new MyTest(); $test->RunTests();
这输出:
Test: TestOne was a failure /** * This test is designed to fail **/ (lines:149-152; file:/Users/kris/Desktop/Testable.php) Test: TestTwo was a success
获取PHPUnit.这是非常容易使用.
然后从非常简单的断言开始.在进入其他任何事情之前,您可以使用AssertEquals进行大量操作.这是让你的脚湿润的好方法.
您可能还想先尝试编写测试(因为您提出了TDD标记的问题),然后编写代码.如果你没有这样做之前它是一个大开眼界.
require_once 'ClassYouWantToTest'; require_once 'PHPUnit...blah,blah,whatever'; class ClassYouWantToTest extends PHPUnit...blah,blah,whatever { private $ClassYouWantToTest; protected function setUp () { parent::setUp(); $this->ClassYouWantToTest = new ClassYouWantToTest(/* parameters */); } protected function tearDown () { $this->ClassYouWantToTest = null; parent::tearDown(); } public function __construct () { // not really needed } /** * Tests ClassYouWantToTest->methodFoo() */ public function testMethodFoo () { $this->assertEquals( $this->ClassYouWantToTest->methodFoo('putValueOfParamHere), 'expectedOutputHere); /** * Tests ClassYouWantToTest->methodBar() */ public function testMethodFoo () { $this->assertEquals( $this->ClassYouWantToTest->methodBar('putValueOfParamHere), 'expectedOutputHere); }
对于简单的测试和文档,php-doctest相当不错,这是一个非常简单的入门方式,因为您不必打开单独的文件.想象一下下面的功能:
/**
* Sums 2 numbers
*
* //doctest: add
* echo add(5,2);
* //expects:
* 7
*
*/
function add($a,$b){
return $a + $b;
}
如果您现在通过phpdt(php-doctest的命令行运行程序)运行此文件,将运行1个测试.doctest包含在块中.Doctest起源于python,可以提供关于代码如何工作的有用且可运行的示例.你不能完全使用它,因为代码本身会乱丢测试用例,但我发现它与更正式的tdd库一起使用 - 我使用phpunit.
这第一次的答案在这里概括起来很好(这不是单元VS文档测试).