测试程序代码

时间:2011-12-13 16:06:04

标签: php tdd

我们90%的代码都是线性的。我们在某些地方散布了各种功能,但我们的代码通常如下所示:

<?php

// gather some data
// do something with that data
// instantiate a bunch of globals

// output a bunch of stuff to the browser

include_once "file.php";

// output some more stuff
include_once "file2.php";

// ad nauseum

然后在file.php

<?php

// do something with the globals from above
// gather some more data
// do something with this newfound data
// output more stuff to the browser

作为迁移到更干净的代码库的一部分,我想开始测试这个,但我不确定正确的方法来做到这一点。有什么建议?我对正确的方法感到茫然。

6 个答案:

答案 0 :(得分:4)

正如其他人所评论的那样,你基本上编写了程序代码。这类代码通常不太有利于单元测试或测试驱动开发。首先,您应该熟悉面向对象编程,并开始将相关的功能分组到适当的抽象中。

你可以尝试寻找Link Seams和其他类似的技巧,但除非你开始改变范式,否则你可能会陷入伤害的世界。除非您可以将过程PHP分解为具有设置输入和输出点的足够小的文件,否则您可以单独测试每个文件。但这肯定需要创建方法并消除尽可能多的GLOBALS。

您需要做的第一件事可能是阅读Michael Feathers的第19章Working Effectively with Legacy Code。事实上,阅读整本书。因为添加测试的“看似简单的位”需要进行范式转换。

答案 1 :(得分:1)

研究员, 虽然我同意使用Selenium等...我想指出这一点: 我们正在谈论TDD。 在我不起眼的经历中,TDD就像流感一样。 首先,必须掌握面向对象的编程,然后必须学习单元测试。

我将称之为单元测试:“测试之后”......从设计的角度来看,测试之后有点愚蠢,它将帮助您了解必须从单元测试切换到单元测试面向对象分析和设计的中心。

此时,您将开始TDD。

我很伤心地说,但除非你是一个惊人忠实的人,我相信你正在寻找一个几年来得到这一切的把握......我很慷慨。

请不要将此解释为对您的角色或技能组合轻微......但作为程序员(使用源代码支付账单)和实现工艺并不容易,因为它有时会与业务目标相冲突。

简而言之,根据您组织的业务模式,您可能会或可能不会获得足够的时间安排。但你必须按下。

不要害怕,因为通过坚持不懈,你有一天能够向下一个试图进入TDD的年轻人或女士解释这件事。

快乐的编码。

答案 2 :(得分:0)

Extract MethodExtract Class重构。注释是提示,告诉您如何命名这些方法/类。

有关测试框架,请参阅:http://en.wikipedia.org/wiki/List_of_unit_testing_frameworks#PHP

答案 3 :(得分:0)

TDD意味着测试首先出现。您不需要测试现有代码,您必须测试新代码。毕竟它是单元测试 - 它测试一段代码而不是整页。为了确保一切都像重构之前一样,你需要编写另一种类型的测试 - 功能测试。基本上模拟HTTP请求并检查响应。例如,可以使用selenium构建此类测试,并且像symfony这样的一些PHP框架为此提供了自己的服务器端测试框架。

答案 4 :(得分:0)

我不羡慕你。我一直在你身边(现在仍然是!)而且它不是一个好地方。如果没有完全重写代码库,那么这将不是一条简单的道路。理想情况下,您需要重构以使您的代码得到测试,但理想情况下您应该在重构之前测试您的代码 - Catch 22.如果您有大量功能,您可以使用其中一个可用的测试来测试这些代码框架(测试框架不仅适用于OO代码!)。您可以使用的另一个策略是使用Web测试(使用类似Selenium之类的东西)来测试您的代码。您至少可以将代码放入某种测试工具中,以便在将代码重构为更可测试的代码时给予一些信心。

答案 5 :(得分:0)

获取受测试的程序代码是一场噩梦,但可以采用增量方法。考虑一下:

// bar.php
$priceWithoutTax = 10;
$priceWithTax = 10 * $annoyingGlobalVarWithTaxRateInIt;
echo $priceWithTax;

你应该在第一个实例中瞄准:

//bar.php
echo Foo::getPriceWithTax($annoyingGlobalVarWithTaxRateInIt);

//Foo.php
class Foo {
    public static function getPriceWithTax($annoyingGlobalVarWithTaxRateInIt) {
        $priceWithoutTax = 10;
        $priceWithTax = 10 * $annoyingGlobalVarWithTaxRateInIt;
        return $priceWithTax;
    }
}

//FooTest.php
public function testGetPriceWithTax() {
    $expectedResult = 12;
    $taxRate = 1.2;
    $this->assertEquals($expectedResult, Foo::getPriceWithTax($taxRate));
}

可能不是你希望代码结束的方式,但是将代码的主体粘贴在静态函数中至少使我们能够获得实际的业务逻辑(这里)一个微不足道的计算)正在测试中。

这样做的目的是假设你的代码偶尔做一些比将事物乘以10更复杂的事情,就是允许安全重构。您现在可以对计算的实现进行更改(对于比此更复杂的业务逻辑,可能涉及正确的面向对象;-)),安全知道您的测试会告诉您如果你有任何破坏。

通常,您总是希望采用增量方法来应用单元测试和重构。将代码的一部分提升到可测试的程度,尽可能减少对生产代码的更改,然后对其进行测试,然后对正在处理的部分进行更广泛的重构,然后继续下一步。

祝你好运。