unittest里discover用法_unittest框架核心要素及应用

1. unittest核心要素

  • unittest介绍
    • 测试框架,不仅仅用于单元测试
    • python自动的测试包
    • 用法和django.test.TestCase类似

1.1【知道】unittest介绍和核心要素

c3ce599e6ec946fdc0f81c8d5feeb0a1.png

1.2【掌握】unittest核心要素的使用

"""
1. 测试用例
2. 容器,容器添加测试用例
3. 运行容器中的测试用例
"""
import unittest
​
# 测试类,继承于unittest.TestCase
class MyTest(unittest.TestCase):def test_1(self):print('test_1')
​def test_2(self):print('test_2')
​
if __name__ == '__main__':# 类的外面# 2. 容器,容器添加测试用例suite = unittest.TestSuite()# 测试用例的执行顺序,按添加的顺序执行suite.addTest(MyTest('test_1'))suite.addTest(MyTest('test_2'))
​# 3. 运行容器中的测试用例runner = unittest.TextTestRunner()runner.run(suite)

注意:只能通过命令运行

python xxx.py

1.3【知道】Fixture

  • 测试类中:实现了前、后置方法,它就是一个fixture

1.4【掌握】defaultTestLoader

"""
1. 测试用例
2. 容器,容器添加测试用例
3. 运行容器中的测试用例
"""
import unittest
​
# 测试类,继承于unittest.TestCase
class MyTest(unittest.TestCase):def test_1(self):print('test_11111111111111')
​def test_2(self):print('test_22222222222222')
​
if __name__ == '__main__':# 2. 容器,容器添加测试用例# 默认找指定路径下,所有test开头的文件# 参数1:路径,参数2:指定的文件suite = unittest.defaultTestLoader.discover('./', 'test_2_demo.py')
​# 3. 运行容器中的测试用例runner = unittest.TextTestRunner()runner.run(suite)

注意:只能通过命令运行

python xxx.py

2.【掌握】unittest基本使用

"""
1. 导入unittest模块
2. 新建类,继承于unittest.TestCase
3. 类中方法1. 前、后置(不是必须的,有前置必须写后置,匹配的)2. test开头的测试用例(测试用例中有断言)
4. unittest.main()运行测试
"""
import unittest
​
class MyTest(unittest.TestCase):@classmethoddef setUpClass(cls) -> None:print('setUpClass')
​@classmethoddef tearDownClass(cls) -> None:print('tearDownClass')
​def setUp(self) -> None:print('setUp')
​def tearDown(self) -> None:print('tearDown')
​def test_1(self):print('test_1111111')
​def test_s(self):print('test_s')a = 1 + 1self.assertEqual(a, 2, '结果不为2')
​def test_f(self):print('test_f')a = 1 + 2self.assertEqual(a, 3, '结果不为3')
​def xxx_xxx(self): # 不会执行非test开头的方法print('xxxxx')
​
if __name__ == '__main__':unittest.main()
  • 测试用例运行顺序:0~9, A~Z, a~z
  • python代码运行,pycharm直接右击运行,等价于:python xxx.py

3.【知道】断言

# arg1和arg2相等,测试通过,标志为 .
# arg1和arg2不相等,测试不通过,标志为 F,抛出异常,显示msg的信息
unittest.assertEqual(arg1, arg2, msg=None)

4.【掌握】参数化

import unittest
from parameterized import parameterized # 需要先安装模块
​
class MyTest(unittest.TestCase):def setUp(self) -> None:print('setUp')
​def tearDown(self) -> None:print('tearDown')# 1. 参数化参数:列表套元组# 2. 列表有几个元素,测试用来执行几次# 3. 元组元素的位置匹配测试用例的形参@parameterized.expand([('mike', '123'), ('yoyo', 'abc')])def test_params(self, name, pwd):print('name = %s, pwd = %s'%(name, pwd))
​
​
if __name__ == '__main__':unittest.main()

5. mock

5.1 mock介绍

715141fca957e55df4129c01c8cb6861.png

5.2 Mock 类基本使用

5.2.1【掌握】return_value

import unittest
import unittest.mock
​
class MyTest(unittest.TestCase):def test_return(self):# 1. 创建Mock()对象,给return_value关键字传参mock_obj = unittest.mock.Mock(return_value=250)# mock_obj是对象,可调用对象,用法和函数一样ret = mock_obj()print(ret)

5.2.2【知道】side_effect

