2016-12-29 10 views
0

У меня проблемы с модульным тестированием приложения торнадо, помогите мне. стек ошибок трассировки:тесты с использованием tornado AsyncHTTPTestCase timeout

Error Traceback (most recent call last): File "/Users/doc/python/lib/python3.5/site-packages/tornado/testing.py", line 432, in tearDown timeout=get_async_test_timeout()) File "/Users/doc/python-virt1/lib/python3.5/site-packages/tornado/ioloop.py", line 456, in run_sync raise TimeoutError('Operation timed out after %s seconds' % timeout) tornado.ioloop.TimeoutError: Operation timed out after 5 seconds

ERROR:tornado.application:Future exception was never retrieved: Traceback (most recent call last): File "/Users/doc/python/lib/python3.5/site-packages/tornado/gen.py", line 1021, in run yielded = self.gen.throw(*exc_info) File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/types.py", line 179, in throw return self.__wrapped.throw(tp, *rest) File "/Users/doc/python-virt1/lib/python3.5/site-packages/tornado/gen.py", line 1015, in run value = future.result() File "/Users/doc/python-virt1/lib/python3.5/site-packages/tornado/concurrent.py", line 237, in result raise_exc_info(self._exc_info) File "", line 3, in raise_exc_info tornado.curl_httpclient.CurlError: HTTP 599: Empty reply from server Traceback (most recent call last):

test.py файл:

from tornado.testing import gen_test 
from tests.api_tests.base import AbstractApplicationTestBase 


class ApiRestTest(AbstractApplicationTestBase): 
    def setUp(self): 
     super(ApiRestTest, self).setUp() 
     self.prepareDatabase(self.config) 
     self.insert_user(config=self.config) 

api_test/base.py

import logging 
from api import server 
from commons.constants import config 
from tests.base import BaseTestClass 


class AbstractApplicationTestBase(BaseTestClass): 
    def get_app(self): 
     application = server.get_application(self.config) 

     application.settings[config.APPLICATION_DB] = self.db 
     application.settings[config.APPLICATION_CONFIG] = self.config 
     application.settings[config.APPLICATION_AES] = self.aes 
     application.settings[config.APPLICATION_FS] = self.fs 
     logging.info(self.config.DEPLOY_API) 

     return application 

тест/base.py

import logging 
from datetime import datetime 
import motor.motor_tornado 
from motor import MotorGridFSBucket 
from pymongo import MongoClient 
from tornado import escape 
from tornado import gen 
from tornado.testing import AsyncHTTPTestCase 

class BaseTestClass(AsyncHTTPTestCase): 
    @classmethod 
    def setUpClass(self): 
     super(BaseTestClass, self).setUpClass() 
     self.config = Config(Environment.TESTS.value) 
     self.client = utils.http_client(self.config.PROXY_HOST, self.config.PROXY_PORT) 
     self.db = motor.motor_tornado.MotorClient(self.config.MONGODB_URI)[self.config.MONGODB_NAME] 
     self.fs = MotorGridFSBucket(self.db) 

ответ

1

Несколько вещей, которые я заметил.

  • Основная проблема, которую я вижу, заключается в том, что вы делаете несколько ВОМ в своем методе setUp через motor и setUp не может быть gen_test (AFAIK). Если вам нужен этот тип функциональности, вам может потребоваться спуститься до пимонго и синхронно вызвать базу данных для обнуления этих баз данных.
  • Вы намеренно работаете против реальной базы данных? Предполагаются ли они настоящие интеграционные тесты с mongodb? Когда я пишу эти типы тестов, я бы обычно использовал класс Mock и издевался над всеми моими взаимодействиями с MongoDb.
  • Кроме того, нет никаких затрат на создание объекта AsyncHttpClient, поэтому передача этого обработчика из каждого объекта настроек/конфигурации, вероятно, не самая лучшая практика.

Вот тестовый пример обработчика в проекте шахты:

example_fixture = [{'foo': 'bar'}] 
URL = r'/list' 

    class BaseListHandlerTests(BaseHandlerTestCase): 
     """ 
     Test the abstract list handler 
     """ 
     def setUp(self): 
      self.mongo_client = Mock() 
      self.fixture = deepcopy(example_fixture) 
      # Must be run last 
      BaseHandlerTestCase.setUp(self) 

     def get_app(self): 
      return Application([ 
       (URL, BaseListHandler, 
       dict(mongo_client=self.mongo_client)) 
      ], **settings) 

     def test_get_list_of_objects_returns_200_with_results(self): 
      self.mongo_client.find.return_value = self.get_future(example_fixture) 
      response = self.fetch('{}'.format(URL)) 
      response_json = self.to_json(response) 
      self.assertListEqual(response_json.get('results'), example_fixture) 
      self.assertEqual(response.code, 200) 

     def test_get_list_of_objects_returns_200_with_no_results(self): 
      self.mongo_client.find.return_value = self.get_future([]) 
      response = self.fetch('{}'.format(URL)) 
      self.assertEqual(response.code, 200) 

     def test_get_list_of_objects_returns_500_with_exception(self): 
      self.mongo_client.find.return_value = self.get_future_with_exception(Exception('FAILED!')) 
      response = self.fetch('{}'.format(URL)) 
      self.assertEqual(response.code, 500) 

Ключ к созданию этой работы является то, что мой mongo_client передается в самом маршруте объект. Поэтому инициализация моего обработчика принимает mongo_client kwarg.

class BaseListHandler(BaseHandler): 
    """ 
    Base list handler 
    """ 
    mongo_client = None 

    def initialize(self, mongo_client=None): 
     """ 
     Rest Client Initialize 
     Args: 
      mongo_client: The client used to access documents for this handler 

     Returns: 

     """ 
     BaseHandler.initialize(self) 
     self.mongo_client = mongo_client 
0

AsyncHTTPTestCase создает новый IOLoop в начале каждого теста и уничтожает его t конец каждого теста. Тем не менее, вы создаете MotorClient в начале всего тестового класса и используете глобальный IOLoop по умолчанию вместо IOLoop, который создается специально для каждого теста.

Я считаю, что вам нужно заменить setUpClass на setUp. Затем вы создадите свой MotorClient после того, как AsyncHTTPTestCase настроит свой IOLoop. Для наглядности передайте IOLoop явно:

client = MotorClient(io_loop=self.io_loop) 
self.db = client[self.config.MONGODB_NAME] 

 Смежные вопросы

  • Нет связанных вопросов^_^