什么是基于http的接口测试
- 接口测试的定义:是测试系统组件间接口的一种测试。接口测试主要用于检测外部系统与系统之间以及内部各个子系统之间的交互点。测试的重点是要检查数据的交换,传递和控制管理过程,以及系统间的相互逻辑依赖关系等
- 基于HTTP协议的接口测试
- 用例设计可以遵循3A原则
- 接口测试必须有断言,不然毫无意义
什么是3A原则
- 3A原则是单元测试用例编写时应该遵循的基本原则,在设计接口测试用例时,依然适用
- A: arrange 初始化测试数据,就是造数据,这里的数据有我们输入的数据,也有目标接口所涉及的资源,比如hr系统中的用户信息,我们必须先有几条人员的详细信息才能去测获取人员信息的接口(当然只是正常的流程,我们有时候还需要清掉数据以便测试资源为空的情况
- A: act 调用接口,传入输入数据
- A: assert 断言, 对返回的资源信息进行断言,比如获取用户信息的接口返回了用户信息之后,我们要判断返回的用户是不是我们想要的那个用户,我们获取的是李雷的信息,接口如果返回韩梅梅,那么接口的逻辑就是不对的
什么是unittest测试框架
- unittest是python自带的单元测试框架,尽管其主要是为单元测试服务的,但我们也可以用它来做接口的自动化测试
- unittest单元测试框架不仅可以适用于单元测试,还可以适用WEB自动化测试用例的开发与执行,该测试框架可组织执行测试用例,并且提供了丰富的断言方法,判断测试用例是否通过,最终生成测试结果。
- 想适用unittest框架必须先导入unittest库(import unittest)
- 测试类必须直接或间接继承unittest.TestCase类
- setUp(self)方法:在每个测试用例执行之前都会执行一次,是做数据初始化的好地方
- tearDown(self)方法:在每个测试用例执行之后都会执行一次
- setupclass(cls):所有的测试方法运行前运行,为单元测试做前期准备,但必须使用@classmethod装饰器进行修饰,整个测试过程中只执行一次
- tearDownClass():所有的测试方法运行结束后运行,为单元测试做后期清理工作,但必须使用@classmethod装饰器进行修饰,整个测试过程中只执行一次
- 所有测试方法的命名都需要以test开头,这样才能被框架识别到
- assert:unittest框架中的断言
- unittest.main():执行测试用例最简单的方式
使用unittest测试框架测试一个简单的接口(代码)
1 #!/usr/bin/env python
2 # -*- coding: utf-8 -*-
3 # @Time : 2018/11/27 14:19
4 # @Author : Weiqiang.long
5 # @Site :
6 # @File : 1.py
7 # @Software: PyCharm
8
9 import unittest
10 import requests
11
12
13 class test_v2ex_python(unittest.TestCase):
14 def setUp(self):
15 self.base_url = 'https://www.v2ex.com/api/nodes/show.json'
16
17 self.data = {'name':'python'}
18
19 def test_python(self):
20 res = requests.get(self.base_url, params=self.data)
21 result = res.json()
22 # print(result['name'])
23 self.assertEqual(result['name'], 'python')
24
25 if __name__ == '__main__':
26 unittest.main()
什么是json
- json是一种规定了格式的字符串
- {} 双括号表示对象
- [] 中括号表示数组
- "" 双引号内是属性或值
- : 冒号表示后者是前者的值(这个值可以是字符串、数字、也可以是另一个数组或对象)
什么是mock server
- 解决前后端依赖或第三方的依赖
- mock表示这个api返回的数据是假的,仅作为测试用的
- server表示需要启动服务,说到底这是一个服务程序
- 契约的描述工具:也就是契约长什么样子,用什么工具去定义才能让前后端团队秒懂
- 通过契约自动生成mock server实现,这样前端团队就可以拿来即用了,如果契约修改了,那么前端团队也很容易感知到
- 通过契约自动生成接口测试用例,这样通过持续运行这些接口测试用例,后端团队就可以第一时间发现契约的修改
如何使用flask实现一个简单的mock server(代码)
1 #!/usr/bin/env python
2 # -*- coding: utf-8 -*-
3 # @Time : 2018/11/27 14:19
4 # @Author : Weiqiang.long
5 # @Site :
6 # @File : 1.py
7 # @Software: PyCharm
8
9 from flask import Flask, jsonify, g
10 import copy
11
12
13 app = Flask(__name__)
14
15
16 @app.route("/") # 路由
17 def hello(): # handler
18 return "Hello World!"
19
20
21 @app.before_request
22 def set_up_data():
23 g.data = [
24 {'id': 1, 'title': 'task 1', 'desc': 'this is task 1'},
25 {'id': 2, 'title': 'task 2', 'desc': 'this is task 2'},
26 {'id': 3, 'title': 'task 3', 'desc': 'this is task 3'},
27 {'id': 4, 'title': 'task 4', 'desc': 'this is task 4'},
28 {'id': 5, 'title': 'task 5', 'desc': 'this is task 5'}
29 ]
30
31 g.task_does_not_exist = {"msg": "task does not exist"}
32
33 @app.route('/api/tasks')
34 def get_all_tasks():
35 return jsonify(g.data)
36
37 @app.route('/api/tasks/<int:task_id>')
38 def get_task(task_id):
39 if task_id > 0 and task_id <= len(g.data):
40 # 因为下标是从0开始的,为了更好的理解,所以这里-1,与下标保持一致
41 task_id -= 1
42 return jsonify(g.data[task_id])
43 else:
44 return jsonify(g.task_does_not_exist)
45
46 @app.route('/api/tasks/<int:task_id>', methods=['PUT'])
47 def complete_task(task_id):
48 if task_id > 0 and task_id <= len(g.data):
49 # 因为下标是从0开始的,为了更好的理解,所以这里-1,与下标保持一致
50 task_id -= 1
51 # print(task_id)
52 tmp = copy.deepcopy(g.data[task_id])
53 print(tmp)
54 tmp['done'] = True
55 return jsonify(tmp)
56 else:
57 return jsonify(g.task_does_not_exist)
58
59
60
61 if __name__ == '__main__':
62 app.run(debug=True)
什么是requests库,以及requests库的一些典型使用方法(代码)
什么是requests库:
- requests是python实现的简单易用的HTTP库
- pip安装:pip3 install requests
- 导入requests库:import requests
- requsts.get():获取网页,对应HTTP中的GET方法
- requsts.post():向网页提交信息,对应HTTP中的POST方法
- requsts.head():获取html网页的头信息,对应HTTP中的HEAD方法
- requsts.put():向html提交put方法,对应HTTP中的PUT方法
- requsts.patch():向html网页提交局部请求修改的的请求,对应HTTP中的PATCH方法
- requsts.delete():向html提交删除请求,对应HTTP中的DELETE方法
代码:
1 #!/usr/bin/env python
2 # -*- coding: utf-8 -*-
3 # @Time : 2018/11/28 10:02
4 # @Author : Weiqiang.long
5 # @Site :
6 # @File : 2.py
7 # @Software: PyCharm
8
9 import requests
10
11 base_url = 'http://127.0.0.1:8000/api/report_list'
12
13 # get方法
14 res = requests.get(url=base_url)
15 result = res.json()
16
17 # post方法
18 data1 = {'id':1}
19 res1 = requests.post(url=base_url, data=data)
20 result1 = res1.json()
21
22 # delete方法
23 data2 = {'id':1}
24 res2 = requests.delete(url=base_url, data=data)
25 result2 = res1.json()