Category: Uncategorized

  • 死的怀念(二):爷爷、奶奶

    大部分关于奶奶的故事我已经在另外一篇文章中写过了。这里不重复贴出,只是会在必要的时候补充一些。

    ==============

    爷爷的脾气一向很直。在苏州话中,这个“直”可以理解为:直来直去,也可以理解为“笃头笃脑”。而爷爷的脾气更多的是属于后一种。

    (more…)

  • 从NBA停播想到的另类解决方法

    次次体位停播NBA,复播NBA。从这个例子说明以下几点:

    • 长官意志高于一切。停,不需要理由;复,不需要理由。
    • 有政府干预其实不错——至少次次体位可以向David Stern两手一摊,说:这个是不可抗力。Savvy?
    • 两面装相反的d真的是某些GLC(Government Linked Company)卖乖的不二法门。在迫于上头的龟腚时,可以向用户推说是来自上面的龟腚;在上头又改变主意时,可以将这个改变窃为己有,变成自己的功劳。

    ===========

    其实,我有一个很另类的解决方法,可以解决所谓NBA太激烈而带来的问题:

    将NBA现场的声音全部屏蔽掉。

    如果还是不相信我们的解说,可以将解说全部屏蔽掉。我们就看画面,和理所当然、不得不播的广告好了。

  • 研究:Python Mock Object教程

    原文连接: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类,如ExpectationCounterExpectationListExpectationSet以及ExpectationMap等。

    尽管我们在测试用例中创建了mock objects,但是使用setUp方法等将它们重构出去会更好。而且我们有很大的几率消除代码中的重复。代码会更短、更清晰,只要我们严格遵循OAOO。但可惜的是,本教程就会更加的冗长了。

  • BT群5月份签名档记录

    2008-05-05 10:44:19 我是出来买酱油的
    嗯,事不关己,高高挂起。
    2008-05-06 11:06:10 :据报道,目前S群情绪稳定
    源于性浪的一篇新闻报道:目前S者情绪稳定。可不吗,这世界上已经没有比S者情绪更稳定的人了。不过不知道是不是一语成谶……
    2008-05-13 09:55:26 为大地震死难者默哀。顺大便BS决定继续传递火炬的SB
    汶川大地震于5月12日发生。针对火炬接力如期举行的举措,我们顺大便表示了我们的不满。
    2008-05-16 08:45:18 道义放两旁,关怀摆中间
    针对救生、救灾过程中发生的一些道德问题,BT群适时的提出了这个口号。实践证明,我们这次又跑在了国务院之前。
    2008-05-19 09:28:19 为地震死难者默哀
    全国哀悼日。
    2008-05-22 09:40:10 继续生活,继续工作,继续关怀
    生活还要继续……

    五月份因有长假和地震的原因,签名更换不多。

  • “六一”苏州乐园游

    今天是“六一”国际儿童节,圣上和梓童、太子一起到苏州乐园游玩。

    去的比较早,所以还比较空,到了下午就不对了,这个people mountain people sea啊。

    这次去,除了是应“六一”的景之外,也是为了测试圣上的四能加百五零弟。联机相册已经创建于此处,欢迎鉴定。

    ============

    从拍摄效果看,四能加百五零弟还是不错的,特别是连拍,拍到了梓童在弹射升空时哇哇乱叫、花容失色的珍贵镜头,但由于涉及暴力和形象问题,所以只放一张,另加一张抓拍的悬挂式过山车的照片。

    太子照片当然还是重点。Hiahiahia。

  • Wag the Dog

    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。

    (more…)

  • 湖人夺取NBA西部冠军

    如我所预料的,湖人没有浪费任何赛点,在第四场“破发”而获得赛点后,又干脆利索的在第五场战胜马刺,从而获得西部总冠军。

    首先,要感谢马刺,他们的坚韧不拔使得本场比赛,以及整个西部决赛充满了紧张和刺激——而这些紧张和刺激是次次体位不能忍受的。

    其次,科比真真正正的体现了一个MVP的价值。他也极有可能成为NBA历史上为数不多的双料MVP之一——马刺的邓肯就是其中之一。

    加索尔毕竟还需要历练,他在针对对方不同的中锋的时候的表现反差还是太大。不过,庆幸的是,东部无论是凯尔特人还是活塞,在中锋位上都不会对他的表现产生太多的威胁。

    鉴于此,我认为在总决赛中,湖人将更充分的发挥KG组合,而不是KO组合。

    大胆预测:总决赛湖人将以4:2的战绩加冕总冠军,科比将毫无争议的荣膺季后赛MVP称号。

  • 老彼得戴上了红领巾

    经过昨天意外的推迟,今天星海学校终于进行了一年级入队仪式,而老彼得也理所当然、不可不戒的成为第一批光荣的少先队员,戴上了红领巾。

    他很高兴,以致于回家拿下红领巾后,在出门学习钢琴之前,又郑重的戴上了它,说要给王老师看看。

    嗯,还是很有荣誉感的。

    放张照片给大家瞅瞅:

  • 湖人很好,很强大

    很抱歉,我对湖人拿下本场的决心还是低估了。洛杉矶人显然不希望在主场才拿到赛点,而是在客场就拿到赛点,从而彻底粉碎马刺的任何侥幸的想法:前面打成3:3,然后在第七场博一博,就象他们对付黄蜂那样。

    但是显然,洛杉矶人不想给他们这样妄想的机会。

    3:1,湖人拿到了赛点,西部决赛将在第五场结束,湖人又获得了宝贵的休息时间,从而开始他们最大的考验:第一次在没有主场优势的情况下,挑战东部。

    另,今日看到消息,央视将暂停NBA转播。特此留存纪念。

  • 湖人与马刺

    湖人在与马刺的客场第一战中发挥失常。今天会迎来第四场的比赛。

    回顾湖人和掘金、爵士的比赛,我个人认为湖人今天胜算不大。

    湖人会确保在自己的主场赢得赛点,然后象对付爵士那样在第六场一举将马刺拔下。

    纯属猜测。