import unittest
import unittest.mock
​
class MyTest(unittest.TestCase):def test_except(self):# 1. 创建Mock()对象,传递异常对象mock_obj = unittest.mock.Mock(side_effect=BaseException('自定义异常'))# mock_obj是对象,可调用对象,用法和函数一样mock_obj()
​def test_list(self):# 1. 创建Mock()对象,传递listmock_obj = unittest.mock.Mock(side_effect=[1,2,3])# mock_obj是对象,可调用对象,用法和函数一样print(mock_obj())print(mock_obj())print(mock_obj())print(mock_obj()) # err, StopIteration
​def test_func(self):def func(a, b):return a+b
​# 1. 创建Mock()对象,传递函数名mock_obj = unittest.mock.Mock(side_effect=func)# mock_obj是对象,可调用对象,用法和函数一样print(mock_obj(1, 1))# TypeError: func() missing 2 required positional arguments: 'a' and 'b'mock_obj()

5.2.3【掌握】mock案例

f507ac80e52be4dd8b9bdf61ad77c28a.png

5.3 限制模拟的范围

class MyTest(unittest.TestCase):def test_1(self):# unittest.mock.Mock# 通过这种方式Mock后,后面调用的测试用来也有效果(保证mock先执行)pay.pay_way = unittest.mock.Mock(return_value={"result": "success", "reason":"null"})
​ret = pay_status.pay_way_status()print("test_1 = ", ret)self.assertEqual(ret, '支付成功', '支付失败')
​def test_2(self):ret = pay_status.pay_way_status()print("test_2 = ", ret)self.assertEqual(ret, '支付成功', '支付失败')

5.3.1【掌握】mock.path

5.3.2【掌握】patch 上下文管理器

  • 通过mock.path或者patch 上下文管理器,限制mock范围
  • patch 上下文管理器注意作用域问题
import unittest
import unittest.mock
import pay
import pay_status
​
​
class MyTest(unittest.TestCase):@unittest.mock.patch('pay.pay_way')def test_1(self, mock_obj):mock_obj.return_value = {"result": "success", "reason":"null"}
​ret = pay_status.pay_way_status()print("test_1 = ", ret)self.assertEqual(ret, '支付成功', '支付失败')
​def test_3(self):with unittest.mock.patch('pay.pay_way') as mock_obj:mock_obj.return_value = {"result": "success", "reason":"null"}
​ret = pay_status.pay_way_status()print("test_3 = ", ret)self.assertEqual(ret, '支付成功', '支付失败')
​
​def test_2(self):ret = pay_status.pay_way_status()print("test_2 = ", ret)self.assertEqual(ret, '支付成功', '支付失败')
​
if __name__ == '__main__':unittest.main()

5.4【掌握】类方法替换

from unittest import mock
import unittest
​
class Pay(object):def pay_way(self):"""假设这里是一个支付的功能,未开发完支付成功返回:{"result": "success", "reason":"null"}支付失败返回:{"result": "fail", "reason":"余额不足"}reason返回失败原因"""raise NotImplementedError('代码还没有实现')
​def pay_way_status(self):"""根据支付的结果success或fail,判断跳转到对应页面假设这里的功能已经开发完成"""
​# todo 此时pay_way()函数并未完成!你先假定他完成了result = self.pay_way()print(result)
​if result["result"] == "success":return "支付成功"if result["result"] == "fail":return "支付失败"
​
class TestPayStatues(unittest.TestCase):'''单元测试用例'''def test_1(self):p = Pay()p.pay_way = unittest.mock.Mock(return_value={"result": "success", "reason":"null"})
​ret = p.pay_way_status()self.assertEqual(ret, '支付成功', '测试失败')
​@unittest.mock.patch.object(Pay, 'pay_way')def test_2(self, mock_obj):mock_obj.return_value={"result": "success", "reason":"null"}
​p = Pay()ret = p.pay_way_status()self.assertEqual(ret, '支付成功', '测试失败')
​def test_3(self):with unittest.mock.patch.object(Pay, 'pay_way') as mock_obj:mock_obj.return_value={"result": "success", "reason":"null"}p = Pay()ret = p.pay_way_status()self.assertEqual(ret, '支付成功', '测试失败')

5.5 常用的方法和属性

import unittest
import unittest.mock
​
​
class MockTest(unittest.TestCase):def test_return_value(self):mock_obj = unittest.mock.Mock(return_value=1999)result = mock_obj()print(result)  # 打印 1999
​mock_obj()print(mock_obj.called)  # 是否被调用过, 返回布尔值print(mock_obj.call_count)  # 获取调用测试, 返回调用测试

6. 测试报告

