基于@SDC的回答,我推荐以下
进一步拆分测试
如果断言与相同的行为不相关,则单个测试中的多个断言会出现问题:您无法正确命名测试,甚至可能最终and
在测试方法名称中使用。如果发生这种情况,请将测试拆分为单独的测试
避免使用 SUT 的实例属性
当我开始编写测试时,我觉得在将被测系统 (SUT) 安排在 中setUp
,然后通过各个测试中的相应实例属性引用 SUT 时,有机会减少代码重复。
这很诱人,但过了一段时间,当您开始从 SUT 中提取协作者时,您将需要设置测试替身。一开始这可能仍然对您有用,但是您将开始在不同的测试中以不同的方式设置测试替身,并且之前旨在避免的所有重复都会回到您身上:您最终将设置两个测试替身,并再次在您的测试中安排 SUT。
当我在代码审查中遇到这个时,我喜欢参考
我建议阅读它。
重要的一点是,你想让测试的编写和维护变得容易。维护测试(或任何代码,如果你愿意的话)主要意味着使代码易于阅读。如果您阅读一些代码,比如说,一个类方法,您想轻松理解它的含义,理想情况下,该方法应该按照您的类名做您期望它做的事情。如果您正在测试不同的行为,请通过创建不同的测试方法使其显而易见。
这也有一个好处,如果你运行你的测试
$ phpunit --testdox
您最终会得到一个很好的预期行为列表,请参阅
基于您的问题的示例
注意我在这个例子中提供的注释只是为了说明进一步拆分测试的想法,在实际代码中我不会有它们。
/**
* The name of this method suggests a behaviour we expect from the
* constructor of DependencyContainer
*/
public function testCanOverrideShellCommanderConfiguration()
{
$container = new DependencyContainer(__DIR__ . '/../../Resources/valid_json.json');
$this->assertEquals(
'overriden',
$container->getConfig('shell_commander')['pygmentize_command']
);
}
/**
* While the idea of using a data provider is good, splitting the test
* further makes sense for the following reasons
*
* - running tests with --testdox option as lined out above
* - modifying the behaviour independently
* Currently, a generic Exception is thrown, but you might
* consider using a more specific exception from the SPL library,
* (see http://php.net/manual/en/spl.exceptions.php),
* or creating your own NonExistentConfigurationException class,
* and then a data provider might not make sense anymore)
*/
public function testConstructorRejectsNonExistentConfigurationFile()
{
$path = 'unexisting_file';
$this->setExpectedException(\Exception::class, sprintf(
'Configuration file at path "%s" doesn\'t exist.',
$path
));
new DependencyContainer($path);
}
public function testConstructorRejectsInvalidConfigurationFile()
{
$path = __DIR__ . '/../../Resources/invalid_json.json';
$this->setExpectedException(
\Exception::class,
'Configuration JSON file provided is not valid.'
);
new DependencyContainer($path);
}
注意我也建议看看