PHPUnit 3.3 测试版已经支持 BDD 了,但有两个主要的缺点:
1、测试代码和 Story 文本差距很大,不容易编写和阅读;
2、如果有失败的测试,没法显示出到底是哪一个测试没有通过。
经过简单的扩展,并且利用 PHP 5.3 对闭包的支持,可以采用下面的格式编写 BDD 测试代码:
- /**
- * 测试从账户中取现
- */
- class AccountHolderWithdrawsCashSpec extends PHPUnit_Extensions_Story_Runner
- {
- /**
- *
@scenario - * 场景 1: 帐户有足够的资金
- */
- function AccountHasSufficientFunds()
- {
- //
GIVEN - $this->given('帐户余额为 100', function (& $world)
- {
- // 由于 Account 对象必须属于一个 AccountHolder(帐户持有人),
- // 因此需要构造一个 AccountHolder 对象
- $account_holder =
new AccountHolder(); - $account_holder->name = 'tester';
- // 创建一个 Account 对象,并设置余额为 $arguments[0]
- $world['account'] = new Account($account_holder);
- $world['account']->balance = 100;
- })
- ->and('有效的银行卡', function (& $world)
- {
- $world['card'] = new CreditCard($world['account']);
- $world['card']->valid = true;
- })
- ->and('提款机有足够现金', function (& $world)
- {
- // 确保 ATM 的余额大于帐户余额
- $world['atm'] = new ATM();
- $world['atm']->balance = $world['account']->balance + 1;
- })
- //
WHEN - ->when('帐户持有人要求取款 20', function (& $world)
- {
- $world['account']->drawingByATM($world['atm'], $world['card'], 20);
- })
- //
THEN - ->then('提款机应该分发 20', function (& $world, $action)
- {
- $this->assertEquals(20, $world['atm']->last_dispense, $action);
- })
- ->and('帐户余额应该为 80', function (& $world, $action)
- {
- $this->assertEquals(80, $world['account']->balance, $action);
- })
- ->and('应该退还银行卡', function (& $world, $action)
- {
- $this->assertTrue($world['card']->isCheckedOut(), $action);
- });
- }
- }
看上去应该好看多了,呵呵。