6.1【知道】HTMLTestRunner

"""
0. 导包, import unittest
1. 定义类,继承unittest.TestCase
2. 是一个fixture, 有前置后置方法
3. 有test开头的测试用例,结果用断言判断
4. 运行测试
"""
import unittest
from HTMLTestRunner.HTMLTestRunner import HTMLTestRunner # 需要安装插件
​
​
class MyTest(unittest.TestCase):def setUp(self) -> None:print('setUp')
​def tearDown(self) -> None:print("tearDown")
​@classmethoddef setUpClass(cls) -> None:print('setUpClass')
​@classmethoddef tearDownClass(cls) -> None:print('tearDownClass')
​def test_1_add(self):num = 1 + 2print('test_add')self.assertEqual(num, 3, msg='加法错误')
​def test_2_sub(self):num = 1 - 1print('test_sub')self.assertEqual(num, 3, msg='减法错误')
​
​
if __name__ == '__main__':# 1. 把测试用例添加到suite容器中suite = unittest.defaultTestLoader.discover('./', 'test_1.py')
​# 2. 打开文件,是一个文件对象with open('./HTMLTestRunner.html', 'w', encoding='utf-8') as f:# 3. HTMLTestRunner()创建一个runner对象runner = HTMLTestRunner(stream=f,  # 测试报告需要写入到的文件verbosity=2,  # 控制台输出信息的详细程度, 默认为1title='这是报告标题',  # 测试报告的标题description='这是一个测试报告内容'  # 测试报告的描述)# 4. runner把容器中测试用例运行runner.run(suite)

6.2【知道】BeautifulReport

import unittest
from BeautifulReport import BeautifulReport
​
​
class MyTest(unittest.TestCase):def setUp(self) -> None:print('setUp')
​def tearDown(self) -> None:print("tearDown")
​@classmethoddef setUpClass(cls) -> None:print('setUpClass')
​@classmethoddef tearDownClass(cls) -> None:print('tearDownClass')
​def test_1_add(self):"""add"""num = 1 + 2print('test_add')self.assertEqual(num, 3, msg='加法错误')
​def test_2_sub(self):"""sub"""num = 1 - 1print('test_sub')self.assertEqual(num, 3, msg='减法错误')
​
​
if __name__ == '__main__':# 1. 把测试用例添加到suite容器中# suite = unittest.defaultTestLoader.discover('./', 'test_2.py')suite = unittest.defaultTestLoader.discover('./')
​# 2. 创建runner对象,同时把suite传参进入runner = BeautifulReport(suite)
​# 3. 运行,同时生成测试报告# 参数1:生成文件的注释, 参数2:生成文件的filename, 参数3:生成report的文件存储路径runner.report('报告描述必须有,在报告中显示为用例名称', '测试报告文件名2', './')

7. 综合案例

7.1【知道】测试流程和目录结构

08fed3029df9089d85f185c14643e3a5.png

7.2【掌握】基础工具方法类:读取json数据

# 读取json文件
# 1. 传入文件,读取内容,返回文件中数据
# 路径的处理
import os
import json
​
​
class Data(object):# 类属性# 获取工程所在的绝对路径BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
​# 设置为类方法,是为了方便调用@classmethoddef read_info(cls, file_name='server.json'):""":param file_name: 文件名:return: 文件中的json数据"""file_path = os.path.join(cls.BASE_DIR, 'data', file_name)# print(file_path)
​# 只读方式打开文件with open(file_path, 'r', encoding='utf-8') as f:ret = json.load(f) # load, 加载,加载是读# print(ret)
​return ret
​
# 测试一下
# print(Data.BASE_DIR)
# ret = Data.read_info('server.json')
# ret = Data.read_info('users/login_users.json')
# print('ret = ', ret)

7.3【掌握】基础工具方法类:请求封装

"""
1. 发送请求,只需要指定路径‘/login/’,无需指定url, 其他参数和原来的一样
import requests
​
def xxx(path = '/info/', params=None, **kwargs):url = 'http://127.0.0.1:8000'requests.get(url + path, params, **kwargs)
"""
from utils.data import Data
import requests
​
​
def read_url():ret = Data.read_info('server.json')# {'schema': 'http', 'host': '127.0.0.1', 'port': 8000}# print(ret)url = f'{ret["schema"]}://{ret["host"]}:{ret["port"]}'
​return url
​
​
# print(read_url())
class Ask(object):# 类熟悉URL = read_url()
​@classmethoddef get(cls, path, params=None, **kwargs):""":param path: 路径, '/info/':param params: url参数:param kwargs: 其他参数:return: requests.Response 响应对象"""resp = requests.get(cls.URL + path, params, **kwargs)return resp
​@classmethoddef post(cls, path, data=None, json=None, **kwargs):""":param path: 路径, 如'/login/':param data: 表单格式数据:param json: json格式数据:param kwargs: 其他参数:return: requests.Response 响应对象"""resp = requests.post(cls.URL + path, data, json, **kwargs)return resp
​
​
# 创建对象,调用方法
# obj = Ask()
# ret = obj.get('/info/')
# print(ret.json())
​
# info = {
#     "username": "admin111",
#     "password": "chuanzhi12345",
#     "remembered": True
# }
# ret = Ask.post('/login/', json=info)
# print(ret.json())

