接口测试 unittest实用教程
Posted 墨迹测试
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了接口测试 unittest实用教程相关的知识,希望对你有一定的参考价值。
备注: 本文档针对 接口学习入门人群; ,中级 以及高级测试本篇文档请略过 ; 所有的实例数据来自于聚合数据平台 http://www.haoservice.com/apilist/
requests复习回顾
首先查看 request文件源码:
"""Constructs and sends a :class:`Request <Request>`.
:param method: method for the new :class:`Request` object.
:param url: URL for the new :class:`Request` object.
:param params: (optional) Dictionary or bytes to be sent in the query string for the :class:`Request`.
:param data: (optional) Dictionary or list of tuples ``[(key, value)]`` (will be form-encoded), bytes, or file-like object to send in the body of the :class:`Request`.
:param json: (optional) A JSON serializable Python object to send in the body of the :class:`Request`.
:param headers: (optional) Dictionary of HTTP Headers to send with the :class:`Request`.
:param cookies: (optional) Dict or CookieJar object to send with the :class:`Request`.
:param files: (optional) Dictionary of ``'name': file-like-objects`` (or ``{'name': file-tuple}``) for multipart encoding upload.
``file-tuple`` can be a 2-tuple ``('filename', fileobj)``, 3-tuple ``('filename', fileobj, 'content_type')``
or a 4-tuple ``('filename', fileobj, 'content_type', custom_headers)``, where ``'content-type'`` is a string
defining the content type of the given file and ``custom_headers`` a dict-like object containing additional headers
to add for the file.
:param auth: (optional) Auth tuple to enable Basic/Digest/Custom HTTP Auth.
:param timeout: (optional) How many seconds to wait for the server to send data
before giving up, as a float, or a :ref:`(connect timeout, read
timeout) <timeouts>` tuple.
:type timeout: float or tuple
:param allow_redirects: (optional) Boolean. Enable/disable GET/OPTIONS/POST/PUT/PATCH/DELETE/HEAD redirection. Defaults to ``True``.
:type allow_redirects: bool
:param proxies: (optional) Dictionary mapping protocol to the URL of the proxy.
:param verify: (optional) Either a boolean, in which case it controls whether we verify
the server's TLS certificate, or a string, in which case it must be a path
to a CA bundle to use. Defaults to ``True``.
:param stream: (optional) if ``False``, the response content will be immediately downloaded.
:param cert: (optional) if String, path to ssl client cert file (.pem). If Tuple, ('cert', 'key') pair.
:return: :class:`Response <Response>` object
:rtype: requests.Response
Usage::
>>> import requests
>>> req = requests.request('GET', 'http://httpbin.org/get')
<Response [200]>
"""
以下,对其中主要方法以及参数进行总结:
Requests.request(“请求方法的名字”,”URL”,可选参数)
1.params=字典 :
{ “id”:”1”,”name”:”张三”}
Python中的格式就字典 dict
javascript 中叫 json
Params是网址中的参数
2.data = Text 字符串:
data 有以下两种方式表述:
"Username = xxx&password=xxxpas"
示例:
response = requests.request("post" ,"http://localhost/index.php?m=user&c=public&a=login",data= "url_forward=&username=zhangsan&password=zhangsan")
[("Username"," xxx"),("password","xxxpas")]
示例:
data = [("url_forward",""),("username","zhangsan"),("password","zhangsan")]
response = requests.request("post" ,"http://localhost/index.php?m=user&c=public&a=login",data= data)
data是请求实体中的参数 ,请求实体类型 application/x-www-form-urlencoded
3.json=json
{"username":"xxx","password":"xxxpas"}
请求实体类型为 application/json
,通过请求实体发送的
4.headers
5.cookies 6.file
7.auth 认证
通过信息头发送 ;
8.timeout 超时
9.请求方法:类似 ;
Request.get(“URL”,可选参数)
Request.post(“URL”,可选参数)
Request.delete(“URL”,可选参数)
Request.put(“URL”,可选参数)
unittest
unittest是一个单元测试框架 ,类似于 java语言中的testng 和junit
作用: 用来组织和执行测试用例 ; 提供了常用的断言 ; 生成了比较丰富的日志信息(测试用例的数量, 测试结果执行的状态,以及测试执行的时间 ,错误用例的报错信息 …) ;提供了很多可扩展的东西(数据驱动测试是在unittest之上 ,生成 测试报告也需要在unittest基础之上,) ;
文本不过多展开讲解, 基本每行代码都进行了注释 ;
一、Pyhon工作原理—— 核心概念:test case, testsuite, TestLoder,TextTestRunner,TextTestResult, test fixture
TestCase(测试用例): 所有测试用例的基类,它是软件 测试中最基本的组成单元。
一个test case就是一个测试用例,是一个完整的测试流程,包括测试前环境的搭建setUp,执行测试代码(run),以及测试后环境的还原(tearDown)。测试用例是一个完整的测试单元,可以对某一问题进行验证。
TestSuite(测试套件):多个测试用例test case集合就是TestSuite,TestSuite可以嵌套TestSuite
TestLoder:是用来加载 TestCase到TestSuite中,其中有几个loadTestsFrom_()方法,就是从各个地方寻找TestCase,创建他们的实例,然后add到TestSuite中,再返回一个TestSuite实例
TextTestRunner:是来执行测试用例的,其中的run(test)会执行TestSuite/TestCase中的run(result)方法。
TextTestResult:测试结果会保存到TextTestResult实例中,包括运行了多少用例,成功与失败多少等信息
TestFixture:又叫测试脚手,测试代码的运行环境,指测试准备前和执行后要做的工作,包括setUp和tearDown方法
二、测试流程:
1.写好TestCase:一个class继承unittest.TestCase,就是一个测试测试用例,其中有多个以test开头的方法,那么 每一个这样的,在load的时候会生成一个TestCase实例。如果一个class中有四个test开头的方法,最后load到suite中时则有四个测试用例
2.由TestLoder加载TestCase到TestSuite
3.然后由TextTestRunner来运行TestSuite,运行的结果保存在TextTestResult中。
说明:
a:通过命令行或者unittest.main()执行时,main会调用TextTestRunner中的run来执行,或者可以直接通过TextTestRunner来执行用例
b:Runner执行时,默认将结果输出到控制台,我们可以设置其输出到文件,在文件中查看 结果,也可以通过htmlTestRunner将结果输出到HTML)
三、详细示例:
快速入门实例:
新建unittestDemo.py文件 ;
# 1.导入 unittest, unittest是python内置的代码库, 不需要单独下载 ;
import unittest
# 2.继承unittest代码库中的 TestCase测试用例类 ;
# 文件名一般首字母小写,类名首字母大写 , 文件名和类名一般就第一个字母不一样 ,
# 在java中 继承使用extends关键字 ,python中使用 小括号()
class UniittestDemo(unittest.TestCase):
chrome = "谷歌浏览器"
# 3. 重写父类中的 setUp 和 tearDown 方法
# 在 Python中 ,方法有一个关键字叫做 :def
# self是 方法的第一个默认参数,self类似于 java中的 this关键字 ;
# self 指的是当前类, 要想调用类中的属性或者方法, 前面需要加上self
# setUp是建立的意思,类似于testng中的 beforeMethod(),负责测试用例之前的准备工作 ;
def setUp(self):
print(1)
print(self.chrome)
# tearDown 是拆除销毁的意思, 类似于testng中的 afterMethod() ,负责测试用例执行后的恢复工作;
def tearDown(self):
print(2)
# 4. 编写 测试用例类
# 在 unittest中, 测试用例方法, 必须以test字符串开头, 类似于testng中,每个测试方法之上必须加@Test注解 ;
def test_login(self):
print(3)
# 默认打印 1 3 2 ,
# Python中对格式的要求比 java严格,遇到冒号就必须缩进 4个空格 为准
def test_register(self):
print(4)
# 每次执行测试用例 ,都会重新执行一遍setUp(), tearDown()方法 ;
# 如果光标在某个 方法内部运行程序, 那么只会运行该方法,
# 一般在测试用例类外面,我们写一个 main关键字方法 , 类似于java中 public static void mian(String[] args){}
# __name__ == '__main__'类似于主函数 ,在这段方法中写的代码,将不会被其他文件调用 ;(常用来做调试用)
if __name__ == '__main__':
# 默认执行当前文件中的测试用例方法 ;
# unittest.main(UniittestDemo)
unittest.main()
Output:
新建 mainDemo.py文件
# 一般方法 ,普通方法只有被调用才能执行
def read():
print(1)
read()
if __name__ == '__main__':
read()
# 这两种写法有什么区别 ??
# main()下面的read方法只能在当前文件执行;
# main上面的调用read方法 ,只要其他文件引用了这文件就会被执行;
# 所以如果想要在类外部直接调用某个方法, 一般都是 if __name__ == '__main__': 方法中执行 ;
新建 callMainDemo.py文件, 验证 if__name__=='__main__':
# 导包快捷键 ,光标点击红色波浪线 ~ Alt+Enter
from mainDemo import read
read()
断言
所有的测试用例都必须包含断言 ,一个测试用例中,可以包含多个断言 ; 断言是由unittest单元自动化测试框架提供的 ;
新建 answerRebotTest.py文件 ;
import unittest
import requests
class AnswerRebotTest(unittest.TestCase):
def setUp(self):
self.url = "http://apis.haoservice.com/efficient/robot"
def tearDown(self):
print(self.result)
def test_answer_rebot(self):
parameters = {"info": "你好美男子", "address": "", "key": "3b1cf1120c2347d4b2c48149abb3e7b5"}
response = requests.request("get",self.url ,params = parameters)
self.result =response.json()
# 第一个参数 期望结果 ,第二个参数 实际结果, 第三个参数 : 断言不通过时 ,提示信息
self.assertEqual('成功',self.result['reason'])
self.assertEqual(0,self.result['error_code'] )
self.assertEqual(100000,self.result['result']['code'])
# 编码代码时 ,要保持所有的测试用例都能 pass , 只有当回归测试或者数据驱动测试的时候,才有可能发现缺陷 ;
if __name__ == '__main__':
unittest.main()
数据驱动测试
读取csv文件的思路:
1.准备 csv文件 2.导入csv 代码库
3.指定需要读取的csv文件的路径 ;
4.打开 csv文件 ,
5.通过csv代码库提供的方法 ,读取csv文件中的内容
6.打印csv文件中的内容
文件示例如下:
数据文件 : answerRebotTestData.csv
新建 csvFileManager.py文件 ;
# 1. 准备 csv文件
# 2. 导入csv 代码库
import csv
# 3. 指定需要读取的csv文件的路径 ;
# 路径中的斜杠处理方式 有三种:
# 1.用双反斜线代替反斜线 2.在整个字符串前加 字母r ,用 r表示该字符串不存在转移字符 ;3.将反斜线改为正斜线
# 推荐 3, 使用正斜线可以跨平台
path = r"D:\pyworkspace\apitest\data\answerRebotTestData.csv"
# 4. 打开 csv文件 ,
file = open(path,'r')
# 5. 通过csv代码库提供的方法 ,读取csv文件中的内容
content = csv.reader(file)
# 6. 打印csv文件中的内容
print(content)
for row in content:
print( row)
# 测试用例类至少要调用这段代码, 才能得到csv文件中的数据
# 必须要把这段代码封装成一个方法,
# 详情见 csvFileManage2.py
测试用例如何接收读取的测试数据
1.导入ddt 即 data driver test ,不是内置的代码库需要单独下载
cmd : pip install ddt
2.准备好读取csv文件的方法
该方法需要有一个返回值,返回csv文件中的数据,以二维列表的方式显示所有数据
新建 csvFileManager2.py文件:
import csv
def readCsv(filename):
path = 'D:/pyworkspace/apitest/data/' +filename +'.csv'
file = open(path,"r")
content = csv.reader(file)
testdata = [] #申明一个空的列表
i = 0
for row in content:
if i ==0:
print("当前行为表头")
else:
testdata.append(row)
i= i+1
return testdata
if __name__ == '__main__':
testdata = readCsv("answerRebotTestData")
print(testdata)
3.在测试用例类上添加装饰器: @ddt.ddt
Python中的装饰器类似于java中的注解;
@ddt.ddt这个装饰器的作用 ,就是标志这个类采用ddt的方式提供测试数据
4.申明一个成员变量 ;
以 csvFileManage.readCsv(文件名)
的返回值作为变量的值
5.在test方法上添加装饰器 : @ddt.data(*成员变量的变量)
6.修改方法的参数列表,增加一个列表类型参数
7.修改方法体 ,用变量名称替代原来的字符串常量
添加ddt后,修改后的answerRebotTest.py文件如下:
import unittest
# 1.导入ddt 代码库
import ddt
import requests
# 2.为类添加装饰器
import csvFileManage2
@ddt.ddt
class AnswerRebotTest(unittest.TestCase):
# 3.申明一个成员变量,读取csv文件中的数据
test_data = csvFileManage2.readCsv("answerRebotTestData")
def setUp(self):
self.url = "http://apis.haoservice.com/efficient/robot"
def tearDown(self):
print(self.result)
# 4.为测试方法添加装饰器 @ddt.data(*variable)
# 在python中 ,给列表前面加上* 号, 表示把列表拆分为多个元素 ;
# example: list=[a,b,c]
# *list = a,b,c
# 这样就把一个list类型的元素, 拆分成了三个不同变量 ;
# list中有几个元素, 就会拆分为几个变量 ;
@ddt.data(*test_data)
# 5.在方法的参数列表中添加一个形参 ,这个形参代表一组测试数据 ,就是excel中的每一行 ;
def test_answer_rebot(self,row ):
# 6.用row[n]代替原来写死的字符串常量
parameters = {"info": row[1], "address": row[2], "key": row[0]}
response = requests.request("get",self.url ,params = parameters)
self.result =response.json()
# 第一个参数 期望结果 ,第二个参数 实际结果, 第三个参数 : 断言不通过时 ,提示信息
self.assertEqual(row[3],self.result['reason'])
# row[4] 默认从csv文件读取出来的是 text ,需要 int()方法进行转换 ;
self.assertEqual(int(row[4]),self.result['error_code'] )
# self.assertEqual(100000,self.result['result']['code'])
# 编码代码时 ,要保持所有的测试用例都能 pass , 只有当回归测试或者数据驱动测试的时候,才有可能发现缺陷 ;
if __name__ == '__main__':
unittest.main()
批量执行测试用例
1.找出所有测试用例 :
test_suite = unittest.defaultTestLoader.discover(目录,文件名规则)
2.执行找出的测试用例 :
unittest.TextTestRunner().run(test_suite)
将要测试的py文件统一放在 test_case目录 ;如图:
新建一个runallcases.py文件:
import unittest
if __name__ == '__main__':
# 1.找出所有的 unittest测试用例
# defaultTestLoader 默认的测试用例加载器
# 通过discover方法,设置规则 ,找出所有符合规则的测试用例 ;
#.表示当前路径, run_all_case.py在项目的根节点位置 ;
test_suite = unittest.defaultTestLoader.discover('./case_test', pattern='*.py', top_level_dir=None)
# 执行找到的所有测试用例 ;
# TextTestRunner()文本格式的测试用例器 ;用来执行测试用例的 ,
unittest.TextTestRunner().run(test_suite)
生成测试报告
1.导入HtmlTestRunner.py文件 (建议单独放在一个包内)
2.使用这个文件中的HtmlTestRunner类 ,代替unittest中的 TextTestRunner类,执行测试
通过类名, 一个是生成html格式的测试报告的测试用例执行器 , 另一个是生成文本日志格式 测试报告测试用例(只会打印在控制台) ;
3.现在生成一个新的文件,那么需要指定测试报告的保存路径 ;
在项目中创建一个report的文件夹
如图查看: 我在项目根目录下新建了package目录,将HTMLTestRunner.py文件拷贝进去 ,新建report目录,用来存放生成的测试报告 ;
使用 HtmlTestRunner.py如何生成测试报告呢? 见以下代码:
使用 HtmlTestRunner生成测试报告, runallcase.py文件内容完整如下:
import unittest
import sys
from package.HTMLTestRunner import HTMLTestRunner
if __name__ == '__main__':
# 1.找出所有的 unittest测试用例
# defaultTestLoader 默认的测试用例加载器
# 通过discover方法,设置规则 ,找出所有符合规则的测试用例 ;
#.表示当前路径, run_all_case.py在项目的根节点位置 ;
test_suite = unittest.defaultTestLoader.discover('./case_test', pattern='*.py', top_level_dir=None)
#
# 2a .执行找到的所有测试用例 ;
# TextTestRunner()文本格式的测试用例器 ;用来执行测试用例的 ,
# unittest.TextTestRunner().run(test_suite)
# 2b .用 HtmlTestRunner代替TextTestRunner
# stream 代表流的意思 , 这里要求填入一个2进制的文件流
# 3 .为生成的Html测试报告指定路径
path = "./report/"
file_path = path + "ApiTestReport.html"
file = open(file_path , "wb")
HTMLTestRunner(stream=file, verbosity=1,title="ApiTest接口自动化测试报告",description="学会使用unittest测试框架 ,soeasy", tester = "Young").run(test_suite)
右键 run 后 ,查看多了 ApiTestReport.html文件:
使用chrome浏览器进行查看 ;
查看通过的详情 截图:
查看通过详情信息:
至此 .本篇完结 ;
拂晓时分
我伫立在阒无一人的街角
我熬过了夜晚
——博尔赫斯
一切经得起再度阅读的语言,
一定值得再度思索
——梭罗
你穿过世事朝我走来 迈出的每一步都留下了一座空城 这时,一支从来世射出的毒箭命定了我 唯一的退路 --仓央嘉措
我这一生的种种 都是万事之来 往往顺其自然 当不得已处 实不愿拂逆旁人之意 宁可舍己从人
by Young
心念一转,万念皆转;心路一通,万路皆通。
以上是关于接口测试 unittest实用教程的主要内容,如果未能解决你的问题,请参考以下文章