【接口测试】-Unitttest测试框架

2021-09-27

领导安排要做接口自动化,也没说怎么搞,那就按照自己的想法搞呗。
调研了几款框架,有利有弊,先从简单的用起来吧,利用空闲时间,写了几个简单的接口,初步实现,后续慢慢优化吧。

为什么要使用unittest?

在编写接口自动化用例时,一般一个接口建立一个.py文件,一条测试用例封装为一个方法,但是在批量执行的过程中,如果有一条出错,后面的用例就无法执行。使用测试框架可以避免这种情况。

当然我们要用还是简单了解下unittest

unittest有哪些特点

  • python自带测试框架,不用安装
  • 用例执行互相不干扰
  • 提供不同范围的setUp(测试准备)和tearDown(测试清理)方法
  • 提供丰富的断言方法
  • 可以通过discover批量执行所有模块的用例
  • 可以通过TestSuite(测试集)比较灵活的组织用例

编写用例

  • 新建一个test_开头(必须)的.py文件,如test_user_login.py
  • 导入unittest
  • 编写一个Test开头(必须)的类,并继承unittest.TestCase,做为测试类
  • 在类中编写一个test_开头(必须)的方法,作为用例

文件必须test_开头 test_teacher.py

import requests
import unittest

class TestTeacherEdit(unittest.TestCase): # 类必须Test开头,继承TestCase才能识别为用例类
	url = "http://api/xxx/teacher/xxx"

	def test_teacher_edit(self): # 一条测试用例,test_开头
		data = {
		'wechat_id': '',
		'auth_username': 'caolihui',
		'real_name': '曹立辉',
		'wx_nickname': '帅辉55',
		'auth_uid': '1000002640',
		'mid': '1627976031427201',
		'employee_id': 'W0006634',
		'id': '368',
		'type': '1',
		'auth_role': '',
		'owner_id': '0',
		'status': '1',
		'create_time': '2021-09-07 16:28:06',
		'update_time': '2021-09-07 16:28:06'
		}
		files=[

		]

		headers = {
		  'Cookie': c_token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ8rliLrbhe-hoOSQFs7Na6PGY}'
		}
		response = requests.post(url=self.url, headers=headers, files=files, data=data)
		self.assertIn('200', response.text)  # 断言
		print('老师编辑成功')

if __name__ == '__main__':  		# 如果是直接从当前模块执行(非别的模块调用本模块)
	unittest.main(verbosity=2)    	# 运行本测试类所有用例,verbosity为结果显示级别

用例断言

unittest断言方法,常用的以下几种:

判断相等
  • assertEqual(a,b)/assertNotEqual(a,b): 断言值是否相等
  • assertIs(a,b)/assertIsNot(a,b): 断言是否同一对象(内存地址一样)
  • assertListEqual(list1, list2)/assertItemNotEqual(list1, list2): 断言列表是否相等
  • assertDictEqual(dict1, dict2)/assertDictNotEqual(dict1, dict2): 断言字典是否相等
是否为空
  • assertIsNone(a)/assertIsNotNone(a)
判断真假
  • assertTrue(a)/assertFalse(a)
是否包含
  • assertIn(a,b)/assertNotIn(a,b) # b中是否包含a
大小判断
  • assertGreater(a,b)/assertLess(a,b) : 断言a>b / 断言a<b
  • assertGreaterEqual(a,b)/assertLessEqual: 断言a>=b / 断言a<=b
类型判断
  • assertIsInstance(a,dict)/assertNotIsInstance(a,list) # 断言a为字典 / 断言a非列表

实例

import unittest

case = unittest.TestCase()
case.assertEqual(1,2.0/2) # 通过1=2.0/2
case.assertEqual(1, True) # 通过
case.assertIs(1.0, 2.0/2) # 失败,不是同一对象
case.assertListEqual([1,2],[1,2]) # 通过(顺序要一致)
case.assertDictEqual({"a":1,"b":2},{"b":2,"a":1}) # 通过,字典本无序
case.assertIsNone({}) # 失败
case.assertFalse({}) # 通过,空字典为False
case.assertIn("h","hello") # 通过
case.assertGreater(3,2) # 通过,3>2
case.assertIsInstance({"a":1}, dict) # 通过

执行结果
image.png

完整的接口测试用例

  • 数据准备:准备测试数据,可手工准备,也可使用代码准备(通常涉及数据库操作)
  • 环境检查:如果手工准备的数据,连接数据库进行环境检查会使用例更健壮
  • 发送请求:发送接口请求
  • 响应断言/数据库断言:响应断言后,还需要进行数据库断言,以确保接口数据库操作的正确性
  • 数据清理:如果接口有更数据库操作,断言结束后需要还原更改
    本次教程暂不涉及

用例组织及运行

import unittest
# 从两个用例里导入测试类 
from test_teacher import TestTeacherEdit 
from test_query import Testquery 
from HTMLTestReportCN import HTMLTestRunner

suite = unittest.TestSuite()
# 添加单个用例
suite.addTest(TestTeacherEdit('test_teacher_edit')) 
# 添加多个用例
suite.addTests([Testquery('test_teacher_c'),Testquery('test_periods_c'),Testquery('test_class_c'),Testquery('test_first_polling')])  

# 运行测试集,verbosity显示级别,运行顺序为添加到suite中的顺序																	
unittest.TextTestRunner(verbosity=2).run(suite) 

生成测试报告

生成文本报告
import unittest
# 从两个用例里导入测试类 
from test_teacher import TestTeacherEdit 
from test_query import Testquery 
from HTMLTestReportCN import HTMLTestRunner

suite = unittest.defaultTestLoader.discover("./")
生成HTML报告
  • 下载HTMLTestRunnerCN
  • 解压并将解压包中python3x文件夹下的HTMLTestRunnerCN.py拷贝到项目目录
  • 在目录下新建脚本run_all_xxx.py
import unittest
# 从两个用例里导入测试类 
from test_teacher import TestTeacherEdit 
from test_query import Testquery 
from HTMLTestReportCN import HTMLTestRunner

suite = unittest.defaultTestLoader.discover("./")

f = open("report.html", 'wb') # 二进制写格式打开要生成的报告文件
HTMLTestRunner(stream=f,title="自动化测试系统",description="xxxx接口测试",tester="曹立辉").run(suite)
f.close()
  • 运行程序,会在当前文件夹下生成report.html,用浏览器打开即可
    image.png

到此基本实现了一个简单的接口自动化。