7.4【掌握】测试用例编写

import unittest
from utils.ask import Ask
​
​
class MyTest(unittest.TestCase):def test_login(self):print('test_login')info = {"username": "admin","password": "chuanzhi12345","remembered": True}r = Ask.post('/login/', json=info)ret = r.json()print(ret)
​self.assertEqual(ret['code'], 0, msg=ret['errmsg'])
​
​

7.5【掌握】执行测试用例

import unittest
from BeautifulReport import BeautifulReport
​
if __name__ == '__main__':# 1. 把测试用例添加到suite容器中suite = unittest.defaultTestLoader.discover('./tests')
​# 2. 创建runner对象,同时把suite传参进入runner = BeautifulReport(suite)
​# 3. 运行,同时生成测试报告# 参数1:生成文件的注释, 参数2:生成文件的filename, 参数3:生成report的文件存储路径runner.report('登陆', '美多登陆测试报告', './report')

推荐学习:

Python入门教程完整版(懂中文就能学会)

完整视频:Python入门教程完整版(懂中文就能学会)

配套资料:https://pan.baidu.com/s/15BmUdw9AgOD2tI9xG6p1WA 提取码:w61i

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/468382.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

void函数调用时显示不允许使用不完整的_4位数码管显示模块驱动

TM1637四位数码管模块是一个带时钟点的4位共阳数码管(0.36英寸)的显示模块,驱动芯片为TM1637,驱动方式为IIC,因此只需2根信号线即可使单片机控制4位8段数码管(数码管8级亮度可调)。模块特点如下:显示器件为4位共阳数码管数码管8级…

在线就能用的Linux我给你找好了

今天的天气真的是超级爽,秋日的凉风吹在脸上真的太美了,好不容易的假期,希望大家都玩得开心,今天分享一篇文章,是守望兄的,总结了几个在线的Linux,喜欢的同学,可以保存下来&#xff…

mysql访问类型最好的_【干货满满】最全的MySQL性能指南(一):选择最佳的数据类型...

对于 MySQL 数据库来说,好的逻辑表和物理表的规划至关重要,我们需要根据查询语句来针对性地设计 Schema ,没有万能好用的 Schema。一个 denormalized 的 schema 可以在某些场景下加速语句查询,但是放在其他应用场景下就会适得其反…

测试两个主机之间的连通性_借助网络测试神器极速解决网络故障

时下,网络使用越来越频繁,随之遇到网络故障的情况也多起来,那么诊断网络故障就成了必不可少的一环,投诉和求助是一种基本的方法,但有时太过缓慢,有些时候自己可以快速搞定,检查到故障原因所在&a…

随想,对嵌入式职场建议

guoqingjie已经过去两天了,因为楠哥生病,我们搁浅在了深圳,不过相比在路上的奔波,待在家里感觉惬意不少,不用在路上各种操心,之前上班感冒,身体处在亚健康状态,睡了两天身体也恢复一…

java可达性_java垃圾回收机制--可达性算法

先说一些题外话,Java虚拟机在执行Java程序的过程中会把它所管理的内存划分为若干个不同的数据区,这些区分为线程私有区和线程共享区1、线程私有区a、程序计数器记录正在执行的虚拟机字节码指令地址。此区域是是唯一一个在java虚拟机规范中没有规定任何Ou…

为什么要有uboot?

