PHPUnit测试问题-如何对我的类进行单元测试

PHPUnit测试问题-如何对我的类进行单元测试,php,unit-testing,phpunit,Php,Unit Testing,Phpunit,我正试图进入单元测试,因为它引入了明显的积极因素,我正试图为我前几天编写的一个类编写一个单元测试。(我知道这与TDD相反,请容忍我) 我的类,Image,与其他一些类一起用于图像处理 Image基本上包装了一个GD图像资源并存储了数据。例如,Image的实例将始终包含其当前状态,即调整大小后的新宽度/高度、原始图像数据等 Image类还包含 从文件、字符串数据或URL创建自身,例如$image->loadFromPath() 从当前图像实例的属性创建新的GD图像资源,例如,用于调整图像大小以保

我正试图进入单元测试,因为它引入了明显的积极因素,我正试图为我前几天编写的一个类编写一个单元测试。(我知道这与TDD相反,请容忍我)

我的类,
Image
,与其他一些类一起用于图像处理

Image
基本上包装了一个GD图像资源并存储了数据。例如,
Image
的实例将始终包含其当前状态,即调整大小后的新宽度/高度、原始图像数据等

Image
类还包含

  • 从文件、字符串数据或URL创建自身,例如
    $image->loadFromPath()
  • 从当前
    图像
    实例的属性创建新的GD图像资源,例如,用于调整图像大小以保持背景透明度等
  • 克隆GD映像资源以在操纵类中使用
我正在努力解决的是如何使用PHPUnit正确地单元测试这个类。我读了一些书,对于如何处理这个问题,我有一些相互矛盾的想法,我不知道什么是正确的。是吗?

  • 为类中的每个方法编写一个测试。我在某个地方读到,我应该测试每一种方法。然而,有些方法运行其他方法(我可以添加正确的方法),因此您就有了一个依赖链。但我也读到,每个单元测试应该相互独立。如果是这样,我该怎么办
  • 将每个测试作为类的使用路径编写。我还从某个地方读到,每个测试应该代表一个可以与类一起使用的路径/使用路线。因此,如果您涵盖每种用法,您最终将获得完整的代码覆盖率
  • 那么,哪一项是正确的,如果有的话?

    您可以使用来指定测试是否涵盖多个方法。因此,如果您的一个方法调用另一个方法,您只需将注释添加到测试的docblock中,它就会添加到您的代码覆盖率统计数据中,例如

    /**
     * @test
     * @covers MyClass::something()
     * @covers MyClass::_somethingElse()
     */
    public function somethingWorksAsExpected()
    {
        $this->assertSame($expected, $this->testObject->something());
    }
    
    对于个人项目,100%的代码覆盖率是可以的。然而,我在会议上看到过100%被怀疑是必要的会谈。尽管有这些好处,但编写测试需要时间,在预算项目中,只测试80/20就足够了,省去了应用程序中不重要的低优先级功能


    至于如何测试你的课程,请看一看关于。在您的情况下,我会测试您在问题中描述的功能。

    应该编写单元测试来评估类的公共接口。您的测试用例应该使用您希望在程序中使用的类。这里的想法是测试类的行为(预期、意外或边缘条件)

    你发表的两个观点都是正确的。理论上,您应该有足够的测试用例(通过代码的路径)来运行类中的所有方法

    如前所述,100%测试覆盖率是一个不错的目标,但并不总是现实的

    另外,在GD的情况下,编写测试GD功能的单元测试时要小心(它已经被测试过了,您不需要再浪费时间测试它)。我将在PHPUnit手册中使用PHPUnit的mock和stub(以及模拟文件系统)

    下面是一个示例测试的样子:

    public function testImageIsResized()
    {
        $image = new Image();
        $image->loadFromPath('some/path');
        $image->resize(200, 300);
        $this->assertEquals(200, $image->getWidth());
        $this->assertEquals(300, $image->getHeight());
    }
    
    现在,根据image类的预期行为,此测试可能会顺利通过,也可能会失败,因为它预期新维度将按比例约束到原始图像维度。但是我们没有明确调用内部方法来检查测试本身中的约束。

    斯蒂芬·梅罗斯说:

    但是,有些方法会运行 其他人(我可以补充一句)也是如此 然后有一个依赖链。但我 还应阅读每个单元测试 独立自主


    测试独立性不是不测试同一代码两次,而是一个测试的结果(或缺少结果)是否会影响另一个测试的结果。如果您的第一个测试插入了一些数据,然后在删除该数据之前失败,那么您的第二个测试可能会得到与预期不同的结果。理想情况下,您应该能够以随机顺序运行测试,或者运行一些而不是其他测试

    你知道代码覆盖率吗?在我看来,更重要的是每一行代码至少运行一次,而不是为每一个方法创建一个测试,因为你提到的原因,这并不总是必要的。+1对于进入UnitTest,我知道什么是代码覆盖率是肯定的,并且你的目标应该是100%,即每一行至少运行一次。因此,编写测试用例时,每个测试都是您的类执行的操作,而不是每个测试都是针对特定方法的,这显然取决于您的类及其方法,但通常是这样。如果实用程序和助手函数也是从其他地方调用的,则不需要单独测试它们。实际上,再考虑一下,您可能也想测试它们。毕竟,如果您不单独测试它们,那么其中的bug不一定很容易找到。所以,基本上,忽略我说的;)现在我的想法差不多了!谢谢你的总结