2012-03-18 19 views
5

PythonのunittestとPyMongoに奇妙な問題があります。テストは、ランダムに成功または失敗する:テストされているPython unittestのテストMongoDBがランダムに失敗する

import unittest 
from pymongo import Connection 

from tractor import Tractor 




class TestTractor(unittest.TestCase): 
    def setUp(self): 
     self.tractor = Tractor(1) 

     self.mongo = Connection() 
     self.db = self.mongo.tractor 

     self.db.classes.remove({'name': {'$regex':'^test_'}}) 

     self.action_class_id = self.db.classes.insert({'name': 'test_action', 
                 'metaclass': 'action'}) 
     self.object_class_id = self.db.classes.insert({'name': 'test_object', 
                 'metaclass': 'object'}) 


    def tearDown(self): 
     self.tractor = None 



    def test_create_class(self): 
     cid1 = self.tractor.create_action_class('test_create_action_class') 
     cid2 = self.tractor.create_object_class('test_create_object_class') 

     self.assertNotEqual(cid1, None) 
     self.assertNotEqual(cid2, None) 

     action_obj = self.db.classes.find_one({'_id': cid1}) 
     object_obj = self.db.classes.find_one({'_id': cid2}) 

     self.assertNotEqual(cid1, cid2) 
     self.assertEqual(action_obj['_id'], cid1) 
     self.assertEqual(object_obj['_id'], cid2) 

     self.assertEqual(action_obj['name'], 'test_create_action_class') 
     self.assertEqual(object_obj['name'], 'test_create_object_class') 

クラス:

from pymongo import Connection 
from pymongo.objectid import ObjectId 



class Tractor(object): 
    def __init__(self, uid): 
     self.uid = uid 
     self.mongo = Connection() 
     self.db = self.mongo.tractor 


    # Classes 

    def create_action_class(self, name): 
     return self.db.classes.insert({'name': name, 
             'attributes': [], 
             'metaclass': 'action'}) 

    def create_object_class(self, name): 
     return self.db.classes.insert({'name': name, 
             'attributes': [], 
             'metaclass': 'object'}) 

ランダム行動:

[email protected] ~/projects/traction/tractor $ python -m unittest discover 
......ssEssssssssss 
====================================================================== 
ERROR: test_create_class (tests.test_tractor.TestTractor) 
---------------------------------------------------------------------- 
Traceback (most recent call last): 
    File "/home/silver/projects/traction/tractor/tests/test_tractor.py", line 64, in test_create_class 
    self.assertEqual(action_obj['_id'], cid1) 
TypeError: 'NoneType' object is not subscriptable 

---------------------------------------------------------------------- 
Ran 19 tests in 0.023s 

FAILED (errors=1, skipped=12) 

...

[email protected] ~/projects/traction/tractor $ python -m unittest discover 
......ss.ssssssssss 
---------------------------------------------------------------------- 
Ran 19 tests in 0.015s 

OK (skipped=12) 

これら二つの結果がランダムに起こります同じテストのために私はtを再実行しますクラスでもテストでも何も変えないで

このすべては私のマシン上で実行され、私がテストを実行中に、誰もがMongoDBのでもコードでもないtinkersないことを確実に知ります。

何がありますか?

+0

競合状態にある可能性があります。あなたのルックアップのために 'None'を受け取っているなら、デバッガにこのユニットテストをスローし、ヒットする原因を正確に突き止めることが賢明でしょう。 – MrGomez

+0

@MrGomez、あなたは、アイテムが実際に挿入される前にinsert()が戻ってきて、すぐにfind()の後にそれが見つからないと思いますか? しかし、insert()は返されません。 – sssilver

+0

それは少なくとも私の理論です。あなたのデバッグに最適です。 – MrGomez

答えて

4

あなたの書き込みに「安全な」モードを使用していないことが強く疑われます。

デフォルトでは、MongoDBは「fire and forget」モードを使用します。つまり、insertコマンドがサーバーに送信されますが、ドライバーはサーバーの応答を確認しません。あなたは「安全な」モードに切り替えると

は、ドライバーが挿入コマンドを送信し、それがその後、2番目のコマンド​​を送信します。この2番目のコマンドは、サーバーが実際に書き込みをコミットしたときに戻されます。

また、デフォルトでは、「火災と忘れ」モードで実行されているため、実際に競合状態が発生する可能性があります。単体テストでは、 "安全"モードで実行する必要があります。

挿入の関数シグネチャは、hereと定義されています。ただし、DBへの各接続がデフォルトで「安全」モードを使用するように、接続レベルで変更を行うこともできます。

+0

絶対に!!それはすべてを修正し、すべての問題を解決しました。 これは私にこのような困難な時間をデバッグすることを与えました。 – sssilver

関連する問題