一、为什么要有uboot1.1、计算机系统的主要部件(1)计算机系统就是以CPU为核心来运行的系统。典型的计算机系统有:PC机(台式机笔记本)、嵌入式设备(手机、平板电脑、游戏机)、单片机(家用电器像电饭锅、空调…

华为路由器上有没有mac表_MAC地址表、ARP缓存表、路由表及交换机、路由器基本原理...

MAC地址表说到MAC地址表,就不得不说一下交换机的工作原理了,因为交换机是根据MAC地址表转发数据帧的。在交换机中有一张记录着局域网主机MAC地址与交换机接口的对应关系的表,交换机就是根据这张表负责将数据帧传输到指定的主机上的。交换机的…

#define的高级用法

来源:嵌入式大杂烩地址:https://blog.csdn.net/xiaoxu2050/article/details/82893476一、宏的定义与撤销需要注意的是:(1)宏定义应注意添加括号,这样语义会比较清晰。(2)使用#undef可…

python读取csv文件_python3.0读取csv文件

创建CSV文件,可以打开excel文件,创建表格以后,另存为csv文件(以逗号分隔的文件)以文本格式打开,发现是用逗号分隔的用python读取csv文件,首先要引入一个库:csvimport csvdef getCsvFile(strpath):with open(strpath, &…

直击中关村创业大街,新街头霸王来了

中国的硅谷在北京中关村。如今,中关村中正在酝酿硅谷中的硅谷,这里将不断诞生最前卫最现代的互联网和移动互联网创业公司,他们当中极可能孵化出中国互联网企业未来10年的新的BAT。这个硅谷中的硅谷。就是中关村创业大街。这条街在过去15年是北…

我们应该这样理解鸿蒙

之前写过文章谈到的鸿蒙,很多人觉得我说的有点过分,但是我觉得现在出来的情况还是符合预期的,鸿蒙正在完成他的任务。讲个故事,手机还没有普及的时候,相机的地位非常高,相机里面有一个东西叫做胶卷&#xf…

人工智能在语音和数字图像处理领域有哪些具体化应用_智能呼叫中心系统有哪些优势...

近年来,随着科技的发展特别是人工智能技术、云计算、大数据的到来,新技术逐渐渗入人们日常生活中的各行各业里面,以机器人来代替人工处理繁重的任务变得普遍。在人工智能时代下,新一代智能呼叫中心系统应运而生,呼叫中…

centos下mysql多实例安装3306、3307实例(2014-10-15)

背景说明 mysql的安装方法有多种,如二进制安装、源代码编译安装、yum安装等。yum安装仅仅能安装mysql 5.1 版本号;源代码安装编译的过程比較长。若没有对源代码进行改动且要求使用mysql较高版本号,建议使用二进制安装。本文以二进制安装mysql…

如何自己实现一个栈

文章转自编程珠玑,作者:守望先生前言栈是一种应用广泛的数据结构,例如函数的调用就需要使用栈,其实我们在介绍《栈的操作栈的常见操作有出栈(POP),从栈中弹出一个元素;入栈(PUSH),将一个元素压入…

python编写ATM类_Python中编写类的各种技巧和方法

有关 Python 内编写类的各种技巧和方法(构建和初始化、重载操作符、类描述、属性访问控制、自定义序列、反射机制、可调用对象、上下文管理、构建描述符对象、Pickling)。你可以把它当作一个教程,进阶,或者使用参考;我希望它能够成为一份针对…

再说嵌入式入门

我之前写过几篇嵌入式入门的文章 不过我的读者还是觉得不够过瘾,我觉得还是要着重说一下嵌入式软件应该重点学习什么,guoqing收假最后一天写文。精通C语言 精通C语言 精通C语言C语言对于嵌入式软件来说就是他的命脉,不懂C语言的人根本就不能说…

java ios 开发工具_iOS应用开发的五个Java开源工具

随着第三方工具的不断壮大,开发人员逐渐摆脱政策束缚,对于iOS系统的封闭性为其他语言(如Java)开发者诟病得到解脱,开始使用自己熟悉的语言来编写iOS本地应用,或将其他平台上的应用移植到iOS上。本文为你介绍5款开源的开发工具&…

hive 时间转字符串_大数据面试杀招——Hive高频考点,还不会的进来挨打

一、什么是Hive,为什么要用Hive,你是如何理解Hive?面试官往往一上来就一个“灵魂三连问”,很多没有提前准备好的小伙伴基本回答得都磕磕绊绊,效果不是很好。下面贴出菌哥的回答:Hive是基于Hadoop的一个数据仓库工具&a…

java jpa jar_JPA 开发所需的Jar包 (基于Hibernate)

JPA 开发所需的Jar包 (基于Hibernate)(一)下载Sun 的JPA规范(即:Jar包)登陆JavaEE 的 Technologies 页面:http://java.sun.com/javaee/technologies/index.jsp选择 Java Persistence 2.0选择 Final Release 中的 Download Page 后进入下面的界面:下载如下…