python_UnitTest测试框架

一、requests模块

Ⅰ、 模块导入

requests模块非原生模块,所以要使用需要先进行安装,cmd中输入命令:pip install requests
如果是已经安装过的则展示安装所在的文件位置

如果安装完成后PyCharm中导入模块import requests标红报错

解决办法1:(可解决当前项目 import requests 问题,但新建一个项目可能又不行)

  • 打开pycharm->File->Settings->Project Interprete ,点击“+”号按钮
    在这里插入图片描述
  • 然后点击添加 ,搜requests,选中后点左下角的install ,等待安装完成即可,就不会报ModuleNotFoundError: No module named 'requests’这个错了
    在这里插入图片描述
    解决办法2:(新建一个项目也没问题)
  • https://blog.csdn.net/qq_21041889/article/details/94392538

Ⅱ 、发送请求 / 获取响应结果

发送请求:

reques t[ rɪ'kwest ]
r = requests.方法(url, headers,data, ···)

其中url必填,其他参数根据实际情况选择性使用,发送请求后悔获取响应结果,然后把结果赋值给变量,最后通过变量的属性值取出需要的结果
获取结果:

response [ rɪ'spɒns ]
response.headers			获取返回的头信息
response.text				获取返回的主体
response.cookies			获取返回的cookie
response.status_code		获取返回的状态码
···

实操:

import requests
# 访问网易首页,并获取返回状态码
test_url = "http://www.163.com"
r = requests.get(test_url)
print(r.status_code)

# 输出
200

Ⅲ、常用参数

url:
唯一必填参数,上方有说明

headers:
模拟手机端访问网易首页,这时候就需要带上headers参数,通过抓包可发现headers有个字段"User-Agent",而服务器就是通过这个字段来判断访问的来源,代码如下:

import requests
# 访问网易首页,并获取返回状态码
test_url = "http://www.163.com"
h = {
    
    "User-Agent":"Android/BKL-AL00/9.0.0/"}
r = requests.get(test_url, header = h)
print(r.status_code)

cookies:
cookies参数以字典形式发送,只需要对应的将namevalue传入即可,代码如下:

import requests

test_url = "http://mail.163.com/js6/main.jsp?sid=xkjskjsnlsoakskoa&df=163nav_icon"
c = "JSESSIONID=6272e7c3762fa26619780af615a75a0b"
h = {
    
    "User-Agent":"Android/BKL-AL00/9.0.0/"}
r = requests.get(test_url, header = h, cookies = c)
print(r.status_code)

params: 可以存放请求的表单,并会以key1=value1&key2=value2的形式跟在url之后发送,为了区分url和参数,最好不要把表单放在url中,可以通过params参数来分离

import requests

# 分离 (test_url = "http://mail.163.com/js6/main.jsp?sid=xkjskj&df=163nav_icon")

test_url = "http://mail.163.com/js6/main.jsp"
p = ("sid":"xkjskj", "df":"163nav_icon") # 将需要发送的表单以字典的形式赋值到变量p中
h = {
    
    "User-Agent":"Android/BKL-AL00/9.0.0/"}
r = requests.get(test_url, params = p)
print(r.status_code)

data: 此参数也是用于存放请求的表单,是request模块最重要的参数之一

补充:
params和data的区别:
params > params是添加到url的请求字符串中的,用于get请求,只能提交一种类型的数据"字符串"
data > 添加到请求体(body)中的, 用于post请求

post请求: 可以提交4种类型的数据,取决与服务器接收的数据类型,post的数据类型需要和服务器接收的一致,不然服务器就无法正确识别post的数据,导致测试结果报错。

  • post四种数据类型:
    • application/json: Content-Type:application/json作为响应头大家肯定不陌生,现在越来越多的人把它作为请求头,用来告诉服务端消息主体是序列化后的 JSON 字符串。
    • application/x-www-form-urlencoded
    • multipart/form-data
    • text/xml

Ⅳ、porttest

  • 请求简介:
  • 不带params的get请求,一般是请求静态页面,大多数只用来测试页面是否存在,返回数据是否正常
  • 带params的get请求,一般是查询请求
  • 带form的post请求,一般是修改/提交/查询…数据

二、有效可用调试接口


`https接口`

淘宝查询电话号码归属地(可用)

https://tcc.taobao.com/cc/json/mobile_tel_segment.htm?tel=手机号

百付宝接口(可用)

https://www.baifubao.com/callback?cmd=1059&callback=phone&phone=手机号

`http接口`

快递接口:
http://www.kuaidi100.com/query?type=快递公司代号&postid=快递单号

ps:快递公司编码:申通=”shentong” EMS=”ems” 顺丰=”shunfeng” 圆通=”yuantong” 中通=”zhongtong” 
韵达=”yunda” 天天=”tiantian” 汇通=”huitongkuaidi” 全峰=”quanfengkuaidi” 德邦=”debangwuliu” 宅急送=”zhaijisong”

谷歌接口(不确定是否可用)
FeedXml转json接口:

http://ajax.googleapis.com/ajax/services/feed/load?q=Feed地址&v=1.0

备选参数:callback:&callback=foo就会在json外面嵌套foo({
    
    })方便做jsonp使用。

备选参数:n:返回多少条记录。

音乐接口
QQ空间音乐接口(可用)

http://qzone-music.qq.com/fcg-bin/cgi_playlist_xml.fcg?uin=QQ号码&json=1&g_tk=1916754934

QQ空间收藏音乐接口(可用)

http://qzone-music.qq.com/fcg-bin/fcg_music_fav_getinfo.fcg?dirinfo=0&dirid=1&uin=QQ&p=0.519638272547262&g_tk=1284234856

多米音乐接口(可用)

http://v5.pc.duomi.com/search-ajaxsearch-searchall?kw=关键字&pi=页码&pz=每页音乐数

soso接口(可用)

http://cgi.music.soso.com/fcgi-bin/fcg_search_xmldata.q?source=10&w=关键字&perpage=1&ie=utf-8

地图接口
阿里云根据地区名获取经纬度接口(可用)

http://gc.ditu.aliyun.com/geocoding?a=苏州市

参数解释: 纬度,经度type 001 (100代表道路,010代表POI001代表门址,111可以同时显示前三项)

阿里云根据经纬度获取地区名接口(可用)

http://gc.ditu.aliyun.com/regeocoding?l=39.938133,116.395739&type=001

IP接口
新浪接口(ip值为空的时候 获取本地的)(可用)

http://int.dpool.sina.com.cn/iplookup/iplookup.php?format=json&ip=218.4.255.255

手机信息查询接口
淘宝网接口(可用)

http://tcc.taobao.com/cc/json/mobile_tel_segment.htm?tel=手机号

获取QQ昵称和用户头像(可用,不过会提示登录)

http://r.qzone.qq.com/cgi-bin/user/cgi_personal_card?uin=QQ

三、断言方法汇总

assertEqual:A为预期值,B为实际值

方法 解释
assertEqual(a, b) 判断ab是否相等
assertNotEqual(a, b) 判断ab不相等
assertIs(a, b) 判断a是b
assertIsNot(a, b) 判断a不是b
assertIsNone(a) 判断a是不是None
assertIsNotNone(a) 判断a不是None
assertIn(a,b) 判断a在b中,此时a与b可以相等
assertNotIn(a, b) 判断a不在b中
assertIsInstance(a, b) 判断a是否属于b的实例
assertNotIsInstance(a, b) 判断a不属于b的实例
assertGreater(a, b) 判断a > b
assertGreaterEqual(a, b) 判断a >= b
assertLess(a, b) 判断a < b
assertLessEqual(a, b) 判断a <= b

四、UnitTest测试框架

  • UnitTest Unit :单元 [ 'juːnɪt ]
    • testcase(测试用例)
    • testsuite(测试套件):多个测试用例组成一个测试套件
    • testfixtrue(测试固件):整合了代码中相同的公共部分,减少代码冗余,比如通过setup()进行初始化,同样的还可以使用teardown()来结束测试工作
    • testrunner(测试运行器):给测试用例提供运行环境,通过它的run()方法,来执行测试用例,并在执行完成后把结果输出在testresult
      · HTMLTestRunner(测试报告)

Ⅰ、testcase(测试用例)

需要通过继承TestCase类来构建测试用例,既可以一个测试用例生产一个类,也可以多个测试用例生产一个类,后者执行效率更高效,构建代码格式如下:

	calss 测试类名(unittest.TestCase):   # 这个类继承了unittest的TestCase的基类
		testcase1
		testcase2
		...

实际代码:

import unittest
import requests

class VersionTest(unittest.TestCase):
    def test1(self):
        url = "https://jdsq.jdsq360.com/wx/version/check"
        form = ({
    
    "version": "1.1.6", "type": "vp"})
        r = requests.post(url, data=form)
        self.assertEqual(r.text, "验证成功!")    # r.text返回主体
        
    def test2(self):
        url = "https://jdsq.jdsq360.com/wx/version/check"
        form = ({
    
    "version": "1.1.7", "type": "vp"})
        r = requests.post(url, data=form)
        self.assertEqual(r.text, "验证失败!")

Ⅱ、testsuite(测试套件)

完成了 testcase准备工作,进行组合时就需要用到testsuite suite:套 [ swiːt ]

import unittest
import requests

class VersionTest(unittest.TestCase):
    def test1(self):
        # 省略之前代码
    def test2(self):
        # 省略之前代码
        
# 1
def suite():
    vt = unittest.TestSuite()       # TestSuite重点,勿写错!!!!!
    vt.addTest(VersionTest("test1"))  # 把"test1"的用例都导入套件
    vt.addTest(VersionTest("test2"))  # 把"test2"的用例都导入套件
    return vt

# 2
def suite():
    vt = unittest.makeSuite(VersionTest, "test")  # 把所有"test"开头的用例都导入套件
    return vt

Ⅲ、test runner(测试运行器)

import unittest
import requests

class VersionTest(unittest.TestCase):
    def test1(self):
        # 省略之前代码
    def test2(self):
        # 省略之前代码
        
# 1
def suite():
    # 省略之前代码

if __name__ == '__main__':
	# 方法1
	# 运行套件suite()中的testcase
    unittest.TextTestRunner().run(suite())    
    
    # verbosity 参数可以控制输出的错误报告的详细程度,不填写默认为1,详情见补充内容
    unittest.TextTestRunner(verbosity=2).run(suite())    
    
    # 方法2
    unittest.main()   # 所有操作封装在main方法中,完成所有testcase的加载和运行

补充verbosity 参数内容:
0 (静默模式): 你只能获得总的测试用例数和总的结果 比如 总共100个 失败20 成功80
1 (默认模式): 非常类似静默模式 只是在每个成功的用例前面有个“.” 每个失败的用例前面有个 “F”
2 (详细模式):测试结果会显示每个测试用例的所有相关的信息

Ⅳ、HTMLTestRunner(测试报告)

下载地址:http://tungwaiyip.info/software/HTMLTestRunner.html
在这里插入图片描述
此模板基于python 2.x写的,如果使用python 3.x的话需要做以下修改:

94行: 引入的名称,从import StringIO改成import io
539行: self.outputBuffer=StringIO.StringIO()改成self.outputBuffer=io.StringIO()

631行: print>>sys.stderr,'\nTime Elapsed:%s' % (self.stopTime-self-startTime)改成:
              print(sys.stderr, '\nTime Elapsed: %s' % (self.stopTime-self.startTime))

642行: if not rmap.has_key(cls):改成if not cls in rmap:
766行: uoo.decode('latin-1')改成uo = e
772行: ue = e.decode('latin-1')改成ue = e
778行: output = saxutils.escape(uo+ue),改成output = saxutils.escape(str(uo)+str(ue)),

存储路径:
将修改的文件存放在Pythonx.x安装路径Lib文件夹下

尝试运行:

import unittest
import requests
import HTMLTestRunner

class VersionTest(unittest.TestCase):
    def test1(self):
        # 省略之前代码
    def test2(self):
        # 省略之前代码
        
# 1
def suite():
    # 省略之前代码

if __name__ == '__main__':
    fr = open("testreal.html", "wb") # 新建一个testreal.html文件,并设置读写权限为读写
    runner = HTMLTestRunner.HTMLTestRunner(stream=fr, title="测试报告", description="详情")
    runner.run(suite())
       
    # 使用HTMLTestRunner模块中的HTMLTestRunner方法,构建一个运行器对象,并通过参数将结果写入testreal.html文件
    # 标题为"测试报告",描述为"详情",最后也是通过run()方法完成运行

五、实际问题汇总

Ⅰ、测试报告不生成

1、无报错:
PyCharm会默认使用自带的unittest框架来执行单元测试,不会执行main函数中的代码,所以不生成测试报告 ,判断可查看右上角文件名前有 Unittests in 文件名
在这里插入图片描述
解决:
在这里插入图片描述
2、有报错:
报错信息:.<_io.TextIOWrapper name=’’ mode=‘w’ encoding=‘UTF-8’>
解决:HTMLTestRunner.py文件修改631行,1或者2修改为3保存即可解决
1、print >> sys.stderr, ‘\nTime Elapsed: %s’ % (self.stopTime-self.startTime)
2、print(sys.stderr, ‘\nTime Elapsed: %s’ % (self.stopTime-self.startTime))
3、sys.stderr.write(’\nTime Elapsed: %s\n’ % (self.stopTime - self.startTime))

Ⅱ、处理josn返回数据

1、转换为字典

import json

AA = {
    
    
    "statusCode": 200,
    "data": {
    
    
        "totoal": "5",
        "height": "5.97",
        "weight": "10.30",
        "age": "11"
    },
    "msg": "成功"
}

s = json.dumps(AA)  # dumps:把字典AA转换为json字符串
s1 = json.loads(s)  # loads:把json转换为dict

print(s1["statusCode"]) # 打印statusCode对应的值   200
print(s1["data"]["age"])   # 打印AA里  data下age对应的值   11
print(len(s1["data"]))   # 打印AA里    data对应的值的个数   4
print(len(s1))   # 打印AA里值对的个数   3
import json

  def test3(self):
        test_url = "https://xxx.goho.co/jdshop/api/wxapp/store/getBanner"
        r = requests.get(test_url)
        s1 = json.loads(r.text)        
        self.assertEqual(len(s1), 3)      # 判断数量是否为3
        
        # json.loads()返回josn数据主体转换为python字典,并赋值给s1
        # r.text 接口返回主体(是josn数据格式)
		 #  len(s1)获取字典内元素个数

Ⅲ、处理返回的cookies

response.cookies是获取response中cookie属性,返回的<class ‘requests.cookies.RequestsCookieJar’>,是一个类
response.cookies.get_dict()返回的是字典格式cookie
Eg:

import requests

url = "https://xxx.jdsq360.com/api/store/storer/login"
p = {
    
    "account": "wanglixin", "pwd": "123456"}
r = requests.get(url, params=p)
cookies = r.cookies.get_dict()
print(r.cookies)
print(cookies)

# 输出结果
<RequestsCookieJar[<Cookie JSESSIONID=B889AF415023FFD986C8E389CD9DFD58 for haohuo.jdsq360.com/>]>
{
    
    'JSESSIONID': 'B889AF415023FFD986C8E389CD9DFD58'}

Ⅳ、生成测试报告报错

1、 报错信息:<_io.TextIOWrapper name='<stderr>' mode='w' encoding='UTF-8'>

解决方案:
HTMLTestRunner.py的631行,此时可能是1或者2,修改为3
1.print >> sys.stderr, '\nTime Elapsed: %s' % (self.stopTime-self.startTime)
2.print(sys.stderr, '\nTime Elapsed: %s' % (self.stopTime-self.startTime))
3.sys.stderr.write('\nTime Elapsed: %s\n' % (self.stopTime - self.startTime)) <<< 修改为此内容即可

2、 报错信息:requests.exceptions.SSLError: HTTPSConnectionPool

解决方案1:抓包工具忘记关windows抓包导致证书错误,关闭即可.

猜你喜欢

转载自blog.csdn.net/qq_38123721/article/details/94824785
今日推荐