2015-02-07 7 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이 있지만, 테스트 데이터 딕셔너리는 키 Request_id (대문자 초기에 항목이 아르 자형). 데이터를 마샬링 할 때, flask-restful은 URL을 구성하기 위해 테스트 데이터 사전에 소문자 인 request_id이있는 항목을 찾지 만 대소 문자가 일치하지 않기 때문에 찾을 수 없습니다.

경로의 매개 변수를 대문자 Request_id으로 변경하면 '테스트'엔드 포인트에 대한 요청에 대해 BuildError가 처리됩니다. 그러나 테스트 엔드 포인트에 대한 요청으로 TestAPI.get()에서 유사한 케이스 불일치로 인해 쉽게 수정할 수있는 오류가 발생합니다.