2013-07-30 56 views
0

我对私有/受保护方法的测试存在疑问。这是一个解决任何平台单元测试的普遍问题。但只是告诉你,我正在与phpunit一个单元测试php的平台。我应该测试私有/受保护的方法吗?为什么?

我们应该测试私有/受保护的方法吗?这个question接受的答案说,我们通常不应该。 从这个问题的答案:

通常你只是不测试或嘲笑的私人&保护方法directy。

你想测试的是你的类的公共API。其他一切都是为您的课程提供的 实施细节,如果您更改它,则不会“破坏”您的测试。

但在这么多的问题,同时其他的答案提供了一种方法来测试他们(我假定这些答案意味着我们应该测试私有/保护的方法,因为他们不说,我们应该或不应该对其进行测试)。

请解释我的理由。谢谢。

+0

我已投票结束主要是基于意见的。我认为这会在没有事实答案的情况下引发太多争论。 –

+0

有很多关于如何做错事的问题(和答案)...... :) –

+0

@DuncanJones好的。然后,如果我有这个疑问,我请你建议我该怎么做。 – Geek

回答

1

至于我 - 它取决于私人/受保护成员的复杂性。

例如你有一个复杂的计算私有方法FUNC1()和FUNC2()或多个输入参数的算法。你有一个使用它们的公共API。和一些数据FUNC1()被打破,并返回不正确的数据,但在FUNC2加工过程中()这个数据在某种程度上转化为正确的结果(如其他问题的结果)。公共API方法的总结果将是正确的 - 这意味着您有错误Func1Func2但您的API retors正确地以某种方式纠正。你试了一下,没问题。

现在你给你的代码给别人,和他/她创造FUNC3()和使用FUNC1()和FUNC3()多了一个公共的API方法和单元测试这个API方法失败。他/她花费多少时间才能发现原因在Func1?并且当Func1将被修复时,您将在之前的测试中使用Func2失败......这总的来说并不好。

因此,恕我直言,你应该测试私有/受保护的方法,如果他们是复杂的(很多代码或使用不明显的算法)和可重复使用。当然,您不需要为返回+ b或编写调试日志记录的私有方法创建100个单元测试。

希望我的回答能帮助你! 最好的问候,米哈伊尔。

0

相信的私人/受保护的方法测试取决于在哪里/如何被访问,什么正在测试。

如果我建立的公共代码可重用库,那么这些类中的private和protected方法库的测试用例中测试。这些测试确保较低级别的代码可以正常工作,以便我可以对图书馆有信心。

现在,当我写访问这个库业务应用程序,我不写的库对象的测试,因为他们将在业务应用测试被嘲笑。图书馆测试表明图书馆工作,然后商业应用程序测试显示该应用程序工作。

业务应用程序不会尝试测试库的私营/保护方法,因为我认为的代码一个黑盒子,我不知道(类似于外部库或Web服务)。然而,我仍然在业务应用程序的测试套件中测试业务应用程序的私有和受保护的方法,以确保方法/函数的行为与他们应该的一样。

作为一个例子吧,假设以下业务类(非常简短的表达思想,而不是函数):

<?php 
class ACCOUNTS 
{ 
    protected GetEstimation() 
    { 
     ... 
     return $CalculatedValue; 
    } 
} 

class CUSTOMER_ACCOUNT extends ACCOUNTS 
{ 
    protected GetEstimation() 
    { 
     $BaseEstimation = parent::GetEstimation(); 
     ... 
     return $NewCalculatedValue 
    } 
} 

class RESELLER_ACCOUNT extends ACCOUNTS 
{ 
    protected GetEstimation() 
    { 
     ... 
     return $ResellerCalculatedValue; // Note: No call to parent 
    } 
} 
?> 

在这个例子中有一些将要返回不同的值。 Protected功能被使用,因此可以被覆盖,并且不必依赖父类功能。在这个例子中,我想测试所有这些类在使用时返回正确的值。

的基本账户类应该尽自己的计算,基于类值后返回的估计。作为一个规则,我只是设置的值和测试的回报:

<?php 
class ACCOUNTSTest extends PHPUnit_Framework_TestCase 
{ 
    protected $Accounts; 

    protected function setUp() 
    { 
     $this->Accounts = new ACCOUNTS(); 
    } 

    public function testEstimationHome() 
    { 
     $this->Accounts->InternalValue1 = 1; 
     $this->Accounts->InternalValue2 = 10; 
     $this->Accounts->InternalValue3 = 100; 
     $this->assertEquals(523, $this->Accounts->GetEstimation(), 'Test Home Account with values 1, 10, 1000'); 
    } 

    public function testEstimationHome2() 
    { 
     $this->Accounts->InternalValue1 = 5; 
     $this->Accounts->InternalValue2 = 2; 
     $this->Accounts->InternalValue3 = 10; 
     $this->assertEquals(253, $this->Accounts->GetEstimation(), 'Test Home Account with values 5, 2, 10'); 
    } 

    protected function tearDown() 
    { 
     unset($this->Accounts); 
    } 
} 
?> 

现在,这些测试将确保ACCOUNTS-> GetEstimation()是否正常工作。然后我会测试CUSTOMER_ACCOUNT,并进行类似的测试以确保该类正确计算。是的,如果基类发生变化,那么我可能需要更新CUSTOMER_ACCOUNT中的测试,因为ACCOUNTS-> GetEstimation()发生了变化,但是我还有一个额外的检查,即基类仍然正确返回。

或者,我可以改变这个结构,使用依赖注入提供某些信息(账户),以确保如果父估计总是523,那么这个类返回正确的价值观。如果ACCOUNTS改变了返回的估计值,并且对这个类无关紧要(也许这个类只是增加了额外的值),然后我将我的测试隔离开来,不用担心。

希望这个更新有助于说明我在说什么。

+0

谢谢你的回答。我明白为什么我们不需要测试库。但是,您能否详细说明为什么我们应该测试私有/受保护的业务应用方法? – Geek

+0

商业应用程序仍然需要工作。许多应用程序类使用私有/受保护的,所以外部类不能更改这些值。但是,如果我在类方法中做了不重要的工作(并且它可能是私有的),那么我想确保该类经过测试并且该方法不会更改。我发布了一个伪示例作为解答这个问题的答案。 –

1

私有和受保护的方法是被测代码的实现细节,不应该被测试。你的测试告诉你“你的代码应该做什么”。测试私有和受保护的方法开始进入你的代码应该做什么的“如何”。

当你修改你的类,因为你发现了一些代码重用,你有没有测试,你知道,那是因为你改变了一些功能和需要修复的测试用例添加一些私有方法。如果您对私有和受保护的方法进行了测试,并且您现在做了同样的事情,那么您需要查看测试是否由于某个有效原因而失败,或者来自您的重新分解。私有和受保护的方法通过类的公共接口的测试覆盖,不需要任何测试。

只因为你“可以”做的东西并不意味着你“应该”做一些事情。

当我测试时,我认为被测系统是一个黑盒子。我给它一些东西,我希望发生一些事情。我不在乎里面发生了什么。所有重要的是给出正确的输出。

复杂的内部函数是一种代码味道,也许我有我的课做得太多,可能有另一个类隐藏在里面。

相关问题