我现在开始使用TDD了。我做了一些测试来编写日志类。
我怎么知道我是否涵盖了测试中的所有内容?
我错过了任何测试吗?测试“testShouldWriteANewLogEntry”使用日期和时间,我测试了吗?
您对我的测试有任何建议吗?
日志测试
define('FILENAME', 'logs.txt');
class LogTest extends PHPUnit_Framework_TestCase
{
public function setUp()
{
if (file_exists(FILENAME)) {
unlink(FILENAME);
}
}
public function testShouldCreateANewLogFile()
{
$log = new Log(FILENAME);
$this->assertFileExists(FILENAME);
}
public function testShouldWriteANewLogEntry()
{
$log = new Log(FILENAME);
$log->write('This is a log message');
$regExp = date('m/d/Y h:i:s a').' - This is a log message';
$regExp = str_replace('/', '\/', $regExp);
$this->assertRegExp('/^'.$regExp.'$/', file_get_contents(FILENAME));
}
public function testShouldWriteFiveLogEntries()
{
$log = new Log(FILENAME);
for ($i = 0; $i < 5; $i++) {
$log->write('#'.($i + 1).' message.');
}
$lines = count(file(FILENAME));
$this->assertEquals($lines, 5);
}
}
?>
日志类:
public function __construct($file)
{
$this->_file = fopen($file, 'a');
}
public function write($message)
{
$dateTime = new DateTime();
$message = $dateTime->format('m/d/Y h:i:s a').' - '.$message.PHP_EOL;
fwrite($this->_file, $message);
}
}
?>
感谢您的帮助。 TDD newby会很棒。 感谢。
答案 0 :(得分:3)
这是一个让人想到的东西,你的第二个测试是时间敏感的。如果您的计算机运行速度稍慢,则测试可能会失败,因为它需要更长的时间才能完成。但是,您确实希望查看日志条目是否正确放入日期时间。为此,传入一个假的DateTime接口,将其与“获取时间问题”分开进行测试。
也许是这样的:
interface DateRetriever {
public function getCurrentDate($format);
}
public function testShouldWriteANewLogEntry()
{
$log = new Log(FILENAME, new FakeDate());
$log->write('This is a log message');
$regExp = "2000-1-1".' - This is a log message';
$regExp = str_replace('/', '\/', $regExp);
$this->assertRegExp('/^'.$regExp.'$/', file_get_contents(FILENAME));
}
class RealDate implements DateRetriever {
public function getCurrentDate($format) {
return new DateTime()->format($format);
}
}
class FakeDate implements DateRetriever {
public function getCurrentDate($format) {
return new DateTime("2000-1-1");
}
}
然后是Log类:
public function __construct($file, DateRetriever $date)
{
$this->date = $date;
$this->_file = fopen($file, 'a');
}
public function write($message)
{
$message = $this->date->getCurrentDate('m/d/Y h:i:s a').' - '.$message.PHP_EOL;
fwrite($this->_file, $message);
}
现在,这不完全正确,但非常接近。这里的要点是:你的测试实际上测试了三件事:1)你得到当前时间的方式2)你的日志你的日志3)他们的内容/格式如何。
我只是拉出你获得当前时间的方式,理想情况下,你会突破你将日志保存到文件系统的方式,也许是在FileSystemManager中。这样,您可以单独测试“FileSystem”功能,“getCurrentDate”功能和“日志中的内容”业务规则。现在,您拥有一个可重用的文件系统类和一个可重用的日期类,这两个日期都是您将来很可能需要的。
我认为TDD最好的功能之一是它会迫使你将这样的概念分解为独立的单元,然后单元测试。鲍勃马丁有一些非常有趣的想法和关于这类事情的帖子,here就是一个例子。
答案 1 :(得分:0)
如果你不想像史蒂夫为这么小的类所建议的那样注入日期时间源,你可以改变你的断言来检查时间的格式而不是实际值。
$regExp = '/^[0-9\/: ]+(am|pm) - This is a log message$/';
这样就不需要拨打str_replace()
。
您还缺少一个测试来验证是否会附加现有文件而不是替换。