Тестирование юнитов Python MongoDB случайно завершается неудачей - PullRequest
5 голосов
/ 18 марта 2012

Странные проблемы с юнит-тестом Python и PyMongo.Тест случайным образом завершается успешно или не проходит:

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'})

Случайное поведение:

silver@aregh-6930-lnx ~/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)

...

silver@aregh-6930-lnx ~/projects/traction/tractor $ python -m unittest discover
......ss.ssssssssss
----------------------------------------------------------------------
Ran 19 tests in 0.015s

OK (skipped=12)

Эти два результата случайным образом происходят для одного и того же теста, когда я перезапускаю тест, не меняя ничего ни в классе, ни в тесте.

Все это выполняется на моей машине, и я точно знаю, что во время работытест, никто больше не возится ни с MongoDB, ни с кодом.

Что дает?

1 Ответ

4 голосов
/ 18 марта 2012

Я сильно подозреваю, что проблема здесь в том, что вы не используете «безопасный» режим для своих записей.

По умолчанию MongoDB использует режим «запусти и забудь».Это означает, что команда вставки отправляется на сервер, но драйвер не проверяет наличие каких-либо ответов сервера.

Когда вы переключаетесь в «безопасный» режим, драйвер отправляет команду вставки, а затемотправить вторую команду getLastError.Эта вторая команда будет возвращена, когда сервер фактически совершит запись.

Опять же, по умолчанию вы работаете в режиме «запусти и забудь», так что здесь действительно есть потенциальное состояние гонки.Для юнит-тестов вам нужно будет работать в «безопасном» режиме.

Сигнатура функции для вставки определена здесь .Однако вы также должны иметь возможность вносить изменения на уровне Соединения, чтобы каждое соединение с БД по умолчанию использовало «безопасный» режим.

...