Python 随机';werkzeug.routing.BuildError';在测试Restful应用程序时

Python 随机';werkzeug.routing.BuildError';在测试Restful应用程序时,python,flask,marshalling,nosetests,flask-restful,Python,Flask,Marshalling,Nosetests,Flask Restful,所以,我在flask restful和fields.Url中遇到了一些奇怪的错误,我真的不知道为什么会出现这种错误,因为它是随机发生的。当我的应用程序正常运行时,它似乎不会发生,而且它只是在测试中随机失败 值得注意的是,它只发生在POST请求上,并且与GET请求一起工作 作为参考,所有代码位于(应用了临时修复) 错误 似乎在编组数据对象时,URL字段的创建失败了。全部错误在问题的末尾 File "/Users/tehnix/Dropbox/github/Tehnix/cred/env/lib/p

所以,我在
flask restful
fields.Url
中遇到了一些奇怪的错误,我真的不知道为什么会出现这种错误,因为它是随机发生的。当我的应用程序正常运行时,它似乎不会发生,而且它只是在测试中随机失败

值得注意的是,它只发生在POST请求上,并且与GET请求一起工作

作为参考,所有代码位于(应用了临时修复)

错误 似乎在编组数据对象时,URL字段的创建失败了。全部错误在问题的末尾

File "/Users/tehnix/Dropbox/github/Tehnix/cred/env/lib/python3.4/site-packages/werkzeug/routing.py", line 1678, in build
    raise BuildError(endpoint, values, method)
werkzeug.routing.BuildError: ('events_item', {'_sa_instance_state': <sqlalchemy.orm.state.InstanceState object at 0x102df6d68>}, None)
其中,
字段.Url
似乎由于某种原因而失败。最后是处理POST请求的资源

# FILE: cred/resources/events.py
class Events(flask.ext.restful.Resource):
    """Methods going to the /events route."""

    def post(self):
        """Create a new event and return the id and uri of the event."""
        # Parse the POST args using the parser from flask-restful into event_args
        # ...
        # Create the event in the database
        event = EventModel(
            self.client,
            event_args['name'],
            event_args['location'],
            event_args['action'],
            event_args['value']
        )
        # Save the event in the database
        db.session.add(event)
        db.session.commit()
        # Finally, convert the event object into our format by marshalling it,
        # and returning the JSON object
        return {
            'status': 201,
            'message': 'Created Event',
            'event': marshal(event, simple_event_fields)
        }, 201
正如在开始时所说的,它只在运行测试时发生(有时也会发生),因此它本身并不重要,但如果不需要多次重新运行测试来查看它是否消失以及其他所有测试是否通过,那还是很好的

测试用例 我用的是烧瓶测试,但其他的都是单元测试

# FILE: cred/test/test_events.py
test_event = {
    'event': {
        'name': 'Temperature',
        'location': 'Living Room',
        'action': 'Temperature Above Setting',
        'value': '5'
    }
}

class BaseTestCase(flask.ext.testing.TestCase):
    SQLALCHEMY_DATABASE_URI = "sqlite://"
    TESTING = True

    def create_app(self):
        return app

    def setUp(self):
        """Create a SQLite database for quick testing."""
        cred.database.init_db(cred.database.db)
        self.session_key = None

    def tearDown(self):
        """Close the database file and unlink it."""
        cred.database.db.session.remove()
        cred.database.db.drop_all()

    @testutil.authenticate('write')
    def test_posting_a_complete_event(self):
        """Create a valid new event."""
        # Post the request to the test server
        response = self.client.post(
            '/events',
            data=json.dumps(test_event),
            content_type='application/json'
        )
        resp = json.loads(response.data.decode('utf-8'))
        # Run self.assertEqual on all items in a dict
        testutil.assertEqual(self, {
            response.status_code: 201,
            resp['status']: 201,
            resp['message']: 'Created Event',
            'id' in resp['event']: True,
            'uri' in resp['event']: True
        })
在上述情况下,
test\u posting\u complete\u事件
将因
uri
项而随机失败

