2012-03-18 2 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) 

이 두 결과는 무작위로 발생 나는 같은 시험을 위해 다시 시험해 보았다. 시험을 치르거나 수업 시간에 아무 것도 바꿀 필요가 없습니다.

이 모든 것은 내 컴퓨터에서 실행되며 테스트를 실행하는 동안 아무도 MongoDB 나 코드를 사용하지 않습니다.

무엇을 제공합니까?

+0

아마도 경쟁 조건이 있습니다. 당신이 조회를 위해'None'을 받았다면,이 단위 테스트를 디버거에 넣고 정확히 무엇이 적중했는지 추적하는 것이 현명 할 것입니다. – MrGomez

+0

@MrGomez, 당신은 item이 실제로 삽입되기 전에 insert()가 돌아오고, 다음에 find()가 그 시간까지 찾지 못한다고 생각하십니까? 그렇다면 insert()가 반환하지 않을 것입니까? – sssilver

+0

그건 적어도 내 이론이야. 디버깅에서 최고의 행운. – MrGomez

답변

4

나는이 문제가 당신이 쓰기에 "안전한"모드를 사용하고 있지 않다는 것을 강하게 의심하고 있습니다.

기본적으로 MongoDB는 "fire and forget"모드를 사용합니다. 즉, 삽입 명령이 서버로 전송되지만 드라이버는 서버 응답을 확인하지 않습니다.

"안전"모드로 전환하면 드라이버는 삽입 명령을 보내고 두 번째 명령 인 getLastError을 보냅니다. 이 두 번째 명령은 서버가 실제로 쓰기를 커밋 할 때 반환됩니다.

다시 말하지만, 기본적으로 "화재 및 잊어"모드로 실행 중이므로 여기에는 잠재적 인 경쟁 조건이 있습니다. 단위 테스트의 경우 "안전"모드로 실행해야합니다.

삽입 기능 시그니처는 here으로 정의됩니다. 그러나 DB에 대한 각 연결이 기본적으로 "안전"모드를 사용하도록 연결 수준에서 변경을 수행 할 수 있어야합니다.

+0

절대적으로 !! 그것은 모든 것을 고치고 모든 문제를 해결했습니다. 이렇게하면 디버깅이 힘들어졌습니다. – sssilver