Test Blueprint di routing - Flask Restplus

voti
0

Sto cercando di verificare l'esempio di ToDo nel sito Flask-Restplus, ma si continua a ottenere me 404 ...

Fondamentalmente ho 3 file:

app.py

import sys
import os
import platform
import datetime
import logging    
from logging import Formatter
from logging.handlers import RotatingFileHandler

from jinja2 import Environment, PackageLoader

from flask import Flask, url_for, render_template, abort, request, Blueprint
from flask.ext.restplus import Api, Resource, fields
from werkzeug.contrib.fixers import ProxyFix


api_v1 = Blueprint('api', __name__, url_prefix='/api/1')


ns = api.namespace('todos', description='TODO operations')

TODOS = {
    'todo1': {'task': 'build an API'},
    'todo2': {'task': '?????'},
    'todo3': {'task': 'profit!'},
}


todo = api.model('Todo', {
    'task': fields.String(required=True, description='The task details')
})

listed_todo = api.model('ListedTodo', {
    'id': fields.String(required=True, description='The todo ID'),
    'todo': fields.Nested(todo, description='The Todo')
})


def abort_if_todo_doesnt_exist(todo_id):
    if todo_id not in TODOS:
        api.abort(404, Todo {} doesn't exist.format(todo_id))

parser = api.parser()
parser.add_argument('task', type=str, required=True, help='The task details', location='form')

@ns.route('/<string:todo_id>')
@api.doc(responses={404: 'Todo not found'}, params={'todo_id': 'The Todo ID'})
class Todo(Resource):
    '''Show a single todo item and lets you delete them'''
    @api.doc(description='todo_id should be in {0}'.format(', '.join(TODOS.keys())))
    @api.marshal_with(todo)
    def get(self, todo_id):
        '''Fetch a given resource'''
        abort_if_todo_doesnt_exist(todo_id)
        return TODOS[todo_id]

    @api.doc(responses={204: 'Todo deleted'})
    def delete(self, todo_id):
        '''Delete a given resource'''
        abort_if_todo_doesnt_exist(todo_id)
        del TODOS[todo_id]
        return '', 204

    @api.doc(parser=parser)
    @api.marshal_with(todo)
    def put(self, todo_id):
        '''Update a given resource'''
        args = parser.parse_args()
        task = {'task': args['task']}
        TODOS[todo_id] = task
        return task


@ns.route('/')
class TodoList(Resource):
    '''Shows a list of all todos, and lets you POST to add new tasks'''
    @api.marshal_list_with(listed_todo)
    def get(self):
        '''List all todos'''
        return [{'id': id, 'todo': todo} for id, todo in TODOS.items()]

    @api.doc(parser=parser)
    @api.marshal_with(todo, code=201)
    def post(self):
        '''Create a todo'''
        args = parser.parse_args()
        todo_id = 'todo%d' % (len(TODOS) + 1)
        TODOS[todo_id] = {'task': args['task']}
        return TODOS[todo_id], 201


app = Flask(__name__)

app.secret_key = secretkey
app.config.from_pyfile('settings.py')

if os.path.exists(os.path.join(app.root_path, 'local_settings.py')):
    app.config.from_pyfile('local_settings.py')


app.config['SQLALCHEMY_DATABASE_URI'] = 'postgres://%s@%s/%s' % (
    app.config['DB_USER'], app.config['DB_HOST'], app.config['DB_NAME'])

main.py

import sys

from flask import Blueprint

from portal.app import app
from portal import libs

if __name__ == '__main__':
    if len(sys.argv) == 2:
        port = int(sys.argv[1])
    else:
        port = 5000

    host = app.config.get('HOST', '127.0.0.1')

    from portal.app import api_v1
    app.register_blueprint(api_v1)

    import os
    app.root_path = os.getcwd()
    print Running in, app.root_path,  with DEBUG=, app.config.get('DEBUG', False)
    app.run(host,
            port,
            app.config.get('DEBUG', False),
            use_reloader=True
    )

tests.py

class ApiTests(helpers.ViewBase):

    ############################
    #### setup and teardown ####
    ############################

    def setUp(self):
        super(ApiTests, self).setUp()
        app.config['TESTING'] = True
        app.config['WTF_CSRF_ENABLED'] = False
        app.config['DEBUG'] = False
        self.assertEquals(app.debug, False)

    # executed after to each test
    def tearDown(self):
        pass

    ###############
    #### tests ####
    ###############
    def test_can_obtain_todos(self):
        response = self.client.get('/api/1/todos')
        self.assertEqual(response.status_code, 200)

Se faccio funzionare l'app posso accedere a http: // localhost: 5000 / api / 1 / Todos senza problemi, ma se corro i test, io continuo ad ottenere 404 eccezione di routing

Traceback (most recent call last):
File /home/internetmosquito/python_envs/portal/local/lib/python2.7/site-packages/flask/app.py, line 1639, in full_dispatch_request
rv = self.dispatch_request()
File /home/internetmosquito/python_envs/portal/local/lib/python2.7/site-packages/flask/app.py, line 1617, in dispatch_request
self.raise_routing_exception(req)
File /home/internetmosquito/python_envs/portal/local/lib/python2.7/site-packages/flask/app.py, line 1600, in raise_routing_exception
raise request.routing_exception
NotFound: 404: Not Found
> /home/internetmosquito/git/wizbots/portal/src/portal/test/test_api.py(47)test_can_obtain_todos()

Qualche idea di cosa mi manca qui? Grazie!

È pubblicato 20/11/2016 alle 10:40
fonte dall'utente
In altre lingue...                            


1 risposte

voti
0

Per la cronaca, il test stava fallendo perché non ero l'inizializzazione correttamente il progetto di nuovo nel file di test ... questo è fatto in main.py per evitare problemi di dipendenze circolari che ho avuto.

Quindi, semplicemente ri-creare il progetto e l'assegnazione ad app in SETUP nel file di test fa il trucco, ma questo non è efficiente e dovrebbe essere evitata, immagino che dovrei controllare il motivo per cui le dipendenze circolari che sta accadendo e fare everythng nel app.py file invece ...

Risposto il 20/11/2016 a 22:29
fonte dall'utente

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more