测试的完整错误输出
======================================================================
错误:创建有效的新事件。
----------------------------------------------------------------------
回溯(最近一次呼叫最后一次):
文件“/Users/technix/Dropbox/github/technix/cred/cred/test/util.py”,第34行,包装
乐趣(自我,*args,**kwargs)
文件“/Users/technix/Dropbox/github/technix/cred/cred/test/test\u events.py”,第37行,在test\u posting\u complete\u事件中
resp=json.load(response.data.decode('utf-8'))
文件“/usr/local/cillar/python3/3.4.2_1/Frameworks/Python.framework/Versions/3.4/lib/python3.4/json/__init__.py”,第318行,在loads中
返回\u默认\u解码器。解码
文件“/usr/local/ceral/python3/3.4.2_1/Frameworks/Python.framework/Versions/3.4/lib/python3.4/json/decoder.py”,第343行,在decode中
obj,end=self.raw\u decode(s,idx=\u w(s,0.end())
文件“/usr/local/ceral/python3/3.4.2_1/Frameworks/Python.framework/Versions/3.4/lib/python3.4/json/decoder.py”,第361行,原始解码
从“无”引发ValueError(errmsg(“期望值”,s,err.value))
nose.proxy.ValueError:预期值:第1行第1列(字符0)

-------------------->>开始捕获日志记录您需要在“fields.Url”中分配
事件\u项
,然后再返回

这个链接解释了更多

但是如果您使用的是蓝图,请在
字段中添加“
”。Url
例如
“uri”:fields.Url(“.events\u items”)


ref

您可以添加测试吗?添加:)我发现它只发生在POST请求上,而不发生在任何GET请求上。手动构造
uri
字段并将其添加到封送结果中,将始终通过所有测试,但这似乎是一个解决办法,我更愿意找出它失败的原因:并且可以添加
test\u event
?添加到
测试用例
部分:)
# FILE: cred/resources/events.py
class Events(flask.ext.restful.Resource):
    """Methods going to the /events route."""

    def post(self):
        """Create a new event and return the id and uri of the event."""
        # Parse the POST args using the parser from flask-restful into event_args
        # ...
        # Create the event in the database
        event = EventModel(
            self.client,
            event_args['name'],
            event_args['location'],
            event_args['action'],
            event_args['value']
        )
        # Save the event in the database
        db.session.add(event)
        db.session.commit()
        # Finally, convert the event object into our format by marshalling it,
        # and returning the JSON object
        return {
            'status': 201,
            'message': 'Created Event',
            'event': marshal(event, simple_event_fields)
        }, 201
# FILE: cred/test/test_events.py
test_event = {
    'event': {
        'name': 'Temperature',
        'location': 'Living Room',
        'action': 'Temperature Above Setting',
        'value': '5'
    }
}

class BaseTestCase(flask.ext.testing.TestCase):
    SQLALCHEMY_DATABASE_URI = "sqlite://"
    TESTING = True

    def create_app(self):
        return app

    def setUp(self):
        """Create a SQLite database for quick testing."""
        cred.database.init_db(cred.database.db)
        self.session_key = None

    def tearDown(self):
        """Close the database file and unlink it."""
        cred.database.db.session.remove()
        cred.database.db.drop_all()

    @testutil.authenticate('write')
    def test_posting_a_complete_event(self):
        """Create a valid new event."""
        # Post the request to the test server
        response = self.client.post(
            '/events',
            data=json.dumps(test_event),
            content_type='application/json'
        )
        resp = json.loads(response.data.decode('utf-8'))
        # Run self.assertEqual on all items in a dict
        testutil.assertEqual(self, {
            response.status_code: 201,
            resp['status']: 201,
            resp['message']: 'Created Event',
            'id' in resp['event']: True,
            'uri' in resp['event']: True
        })
======================================================================
ERROR: Create a valid new event.
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/Users/tehnix/Dropbox/github/Tehnix/cred/cred/test/util.py", line 34, in wrapped
    fun(self, *args, **kwargs)
  File "/Users/tehnix/Dropbox/github/Tehnix/cred/cred/test/test_events.py", line 37, in test_posting_a_complete_event
    resp = json.loads(response.data.decode('utf-8'))
  File "/usr/local/Cellar/python3/3.4.2_1/Frameworks/Python.framework/Versions/3.4/lib/python3.4/json/__init__.py", line 318, in loads
    return _default_decoder.decode(s)
  File "/usr/local/Cellar/python3/3.4.2_1/Frameworks/Python.framework/Versions/3.4/lib/python3.4/json/decoder.py", line 343, in decode
    obj, end = self.raw_decode(s, idx=_w(s, 0).end())
  File "/usr/local/Cellar/python3/3.4.2_1/Frameworks/Python.framework/Versions/3.4/lib/python3.4/json/decoder.py", line 361, in raw_decode
    raise ValueError(errmsg("Expecting value", s, err.value)) from None
