接口测试之RESTful

2019-08-13 18:30:50 浏览数 (1)

REST又被称为表征性状态传输,它是指客户端与服务端之间传输信息的一种方式。在REST中并没有严格的标准和规范,它只是规定了一套对通信的约束,当然它也存在一些指导的约束,也就是说客户端与服务端关注的是分离,只要API改变。常见的RESTful系统形式由JSON组成,每个资源位于自己的URL路径上,并使用不同的HTTP请求方法进行操作。在这里还是以具体的案例来说明这部分的应用,在无涯课堂里面添加课程的信息,获取所有课程的信息,以及获取某一个课程的信息,和对课程信息进行修改,以及删除课程的信息。需要安装的第三方的库为:flask-restful,flask-httpauth,flask,安装成功后,就实现具体的案例代码。

下面是添加课程信息,以及课程信息的操作,当然也添加了鉴权的认证方式(基本认证),见如下的源码:

代码语言:javascript复制
#!/usr/bin/env python
# -*-coding:utf-8 -*-
from flask import  Flask,make_response,jsonify,abort,request
from flask_restful import  Api,Resource
from flask_httpauth import  HTTPBasicAuth

app=Flask(__name__)
api=Api(app=app)
auth=HTTPBasicAuth()


@auth.get_password
def get_password(name):
   if name=='wuya':
      return 'admin'
@auth.error_handler
def authoorized():
   return make_response(jsonify({'msg':"请认证"}),401)

@app.errorhandler(404)
def not_found(error):
   return make_response(jsonify({'msg':'很抱歉,您访问的页面不存在'}))

books=[
   {'id':1,'author':'wuya','name':'Python接口自动化测试实战','done':True},
   {'id':2,'author':'无涯','name':'Selenium3自动化测试实战','done':False}
]

@app.route('/v1/api/books',methods=['GET'])
@auth.login_required
def get_books():
   return jsonify(books)


@app.route('/v1/api/books',methods=['POST'])
@auth.login_required
def create_books():
   if not request.json:
      abort(400)
   else:
      book={
         'id':books[-1]['id'] 1,
         'author':request.json.get('author'),
         'name':request.json.get('name'),
         'done':True
      }
      books.append(book)
      return jsonify({'msg':'created ok '},201)


@app.route('/v1/api/book/<int:book_id>',methods=['GET'])
@auth.login_required
def get_book(book_id):
   book=list(filter(lambda t:t['id']==book_id,books))
   if len(book)==0:
      abort(404)
   else:
      return jsonify({'status':0,'msg':'ok','datas':book})

@app.route('/v1/api/book/<int:book_id>',methods=['DELETE'])
@auth.login_required
def delete_book(book_id):
   book=list(filter(lambda t:t['id']==book_id,books))
   if len(book)==0:
      abort(404)
   else:
      books.remove(book[0])
      return jsonify({'status':1001,'msg':'课程信息已经删除成功'})

@app.route('/v1/api/book/<int:book_id>',methods=['PUT'])
@auth.login_required
def update_book(book_id):
   book=list(filter(lambda t:t['id']==book_id,books))
   if len(book)==0:
      abort(404)
   elif not request.json:
      abort(400)
   elif 'author' not  in request.json and 'name' not in request.json:
      abort(400)
   elif 'done' not in request.json and type(request.json['done']) is not bool:
      abort(400)
   else:
      book[0]['author']=request.json.get('author',book[0]['author'])
      book[0]['name'] = request.json.get('name', book[0]['name'])
      book[0]['done'] = request.json.get('done', book[0]['done'])
      return jsonify({'status':1002,'msg':'课程信息更新成功','dats':book})


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

在上面的案例代码中,定义了基础的员数据books,下来就是一系列的业务操作,每个业务操作都指定了访问URL地址,在每个业务上面都增加了基本的认证信息,也就意味着用户需要访问这些信息,需要经过认证。启动服务后,获取所有的课程信息,见如下的截图信息:

其它的API就不再演示,对上面的代码进行改造,使用类的方式编写,定义的类必须继承Response类,在类中依据业务的操作编写不同的方法,比很添加课程信息POST请求,获取课程信息GET方法,见修改后的源码:

代码语言:javascript复制
#!/usr/bin/env python
# -*-coding:utf-8 -*-
from flask import  Flask,make_response,jsonify,abort,request
from flask_restful import  Api,Resource
from flask_httpauth import  HTTPBasicAuth

app=Flask(__name__)
api=Api(app=app)
auth=HTTPBasicAuth()


@auth.get_password
def get_password(name):
   if name=='admin':
      return 'admin'
@auth.error_handler
def authoorized():
   return make_response(jsonify({'msg':"请认证"}),401)

books=[
   {'id':1,'author':'wuya','name':'Python接口自动化测试实战','done':True},
   {'id':2,'author':'无涯','name':'Selenium3自动化测试实战','done':False}
]

class Books(Resource):
   decorators = [auth.login_required]

   def get(self):
      return jsonify(books)

   def post(self):
      if not request.json:
         abort(400)
      else:
         book = {
            'id': books[-1]['id']   1,
            'author': request.json.get('author'),
            'name': request.json.get('name'),
            'done': True
         }
         books.append(book)
         return jsonify({'msg': 'created ok '}, 201)


class Book(Resource):
   decorators = [auth.login_required]

   def get(self,book_id):
      book = list(filter(lambda t: t['id'] == book_id, books))
      if len(book) == 0:
         abort(404)
      else:
         return jsonify({'status': 0, 'msg': 'ok', 'datas': book})

   def post(self,book_id):
      book = list(filter(lambda t: t['id'] == book_id, books))
      if len(book) == 0:
         abort(404)
      elif not request.json:
         abort(400)
      elif 'author' not in request.json and 'name' not in request.json:
         abort(400)
      elif 'done' not in request.json and type(request.json['done']) is not bool:
         abort(400)
      else:
         book[0]['author'] = request.json.get('author', book[0]['author'])
         book[0]['name'] = request.json.get('name', book[0]['name'])
         book[0]['done'] = request.json.get('done', book[0]['done'])
         return jsonify({'status': 1002, 'msg': '更新课程信息成功', 'dats': book})

   def post(self,book_id):
      book = list(filter(lambda t: t['id'] == book_id, books))
      if len(book) == 0:
         abort(404)
      else:
         books.remove(book[0])
         return jsonify({'status': 1001, 'msg': '课程的信息已经删除成功'})

api.add_resource(Books,'/v1/api/books')
api.add_resource(Book,'/v1/api/book/<int:book_id>')

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

修改的代码和上面的没多少差异,唯一不同的是通过类的方式编写,维护起来更加简单高效,依据业务的方法在类的方法中编写不同的业务就可以了。可能细心的同学注意到,修改课程信息和删除课程信息,我并没有使用PUT请求方法和DELETE请求方法,而是使用的是POST请求方法。这是因为HTTP/1.1的PUT方法和DELETE方法自身不带验证机制,任何人都可以对服务端进行操作,存在安全性的问题,因此一般不建议使用。当然如果配合WEB应用程序的验证机制,就可能开放使用PUT方法和DELETE方法。通过上面的案例代码,实现了一个简单的业务操作。在实际的工作应用中,可能会涉及到模拟程序,那么就可以使用flask-restful来进行应用,也可以采用unittest框架里面的mock,就看个人喜好而已。

感谢您的阅读,后续会陆续更新文章。谢谢您的关注!如您对我的书或者课程感兴趣,可扫描二维码购买,谢谢您!

0 人点赞