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

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

问题描述

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.

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?

解决方案

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

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.

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.

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.

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.

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);
}

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);
    }

Hope this helps.

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

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