- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
我正在尝试遵循/学习 TDD。我正在使用 PHPUnit。目前,我正在编写非常简单的小类/项目,只是为了吸收所有内容。
目前我正在编写扑克牌设置。
因此,为了开始它,我编写了这个测试,因为我会避免在我的纸牌花色中重复,我决定测试应该针对花色可以扩展的抽象类。
当您读到文章结尾时,希望类的模式很明显。
BaseSuitTest.php
use Cards\French\Suits\BaseSuit as Card;
class BaseSuitTest extends PHPUnit_Framework_TestCase
{
protected $Card;
public function setUp()
{
$this->Card = $this->getMockForAbstractClass('Cards\French\Suits\BaseSuit', [10]);
}
/**
* @expectedException InvalidArgumentException
*/
public function testConstructThrowsExceptionIfFirstArgLessThan1()
{
$Card = $this->getMockForAbstractClass('Cards\French\Suits\BaseSuit', [0]);
}
/**
* @expectedException InvalidArgumentException
*/
public function testConstructThrowsExceptionIfFirstArgHigherThan13()
{
$Card = $this->getMockForAbstractClass('Cards\French\Suits\BaseSuit', [14]);
}
public function testGetSuitReturnsClassName()
{
$suit = $this->Card->getSuit();
$this->assertSame( get_class($this->Card), $suit);
}
public function testGetValueReturnsValue()
{
$value = $this->Card->getValue();
$this->assertSame(10, $value);
}
}
然后我写了下面的文件,让所有的测试都通过了。至于这一点,我也在考虑是否应该为 BaseSuit 实现一个 CardInterface(我应该编写一个测试来检查实现还是这不是测试的一部分)。我决定不这样做。
BaseSuit.php
namespace Cards\French\Suits;
abstract class BaseSuit
{
const MIN_VALUE = 1;
const MAX_VALUE = 13;
protected $value;
public function __construct($value)
{
if( $this->isWithinValueRange($value) === false)
throw new \InvalidArgumentException('The value must be higer than 0 and less than 14 (1-13) Given ' . $value);
$this->value = $value;
}
protected function isWithinValueRange($value)
{
if($value < self::MIN_VALUE OR $value > self::MAX_VALUE)
return false;
return true;
}
public function getSuit()
{
return get_class($this);
}
public function getValue()
{
return $this->value;
}
}
最后,我开始对将从基类扩展的实际类/套装进行测试。
该测试与 BaseSuit 中的测试非常相似,这已经让我心烦意乱。
HeartTest.php
use Cards\French\Suits\Heart as Heart;
class HeartTest extends PHPUnit_Framework_TestCase
{
protected $Heart;
public function setUp()
{
$this->Heart = new Heart(10);
}
/**
* @expectedException InvalidArgumentException
*/
public function testConstructThrowsExceptionIfFirstArgLessThan1()
{
$Heart = new Heart(0);
}
/**
* @expectedException InvalidArgumentException
*/
public function testConstructThrowsExceptionIfFirstArgHigherThan13()
{
$Heart = new Heart(14);
}
public function testGetSuitReturnsClassName()
{
$suit = $this->Heart->getSuit();
$this->assertSame( get_class($this->Heart), $suit);
}
public function testGetValueReturnsValue()
{
$value = $this->Heart->getValue();
$this->assertSame(10, $value);
}
}
我再次编写代码以便测试通过。
心.php
namespace Cards\French\Suits;
class Heart extends BaseSuit {}
所有测试都通过了,但还不是很酷。我想避免重复从 BaseSuit 延伸出来的套装测试(比如 Heart)。
我最初的想法是将 BaseSuit 中的方法重命名为 protected然后从这个测试延伸。这是其中一个 BaseSuit 的示例重命名测试。
BaseSuit.php中的重构方法
/**
* @expectedException InvalidArgumentException
*/
protected function constructThrowsExceptionIfFirstArgLessThan1($class)
{
// .. i have not written this code, it just a figment of my imagination.
}
这是我分开的地方。我不确定如何继续。
将 BaseSuitTest 中的测试移动到 protected 方法意味着我要么放弃当前的公共(public)测试方法。这可以修复我制作调用 protected 方法的新测试方法。
代码示例、重构建议、模式建议以及阅读本文时您脑海中浮现的任何建设性想法,我将非常感激。
有人建议我使用一个提供程序来运行以相同方法运行的测试。聪明,我以后会这样做,但我看不出这能如何解决我的情况。只是当它是抽象的 BaseSuit 时,我想在测试中使用 getMockForAbstract,当它是套装时,我只是应该更像 HeartTest。我需要帮助以了解如何以正确的方式实现。
最佳答案
我认为您没有达到 TDD 的主要目标。与其询问如何重构测试以避免代码和工作重复,不如使用测试来告知非测试代码的设计。为什么 Heart
是它自己的类?它改变或添加到 BaseSuit
的什么行为将不同于 Spade
、Diamond
和 Club
?
您已经将卡片的序号值变成了数据属性;你应该对西装做同样的事情。每张牌不是具有值(value)的花色,而是应该有花色和值(value)。这允许您拥有一个单一的、具体的 Card
类,而不需要基础或抽象版本。创建一个 Suits
类,它使用常量和排序所需的任何方法定义不同的花色 值(尽管那些可能属于 Rules
类)。
如果您仍然发现需要对更复杂的西装进行建模,我会坚持使用具有 name
、 的单个通用
、Suit
类symbolorder
等作为数据属性。
关于PHPUnit,在我对抽象类及其子类的测试中避免重复的正确方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19182198/
我可以在所有 PHPUnit 测试完成后自动运行 PHP 脚本吗? 我想在所有测试完成后报告一些非致命问题(即正确但次优的测试结果)。 最佳答案 假设您可以检测到此类次优结果,PHPUnit(v9 及
假设我要测试三种状态下的数据库一致性: 插入数据后 - 我想确保已将一定数量的行插入到数据库表中。 当数据更新后-我想重复行数量测试(数量必须与插入后相同) 删除数据时 - 我想确保所有数据都已删除。
在 pear.phpunit.de/PHPUnit 中安装 PHPUnit 未知 channel pear.phpunit.de 时出错 无效的包名称/包文件 "Debian-4 操作系统上的 pea
谁能给我解释一下使用名为 phpunit.xml.dist 或 phpunit.xml 的 PHPunit 配置文件有什么区别。 official documentation提到两个名字: PHPUn
如果我只想使用来自数据提供者的一个数据运行测试,我该怎么做? 我在这个线程上尝试了解决方案,但没有奏效 Cannot run single test with data provider in PHP
如何编写自定义断言,例如 assertFoo($expected, $actual) ,它的行为类似于关于错误“堆栈跟踪”的内置断言? 我目前定义了以下方法(在扩展 PHPUnit_Framework
我想在我的 Windows 服务器上安装 PHPUnit 3.7。我遵循了各种说明 here并以 PHPUnit 3.4.1 结束。当我尝试使用以下方法再次安装它时: pear update chan
我尝试在 PhpUnit 的 WebTestCase 中发送原始数据,但它不起作用: $jsonEvent = '{ "type": "invoice.payment_succeeded"
我收到了 PHPUnit 错误的代码覆盖率报告,我相信这是 XDebug 的一个错误。 如何配置 PHPUnit 以使用 one of its other drivers ,即PHPDBG? (我使用
我正在我的第一个项目中使用 PHPUnit 进行单元测试。事情进展顺利;但是,我已经开始通过最近的测试获得以下输出: .........................................
我刚刚学习如何使用 PHPUnit。我从命令行运行它,在结果中我得到OK,但是有问题!测试:5,断言:15,警告:2,弃用:5。 我不知道如何让它解释导致弃用和警告计数的原因。 如何找出测试代码中导致
是否有比 $this->assertTrue(false) 更官方的方法来强制 phpunit 失败? 最佳答案 我相信这应该在测试用例中起作用: $this->fail('Message'); 关于
我正在尝试为我的 Silex 应用程序编写一些测试,但遇到了问题。 我有以下 phpunit.xml 文件 ./
目前,我正在尝试使用命令行 phpunittests/Unit/ExampleTest 在 Laravel 项目上使用 phpunit 运行一些简单的单元测试。但它只运行第一种方法。有人有解决办法吗?
我的一些测试用例使用自定义测试库。而且这些测试用例非常慢。所以我想只在构建服务器中运行它们,而不是在我的本地服务器中运行它们。我想在本地运行其他测试。 以下是目录结构。 slow 目录中的那些是应该排
我有以下测试/文件夹: tests/ ClassOne.test.php ClassTwo.test.php ClassThree.test.php 我必须将以下 setUp() 和
我使用 phpunit 的测试套件功能来组织我的测试。我这样做是为了以后能够并行运行测试。 对于不同的目录,这是相对直接的。例如,我可以按捆绑拆分测试套件。 tests/BundleOne
我必须用内部数组测试一个数组。 我的数组如下所示。 $testdata=Array ( [0] => Array ( [
问题:为什么 PHPUnit 似乎在严格模式下运行? 问题: PHPUnit 4.3.1 by Sebastian Bergmann. Configuration read from /full/pa
我已经通过 Composer 安装了 PHPUnit,并将其设置为通过设置运行单元测试。 但是当我运行测试时,测试报告器出现以下错误(tets 执行得很好): Unable to attach tes
我是一名优秀的程序员,十分优秀!