nose.proxy.ValueError: Expecting value: line 1 column 1 (char 0)
-------------------- >> begin captured logging << --------------------
cred-server: ERROR: Exception on /events [POST]
Traceback (most recent call last):
  File "/Users/tehnix/Dropbox/github/Tehnix/cred/env/lib/python3.4/site-packages/flask/app.py", line 1817, in wsgi_app
    response = self.full_dispatch_request()
  File "/Users/tehnix/Dropbox/github/Tehnix/cred/env/lib/python3.4/site-packages/flask/app.py", line 1477, in full_dispatch_request
    rv = self.handle_user_exception(e)
  File "/Users/tehnix/Dropbox/github/Tehnix/cred/env/lib/python3.4/site-packages/flask_restful/__init__.py", line 265, in error_router
    return original_handler(e)
  File "/Users/tehnix/Dropbox/github/Tehnix/cred/env/lib/python3.4/site-packages/flask/app.py", line 1381, in handle_user_exception
    reraise(exc_type, exc_value, tb)
  File "/Users/tehnix/Dropbox/github/Tehnix/cred/env/lib/python3.4/site-packages/flask/_compat.py", line 33, in reraise
    raise value
  File "/Users/tehnix/Dropbox/github/Tehnix/cred/env/lib/python3.4/site-packages/flask/app.py", line 1475, in full_dispatch_request
    rv = self.dispatch_request()
  File "/Users/tehnix/Dropbox/github/Tehnix/cred/env/lib/python3.4/site-packages/flask/app.py", line 1461, in dispatch_request
    return self.view_functions[rule.endpoint](**req.view_args)
  File "/Users/tehnix/Dropbox/github/Tehnix/cred/env/lib/python3.4/site-packages/flask_restful/__init__.py", line 446, in wrapper
    resp = resource(*args, **kwargs)
  File "/Users/tehnix/Dropbox/github/Tehnix/cred/env/lib/python3.4/site-packages/flask/views.py", line 84, in view
    return self.dispatch_request(*args, **kwargs)
  File "/Users/tehnix/Dropbox/github/Tehnix/cred/env/lib/python3.4/site-packages/flask_restful/__init__.py", line 550, in dispatch_request
    resp = meth(*args, **kwargs)
  File "/Users/tehnix/Dropbox/github/Tehnix/cred/cred/resources/events.py", line 88, in post
    'event': marshal(event, simple_event_fields)
  File "/Users/tehnix/Dropbox/github/Tehnix/cred/env/lib/python3.4/site-packages/flask_restful/__init__.py", line 603, in marshal
    return OrderedDict([(envelope, OrderedDict(items))]) if envelope else OrderedDict(items)
  File "/Users/tehnix/Dropbox/github/Tehnix/cred/env/lib/python3.4/collections/__init__.py", line 56, in __init__
    self.__update(*args, **kwds)
  File "/Users/tehnix/Dropbox/github/Tehnix/cred/env/bin/../lib/python3.4/_collections_abc.py", line 602, in update
    for key, value in other:
  File "/Users/tehnix/Dropbox/github/Tehnix/cred/env/lib/python3.4/site-packages/flask_restful/__init__.py", line 602, in <genexpr>
    for k, v in fields.items())
  File "/Users/tehnix/Dropbox/github/Tehnix/cred/env/lib/python3.4/site-packages/flask_restful/fields.py", line 294, in output
    o = urlparse(url_for(endpoint, _external=self.absolute, **data))
  File "/Users/tehnix/Dropbox/github/Tehnix/cred/env/lib/python3.4/site-packages/flask/helpers.py", line 312, in url_for
    return appctx.app.handle_url_build_error(error, endpoint, values)
  File "/Users/tehnix/Dropbox/github/Tehnix/cred/env/lib/python3.4/site-packages/flask/app.py", line 1641, in handle_url_build_error
    reraise(exc_type, exc_value, tb)
  File "/Users/tehnix/Dropbox/github/Tehnix/cred/env/lib/python3.4/site-packages/flask/_compat.py", line 33, in reraise
    raise value
  File "/Users/tehnix/Dropbox/github/Tehnix/cred/env/lib/python3.4/site-packages/flask/helpers.py", line 305, in url_for
    force_external=external)
  File "/Users/tehnix/Dropbox/github/Tehnix/cred/env/lib/python3.4/site-packages/werkzeug/routing.py", line 1678, in build
    raise BuildError(endpoint, values, method)
werkzeug.routing.BuildError: ('events_item', {'_sa_instance_state': <sqlalchemy.orm.state.InstanceState object at 0x102df6d68>}, None)