我是PHP测试的新手,并尝试使用TDD构建一个简单的项目。
简单的想法是制作一种简单的卡片/卡片设置。
我开始编写测试并迅速开始在我的运行测试中混合 CardDeck 类和 CardStack 类。他们都实现了一些相同的方法,比如getTop(),getTopStack()..所以我决定实现一个 CardDeckInterface ,一个抽象类 BaseCardStack 来干掉它。
重构后。 CardDeck和CardStack扩展了实现CardStackInterface的BaseCardStack。
CardDeck和CardStack唯一的区别是CardStack的构造和一些附加功能。否则,BaseCardStack的所有实现功能都不会被覆盖。
这就是我的麻烦所在。在我的 CardDeckTest 中,我将测试与已实现的方法联系起来,这已经移动了BaseCardDeck。
我应该将当前的测试保存在我的CardDeckTest中(它们仍像以前一样通过)并为CardStackTest写一组额外的测试吗?这似乎是错误的解决方案,因为这些方法已经过测试,并且没有任何区别(不会被覆盖),正如我所提到的,BaseCardStack中实现的方法不会被覆盖。
相反,我认为我应该为我的抽象类移动/编写测试。
基本上我想测试我的抽象类中的函数,我知道它将在不被覆盖的情况下实现。
但我该怎么做? 我应该嘲笑吗?我应该改变模式吗?
答案 0 :(得分:1)
相反,我认为我应该为我的抽象类移动/编写测试
实际上,您可能希望在实现该接口的任何其他类上应用相同的单元测试集。
但是在你做一些警告之前:三思而后行。你可能不需要这里的抽象类。听起来你有一些适合两个类使用的工作的数据结构,但这两个类不是那个数据结构。
但是,通过从抽象数据结构类中扩展这两个类,实际上只是将这两个类放在这个数据结构中。
收藏composition over inheritance。
简单地说,对于关于如何测试抽象类的原始问题,您可以创建一个测试双重。这适用于能够mock abstract classes(和Testing Abstract Classes)的PHPUnit模拟,并且这样做可以接管已定义的方法。
但我通常只是创建一个用于测试的存根类,它创建一个新文件,其中包含一个从抽象基类扩展的类定义,该类定义独立于应用程序的其余部分(但绑定在抽象类上)和然后在单元测试中使用它作为主题(与Test methods of Abstract Class with PHPUnit比较)。
这样做最常见的并不是隐藏在复杂的模拟和存根设置之后不需要抽象基类的事实。只需将代码编写为必要的代码就很难实现。
希望这有帮助,随时回复。
哦,实际上这是另一个提示。我为抽象基类做过一次或两次的事情就是创建一个包含基础测试的abtract测试用例。从它扩展到具体的实现测试确实很好。 IIRC的相关问题是: