大部分关于奶奶的故事我已经在另外一篇文章中写过了。这里不重复贴出,只是会在必要的时候补充一些。
==============
爷爷的脾气一向很直。在苏州话中,这个“直”可以理解为:直来直去,也可以理解为“笃头笃脑”。而爷爷的脾气更多的是属于后一种。
次次体位停播NBA,复播NBA。从这个例子说明以下几点:
===========
其实,我有一个很另类的解决方法,可以解决所谓NBA太激烈而带来的问题:
将NBA现场的声音全部屏蔽掉。
如果还是不相信我们的解说,可以将解说全部屏蔽掉。我们就看画面,和理所当然、不得不播的广告好了。
原文连接:http://www.xper.org/wiki/seminar/PythonMockObjectTutorial
===============
源文件可以在mockobject.py处下载(它使用到了PyUnit模块)。
在开始之前,我想先和大家确定一点:本教程不是Mock Objects的介绍;它只是一个如何在Python 中使用MockObject^模块的简短介绍。在这里我们会看到一些Mock Objects的基本用法。要了解Mock Objects更多的信息,可以参见:
第一篇文章是任何想使用Mock Objects的人的必读(囧——译者注)。
—JuNe
假定你和你所在的团队在建立一个KMS。那么应该有一个数据库保存了所有的文档。团队决定创建一个函数来删除所有一年前发布的文章。根据文档名删除文档,以及取得所有文档名和发布日期的功能是已经有了的——由接口完成——但还没有实现,数据库也没有建立。你被分配来开发“删除老文档”的功 能,但它取决于数据库组件。你是不是应该等下去,直到别人完成了你的模块所依赖的所有功能后才进行开发呢?
让我们使用Mock Objects。 第一个版本将是这样的:
import unittest
def removeOldDocs(aDb):
pass
class RemoveOldDocs(unittest.TestCase):
def testRemoveNoneFromEmptyDb(self):
removeOldDocs(db)
if __name__=='__main__':
unittest.main(argv=('','-v'))
此时,我们想测试的情况是:如果数据库中没有任何文档,那么也就没有任何文档会被删除——这可能是最简单的情况了。这里有两重的问题。他们还没有实现数据库,而我们如何能测试removeOldDocs表现正常呢?让我们用一个mock object来进行“伪装”。
import unittest,mockobject
class MockDb(mockobject.MockObject):
pass
def removeOldDocs(aDb):
pass
class RemoveOldDocs(unittest.TestCase):
def testRemoveNoneFromEmptyDb(self):
db=MockDb()
removeOldDocs(db)
现在正常了,但是测试代码并不完整。我们需要测试removeOldDocs的行为。在测试用例中增加以下两行:
class RemoveOldDocs(unittest.TestCase):
def testRemoveNoneFromEmptyDb(self):
db=MockDb()
db._setExpectedRemoveCalls(0)
removeOldDocs(db)
db._verify()
当然,此时会出错——因为我们还没有定义_setExpectedRemovedCalls。还好,计算机告诉我们接下来做什么:定义这个方法。 我们在新定义的方法中要做些什么呢?我们应该设置删除调用应该进行的次数。因此,我们在MockDb的__init__中创建一个Expectation对象。
class MockDb(mockobject.MockObject):
def __init__(self):
self._removeCalls=mockobject.ExpectationCounter(MockDb.removeCalls)
def _setExpectedRemoveCalls(self,aCount):
self._removeCalls.setExpected(aCount)
现在我们运行测试代码,代码测试通过。现在,让我们做一些有意义的事情。
def testRemoveOne(self):
db=MockDb()
db._addDoc(doc1,1992/3/1)
db._setExpectedRemoveCalls(1)
removeOldDocs(db)
db._verify()
等一下。当前时间的信息在哪里?我们是不是也可以“伪装”它?是的。你可以替换time模块(或函数)而改用MockTime类。但是,这不是一个很好的想法。为什么不用参数将它进行传递呢?哈,我们需要修改代码,以及测试用例。让我们暂时注释掉刚加入的测试用例,让所有的测试都得以通过。然后修改测试代码。
class RemoveOldDocs(unittest.TestCase):
def testRemoveNoneFromEmptyDb(self):
db=MockDb()
db._setExpectedRemoveCalls(0)
removeOldDocs(db,2002/3/1)
db._verify()
## def testRemoveOne(self):
## db=MockDb()
## db._addDoc(doc1,1992/3/1)
## db._setExpectedRemoveCalls(1)
## removeOldDocs(db)
## db._verify()
如我们所愿,测试出错了。让我们使之通过:增加一个参数。
def removeOldDocs(aDb,aDate):
pass
现在回到刚才被注释掉的测试用例。函数调用中增加一个参数并运行。这回,计算机需要定义一个新的方法。
class MockDb(mockobject.MockObject):
......
def _addDoc(self,aName,aDate):
pass
现在又出错了。需要调用一次删除操作,但是一次也没有调用。
class MockDb(mockobject.MockObject):
def getAllDocumentDates(self):
return ()
def removeOldDocs(aDb,aDate):
for eachDoc,eachDate in aDb.getAllDocumentDates():
if isOlderThanBy(eachDate,aDate,365):
aDb.remove(eachDoc)
假定isOlderThanBy已经实现了。这行的意思是:如果eachDate早于aDate超过365天。
现在我们创建一个新的属性以便我们在mock db中保存测试用的文档。
class MockDb(mockobject.MockObject):
def __init__(self):
self._removeCalls=mockobject.ExpectationCounter(MockDb.removeCalls)
self._docs={}
def _setExpectedRemoveCalls(self,aCount):
self._removeCalls.setExpected(aCount)
def _addDoc(self,aName,aDate):
self._docs[aName]=aDate
def getAllDocumentDates(self):
return self._docs.items()
是时候在mock db中加入remove方法了。
class MockDb(mockobject.MockObject):
def remove(self,aName):
self._removeCalls.inc()
现在所有都可以执行通过。我们可以再增加一个测试用例。
def testRemoveSome(self):
db=MockDb()
db._addDoc(doc1,1992/2/15)
db._addDoc(doc2,1992/3/15)
db._addDoc(doc3,1992/4/15)
db._setExpectedRemoveCalls(2)
removeOldDocs(db,1993/4/1)
db._verify()
不需要修改代码,该用例应该可以通过。
如果你想确定某些特定文档被删除,你可以使用ExpectationSet。例如:
class MockDb(mockobject.MockObject):
def __init__(self):
self._removeCalls=mockobject.ExpectationCounter(MockDb.removeCalls)
self._removedDocs=mockobject.ExpectationSet(MockDb.removedDocs)
self._docs={}
def _addExpectedRemovedDoc(self,aName):
self._removedDocs.addExpected(aName)
def remove(self,aName):
self._removeCalls.inc()
self._removedDocs.addActual(aName)
#you may add del self._docs[aName] here if you'll use getAllDocumentDates again
class RemoveOldDocs(unittest.TestCase):
def testRemoveSome(self):
db=MockDb()
db._addDoc(doc1,1992/2/15)
db._addDoc(doc2,1992/3/15)
db._addDoc(doc3,1992/4/15)
db._setExpectedRemoveCalls(2)
db._addExpectedRemovedDoc(doc1)
db._addExpectedRemovedDoc(doc2)
removeOldDocs(db,1993/4/1)
db._verify()
有很多不同类型的Expectation类,如ExpectationCounter,ExpectationList,ExpectationSet以及ExpectationMap等。
尽管我们在测试用例中创建了mock objects,但是使用setUp方法等将它们重构出去会更好。而且我们有很大的几率消除代码中的重复。代码会更短、更清晰,只要我们严格遵循OAOO。但可惜的是,本教程就会更加的冗长了。
五月份因有长假和地震的原因,签名更换不多。
Why the dog wags its tail?
Because the dog is smarter than its tail.
If the tail is smarter than the dog,
The tail will wag the dog.
===================
猛禽在我的大力推荐下,终于看完了Conspiracy Theory,而我则在11年后,再次重新欣赏了有两位Oscar金像奖得主——达斯汀·霍夫曼和罗伯特·德·尼罗——出演的标准美国式黑色幽默片:Wag the Dog。
如我所预料的,湖人没有浪费任何赛点,在第四场“破发”而获得赛点后,又干脆利索的在第五场战胜马刺,从而获得西部总冠军。
首先,要感谢马刺,他们的坚韧不拔使得本场比赛,以及整个西部决赛充满了紧张和刺激——而这些紧张和刺激是次次体位不能忍受的。
其次,科比真真正正的体现了一个MVP的价值。他也极有可能成为NBA历史上为数不多的双料MVP之一——马刺的邓肯就是其中之一。
加索尔毕竟还需要历练,他在针对对方不同的中锋的时候的表现反差还是太大。不过,庆幸的是,东部无论是凯尔特人还是活塞,在中锋位上都不会对他的表现产生太多的威胁。
鉴于此,我认为在总决赛中,湖人将更充分的发挥KG组合,而不是KO组合。
大胆预测:总决赛湖人将以4:2的战绩加冕总冠军,科比将毫无争议的荣膺季后赛MVP称号。
经过昨天意外的推迟,今天星海学校终于进行了一年级入队仪式,而老彼得也理所当然、不可不戒的成为第一批光荣的少先队员,戴上了红领巾。
他很高兴,以致于回家拿下红领巾后,在出门学习钢琴之前,又郑重的戴上了它,说要给王老师看看。
嗯,还是很有荣誉感的。
放张照片给大家瞅瞅:

很抱歉,我对湖人拿下本场的决心还是低估了。洛杉矶人显然不希望在主场才拿到赛点,而是在客场就拿到赛点,从而彻底粉碎马刺的任何侥幸的想法:前面打成3:3,然后在第七场博一博,就象他们对付黄蜂那样。
但是显然,洛杉矶人不想给他们这样妄想的机会。
3:1,湖人拿到了赛点,西部决赛将在第五场结束,湖人又获得了宝贵的休息时间,从而开始他们最大的考验:第一次在没有主场优势的情况下,挑战东部。
另,今日看到消息,央视将暂停NBA转播。特此留存纪念。
湖人在与马刺的客场第一战中发挥失常。今天会迎来第四场的比赛。
回顾湖人和掘金、爵士的比赛,我个人认为湖人今天胜算不大。
湖人会确保在自己的主场赢得赛点,然后象对付爵士那样在第六场一举将马刺拔下。
纯属猜测。