如何使用过程代码库在PHP中编写单元测试? [英] How do I write unit tests in PHP with a procedural codebase?

查看:93
本文介绍了如何使用过程代码库在PHP中编写单元测试?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对单元测试的好处深信不疑,我想开始将这一概念应用到以PHP编写的大量现有代码库中.不到10%的代码是面向对象的.

I'm mostly convinced of the benefits of unit testing, and I would like to start applying the concept to a large existing codebase written in PHP. Less than 10% of this code is object-oriented.

我研究了几个单元测试框架(PHPUnit,SimpleTest和phpt).但是,我还没有找到测试过程代码的任何示例.什么是最适合我的情况的框架?是否有使用非OOP代码进行PHP单元测试的示例?

I've looked at several unit testing frameworks (PHPUnit, SimpleTest, and phpt). However, I haven't found examples for any of these that test procedural code. What's the best framework for my situation and are there any examples of unit testing PHP using non-OOP code?

推荐答案

您可以对程序PHP进行单元测试,没问题.而且,如果您的代码与HTML混合在一起,那么您绝对不会碰运气.

You can unit-test procedural PHP, no problem. And you're definitely not out of luck if your code is mixed in with HTML.

在应用程序或验收测试级别,您的过程PHP可能取决于超全局变量($_POST, $_GET, $_COOKIE等)的值来确定行为,最后以包含模板文件并吐出输出为结束.

At the application or acceptance test level, your procedural PHP probably depends on the value of the superglobals ($_POST, $_GET, $_COOKIE, etc.) to determine behavior, and ends by including a template file and spitting out the output.

要进行应用程序级测试,您只需设置超全局值即可;启动输出缓冲区(以防止一堆html淹没您的屏幕);呼叫页面;断言缓冲区中的内容;并在最后丢弃缓冲区. 因此,您可以执行以下操作:

To do application-level testing, you can just set the superglobal values; start an output buffer (to keep a bunch of html from flooding your screen); call the page; assert against stuff inside the buffer; and trash the buffer at the end. So, you could do something like this:

public function setUp()
{
    if (isset($_POST['foo'])) {
        unset($_POST['foo']);
    }
}

public function testSomeKindOfAcceptanceTest()
{
    $_POST['foo'] = 'bar';
    ob_start();
    include('fileToTest.php');
    $output = ob_get_flush();
    $this->assertContains($someExpectedString, $output);
}

即使对于包含许多包含项的巨大框架",此类测试也将告诉您是否具有应用程序级功能正常运行.当您开始改进代码时,这将非常重要,因为即使您确信数据库连接器仍然可以正常工作并且看起来比以前更好,您仍然需要单击一个按钮,看看,是的,您仍然可以通过数据库登录和注销.

Even for enormous "frameworks" with lots of includes, this kind of testing will tell you if you have application-level features working or not. This is going to be really important as you start improving your code, because even if you're convinced that the database connector still works and looks better than before, you'll want to click a button and see that, yes, you can still login and logout through the database.

在较低级别上,根据变量范围以及函数是通过副作用(返回true还是false)起作用,还是直接返回结果,这些变化很小.

At lower levels, there are minor variations depending on variable scope and whether functions work by side-effects (returning true or false), or return the result directly.

变量是否作为函数之间的参数或参数数组显式传递?还是将变量设置在许多不同的地方,然后隐式地作为全局变量传递?如果是(好的)显式情况,则可以通过以下方式对功能进行单元测试:(1)包括保存该功能的文件,然后(2)直接提供功能测试值,以及(3)捕获输出并对其断言.如果您使用的是全局变量,则只需格外小心(如上所述,在$ _POST示例中),以谨慎地消除测试之间的所有全局变量.在处理推入和拉入大量globals的函数时,使测试保持很小(5-10行,1-2断言)也特别有用.

Are variables passed around explicitly, as parameters or arrays of parameters between functions? Or are variables set in many different places, and passed implicitly as globals? If it's the (good) explicit case, you can unit test a function by (1) including the file holding the function, then (2) feeding the function test values directly, and (3) capturing the output and asserting against it. If you're using globals, you just have to be extra careful (as above, in the $_POST example) to carefully null out all the globals between tests. It's also especially helpful to keep tests very small (5-10 lines, 1-2 asserts) when dealing with a function that pushes and pulls lots of globals.

另一个基本问题是函数是通过返回输出还是通过更改传入的参数(返回true/false)来工作.在第一种情况下,测试更容易,但在两种情况下都可以:

Another basic issue is whether the functions work by returning the output, or by altering the params passed in, returning true/false instead. In the first case, testing is easier, but again, it's possible in both cases:

// assuming you required the file of interest at the top of the test file
public function testShouldConcatenateTwoStringsAndReturnResult()
{
  $stringOne = 'foo';
  $stringTwo = 'bar';
  $expectedOutput = 'foobar';
  $output = myCustomCatFunction($stringOne, $stringTwo);
  $this->assertEquals($expectedOutput, $output);
}

在最坏的情况下,您的代码受副作用影响并返回true或false,您仍然可以轻松进行测试:

In the bad case, where your code works by side-effects and returns true or false, you still can test pretty easily:

/* suppose your cat function stupidly 
 * overwrites the first parameter
 * with the result of concatenation, 
 * as an admittedly contrived example 
 */
public function testShouldConcatenateTwoStringsAndReturnTrue()
    {
      $stringOne = 'foo';
      $stringTwo = 'bar';
      $expectedOutput = 'foobar';
      $output = myCustomCatFunction($stringOne, $stringTwo);
      $this->assertTrue($output);
      $this->Equals($expectedOutput, $stringOne);
    }

希望这会有所帮助.

这篇关于如何使用过程代码库在PHP中编写单元测试?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