2015-02-07 126 views
1

我想修改美妙的Tutorial from Miguel Grinberg来创建unittest测试执行程序。我主要是根据我的需要调整了Miguel的代码,但是我在字段映射中生成uri时遇到了问题。只要我删除当使用Flask-Restful时生成带fields.Url的url生成BuildError

'uri': fields.Url('test') 

一切工作正常,但除此之外,我得到一个编译错误:

BuildError: ('test', {'Test_environment_id': 123, 'Test_duration': '0.5 sec', 'Success': 1, 'Failure_count': 0, 'Tested_files': 'Some files', 'Request_id': 1, 'Runs_count': 3, 'Created_on': '01.01.1970', 'Error_count': 0, 'Requester': 'John', 'Skipped_count': 2}, None) 

我发现这里非常类似的问题在计算器here但这并没有帮助我了解什么我的代码是错误的。我可以用这个问题描述的解决方法,但我真的很想知道我做错了什么。

这里是我的代码:

#!/usr/bin/python 
__author__ = 'karlitos' 

from flask import Flask, jsonify, abort, make_response, request 
from flask.ext.restful import Api, Resource, reqparse, fields, marshal,url_for 
from time import strftime 
from glob import glob 
import os 
import sqlite3 

CURRENT_DIRECTORY = os.getcwd() 
PROJECT_DIRECTORIES = glob('{}/projects/*'.format(CURRENT_DIRECTORY)) 
# create a sqlite database connection object 
db_con = sqlite3.connect('{}unittest.db'.format(CURRENT_DIRECTORY)) 

app = Flask(__name__, static_url_path="") 
api = Api(app) 

tests = [ 
    { 
     'Request_id': 1, 
     'Requester': 'John', 
     'Created_on': '01.01.1970', 
     'Test_environment_id': 123, 
     'Tested_files': 'Some files', 
     'Test_duration': '0.5 sec', 
     'Runs_count': 3, 
     'Error_count': 0, 
     'Failure_count': 0, 
     'Skipped_count': 2, 
     'Success': 1 
    } 
] 

"""Structure storing the `Request_id`'s of all test currently running indexed by their `Test_environment_id`'s.""" 
env_id_of_running_tests = {} 

"""Structure serving as a template for the `marshal` function which takes raw data and a dict of fields to output and 
filters the data based on those fields.""" 
test_fields = { 
    'Request_id': fields.Integer, 
    'Requester': fields.String, 
    'Created_on': fields.String, 
    'Test_environment_id': fields.Integer, 
    'Tested_files': fields.String, 
    'Test_duration': fields.String, 
    'Runs_count': fields.Integer, 
    'Error_count': fields.Integer, 
    'Failure_count': fields.Integer, 
    'Skipped_count': fields.Integer, 
    'Success': fields.Boolean, 
    'uri': fields.Url('test') 
} 

"""Validation function for the environment-id type which has to be in range [1,100]""" 


def env_id_type(value, name): 
    if value <= 1 or value >= 100: 
     raise ValueError("The parameter '{}' is not between 1 and 100. The value: {} was provided".format(name, value)) 
    return value 


class TestsAPI(Resource): 
    def __init__(self): 
     self.reqparse = reqparse.RequestParser() 
     self.reqparse.add_argument('Requester', type=str, required=True, 
            help='No requester name provided', location='json') 
     self.reqparse.add_argument('Test_environment_id', type=env_id_type, required=True, 
            help='Bad environment-id provided, between 1 and 100.', location='json') 
     super(TestsAPI, self).__init__() 

    def get(self): 
     return {'tests': [marshal(test, test_fields) for test in tests]} 

    def post(self): 
     args = self.reqparse.parse_args() 

     request_id = tests[-1]['Request_id'] + 1 

     # check if the current Test_environment_id is not under the currently running test 
     if args['Test_environment_id'] in env_id_of_running_tests: 
      return {'message': 'Another test with the same Environment-ID is still running.'}, 409 
     else: 
      env_id_of_running_tests[args['Test_environment_id']] = request_id 
     test = { 
      'Request_id': request_id, 
      'Requester': args['Requester'], 
      'Created_on': strftime('%a, %d %b %Y %H:%M:%S'), 
      'Test_environment_id': args['Test_environment_id'], 
      'Tested_files': 'Some files', 
      'Test_duration': '', 
      'Runs_count': None, 
      'Error_count': None, 
      'Failure_count': None, 
      'Skipped_count': None, 
      'Success': None 
     } 

     tests.append(test) 

     return {'test started': marshal(test, test_fields)}, 201 


class TestAPI(Resource): 

    def __init__(self): 
     self.reqparse = reqparse.RequestParser() 
     self.reqparse.add_argument('Request_id', type=int, required=True, 
            help='No Request-ID provided', location='json') 
     super(TestAPI, self).__init__() 

    def get(self, request_id): 
     test = [test for test in tests if test['Request_id'] == request_id] 
     print 'Request_ID', request_id 
     if len(test) == 0: 
      abort(404) 
     return {'test ': marshal(test[0], test_fields)} 


api.add_resource(TestsAPI, '/test-executor/api/tests', endpoint='tests') 
api.add_resource(TestAPI, '/test-executor/api/tests/<int:request_id>', endpoint='test') 

if __name__ == '__main__': 
    app.run(debug=True) 

回答

0

你的“测试”终点的路线有一个参数request_id(以小写初始R),但您的测试数据字典与关键Request_id(大写初始入口R)。编组数据时,flask-restful在测试数据字典中查找小写字母request_id以便构造URL,但由于大小写不匹配而无法找到它。

如果您将路由中的参数更改为大写Request_id它将负责处理'测试'端点请求的BuildError。但是随着对测试端点的请求,由于TestAPI.get()中类似的大小写不匹配,您将有新的易于修复的错误。