1.test_1_login.py文件
'''
==================================
cooding:utf-8
@Time :2020/6/12 20:00
@Author :henry
@Email :yinpingwei@gmail.com
@File :test_1_login.py
@Software:PyCharm
===================================
'''
# 单元测试
"""
单元测试:就是对单个模块或者是单个类或者是单个函数进行测试
自动化的测试:
代码实现的用例,代码执行用例,代码判断结果,代码生成测试报告
单元测试框架类型有:
1.pytest框架
2.unittest框架——4大核心概念
TestCase(测试用例)
TestSuite(测试套件)
TextTestRunner(执行用例/呈现结果)
Fixture(前置后置条件)
表达用例-》收集用例-》执行用例-》生成报告
1.TestCase(测试用例)
用例编写格式步骤:
1. import unittest # 导入unittest模块,被测文件或者其中的类
2. class xxxx(unittest.TestCase) # 创建一个测试类 ,继承unittest.TestCase
3. def Testxxx(self) # 在定义一个测试函数,以test_开头,定义测试函数。
def test_xxx(self): # 每一个test_开头的函数,就是一个测试用例。
4. 测试用例中:
1、测试数据、期望结果
2、测试步骤
3、断言:预期结果与实际结果的比对
AssertionError: 断言失败 - 用例失败
assert 表达式(True表示通过,False表示失败)
self.assertXXXXX()
4、前置后置(Fixture)-前置条件、后置工作
自动化用例:1.前置后置(可有可无) 2、步骤 3、断言
unittest用例断言方法:
1.assertEqual(a,b) 检查:a==b
2.assertNotEqual(a,b) 检查:a!=b
3.assertTrue(x) 检查:boxl(x)is True
4.assertFalse(x) 检查:boxl(x)is False
5.assertis(a,b) 检查:a is b
6.assertisNot(a,b) 检查:a is not b
7.assertin(a,b) 检查:a in b
8.assertNotin(a,b) 检查:a not in b
AssertionError: 断言失败,是unittest框架,识别用例识别的标识
2.Fixture(前置后置条件)可要可不要
1、setup,teardown - 类下面的每一条用例在执行之前,会执行setup(前置条件)
在每一条用例执行之后,会执行teardown(后置工作)
setup 测试用例 teardown
2、setupClass,teardownClass - 类里面的第一个用例执行之前执行,会执行setupClass
类里面最后一个用例执行之后,会执行teardownClass
stupClass 测试类 teardownClass
3.TestSuite/TestLoader(测试套件/用例收集)
1.用例套件 TestSuite: 测试用例集合(了解均可)
unittest.TestSuite 实例化套件
方法一:addTest(类名('用例名')) 添加一个测试用例
方法二:addTests([]) 添加一个测试用例的列表
2.TestLoader:测试用例收集(专门用这个)
可通过类目,模块名,目录三种方式去收集用例,我们只用方法一即可
方法一:目录(最常用)
unittest.TestLoader().discover(搜索目录)
搜索标准:
1.从指定目录
2.文件过滤标准:以文件名匹配,test*.py的文件
3.在文件当中去过滤用例:继承了unittest.TestCase类的测试类,类当中以test_开头的测试函数
方法二:类名(了解)
unittest.TestLoader().loadTestFromTestCase(测试类名) 测试类名不需要加引号
方法三:模块名(了解)
unittest.TestLoader().loadTestFromModule(模块名) 模块名不需要加引号(注意要导入模块)
4.执行用例+生产测试报告
运行用例,并生成测试报告到txt,html中
1.TextTestRunner 运行结果以text呈现(是自带的)
2.HtmlTestRunner 运行结果以html呈现(第三方,需要安装)
先实例化,在生成html报告
3.BeautifulIReport 运行结果以html呈现(第三方,需要安装)
安装:pip install BeautifulIReport
先实例化,在生成html报告
用例的执行顺序:ASCII码顺序,从小到大
1.ASCII码大小规则:0-9 < A-Z < a-z
2.如果想自己指定执行顺序,在文件名或者用例名称上做文章
5.设计思维(参数化):ddt data driven test 数据驱动
一个测试流程,N个测试用例 流程不变,只是数据和断言不一样
模块名:ddt 第三方库 pip install ddt
将多组测试数据,依次传递给一个测试流程
0、引入ddt
import ddt
1、在测试类名上面,用@ddt.ddt
@ddt.ddt
2、在测试函数上面,用@ddt。data(*列表)
在测试函数的参数中,定义一个参数来接收每一组测试数据
总结:
表达用例 - 收集用例 - 执行用例生+成报告
setup TestSuite TextTestRunner (不用)
teardown TestLoader().disover(搜索路径) HtmlTestRunner--实例化后调用run方法,html报告
setupClass 用例搜索原则:目录(test*.py)-测试用例 BeautifulIReport--实例化后,report生成html报告
teardownClass
用例的执行顺序:ASCII码顺序,从小到大
ddt:一个测试流程,N个测试用例
1、列表 = 准备好N组测试数据
2、
import ddt
类名上:@ddt.ddt
测试流程函数上:@ddt.data(*列表)
测试流程函数:用一个变量接收每一组测试数据
"""
# 引入unittest单元测试
import unittest
# 从导入(class_work_two)包.(new_class)模块 导入(login_check)函数
from class_work_two.login import login_check
# 引入ddt模块
import ddt
# 给定一个列表里面放不同的用例参数和预期结果
datas = [
{'user':'woshijinyao300','password':'lemonbanpy30','check':{"code": 0, "msg": "登录成功"}},
{'user':'woshijinyao300','password': 'lemonban','check':{"code": 1, "msg": "账号或密码不正确"}},
{'user':'woshijinya','password': 'lemonbanpy30','check':{"code": 1, "msg": "账号或密码不正确"}}
]
@ddt.ddt
class TestLogin(unittest.TestCase): # 定义测试类,继承unittest.TestCase
# 第一种使用ddt:
@ddt.data(*datas) # 拆包传参
def test_0_succ(self,case): # 顶一个变量接收
res = login_check(case['user'],case['password']) # 给与测试数据账号与密码
self.assertEqual(res,case['check']) # 断言:判断预期结果与实际结果是否一致
# 第二种使用for循环:
# def test_lo(self):
# for data in datas:
# res = login_check(data['user'], data['password']) # 给与测试数据账号与密码
# self.assertEqual(res, data['check']) # 断言:判断预期结果与实际结
@classmethod # 装饰器,声明为类方法
def setUpClass(cls): # 这是类方法,意思是继承了类,这里重写了,只会执行一次
print('*********** TestLogin类下面的用例开始执行 ************')
@classmethod # 装饰器,声明为类方法
def tearDownClass(cls): # 这是类方法,意思是继承了类,这里重写了,只会执行一次
print('*********** TestLogin类下面的用例结束执行 ************')
def setUp(self): # 这是前置条件,定义了每个测试用例都会执行
print('======= 单个用例开始执行 ========')
def tearDown(self): # 这是后置条件,定义了每个测试用例都会执行
print('======= 单个用例结束执行 ========')
# def test_1_error_password(self): # 错误的密码登录
# res1 = login_check('woshijinyao300', 'lemonbanpy') # 给与测试数据,正确的账号与错误的密码
# self.assertNotEqual(res1, {"code": 1, "msg": "账号或密码不正确"}) # 断言:判断预期结果与实际结果是否一致
#
# def test_2_error_account(self): # 错误的账号登录
# res2 = login_check('woshijinyao', 'lemonbanpy30') # 给与测试数据,错误的账号与正确的密码
# self.assertEqual(res2, {"code": 1, "msg": "账号或密码不正确"}) # 断言:判断预期结果与实际结果是否一致
#
# def test_3_no_account(self): # 账号为空
# res3 = login_check('lemonbanpy30') # 给与测试数据,空的账号与正确的密码
# self.assertEqual(res3, {"code": 1, "msg": "所有的参数不能为空"}) # 断言:判断预期结果与实际结果是否一致
#
# def test_4_no_password(self): # 密码为空
# res4 = login_check('woshijinyao300') # 给与测试数据,正确的账号与空密码
# self.assertEqual(res4, {"code": 1, "msg": "所有的参数不能为空"}) # 断言:判断预期结果与实际结果是否一致
2.getter_main.py文件
'''
==================================
cooding:utf-8
@Time :2020/6/13 9:22
@Author :henry
@Email :yinpingwei@gmail.com
@File :getter_main.py
@Software:PyCharm
===================================
'''
# 1.用例收集
# 引入unittest单元测试
import unittest
# 导入(from 包名.模块名 import 函数/变量)
from class_work_two.test_1_login import TestLogin # 第一个用例
from class_work_two.test_0_modex import TestDemo # 第二个用例
# 方法一:
# 1.实例化套件TestSuite
# s = unittest.TestSuite()
# 有2个方法,了解下就好
# 添加一个用例 格式是:函数名(用例名称)
# s.addTest(TestLogin('test_success'))
# 添加一个测试用例的列表
# s.addTests([TestLogin('test_success'),TestLogin('test_error_password')])
# 方法二:
# 2.实例化套件TestLoader
# 从start_directory这个目录下开始,搜索所有的目录,搜索所有的测试用例,并加载到测试套件中
# 搜索标准:
# 1.从指定目录
# 2.文件过滤标准:以文件名匹配,test*.py的文件
# 3.在文件当中去过滤用例:继承了unittest.TestCase类的测试类,类当中以test_开头的测试函数
s = unittest.TestLoader().discover(r'E:\Python-workspace\py30') # 搜索目录
print(type(s)) # 类型是:<class 'unittest.suite.TestSuite'>
print(s)
# 2.TextTestRunner(执行用例+生成测试报告)
# 第一种:TextTestRunner模块
# 运行测试用例并生成结果
# runner = unittest.TextTestRunner() # 调用函数
# runner.run(s) # 生成结果
# 第二种:HtmlTestRunner模块
# 运行测试用例并生成结果
# 导入这个包
from HTMLTestRunnerNew import HTMLTestRunner
# 创建一个html文件,以写入的模式打开,支持中文
with open('report.html','wb') as fs:
# 运行测试用例,将结果写入html当中
runner = HTMLTestRunner(fs,title='py30期单元测试报告',tester='henry') # 实例化之后运行这个对象.可以指定给参数
runner.run(s) # 调用run方法
# 第三种:BeautifulIReport模块
# 导入这个包
# from BeautifulReport import BeautifulReport
# 实例化之后运行这个对象
# br = BeautifulReport(s)
# 给到名称和创建html文件
# br.report('py30单元测试报告','br_report.html')
3.login.py文件
'''
==================================
cooding:utf-8
@Time :2020/6/138:35
@Author :henry
@Email :yinpingwei@gmail.com
@File :login.py
@Software:PyCharm
===================================
'''
# 功能逻辑
def login_check(username=None, password=None):
""" 登录校验的函数
:param username: 账号
:param password: 密码
:return: dict type
"""
if username != None and password != None:
if username == 'woshijinyao300' and password == 'lemonbanpy30':
return {"code": 0, "msg": "登录成功"}
else:
return {"code": 1, "msg": "账号或密码不正确"}
else:
return {"code": 1, "msg": "所有的参数不能为空"}
'''
1.账号密码正确
入参:账号:woshijinyao300 密码:lemonbanpy30
预期结果:{"code": 0, "msg": "登录成功"}
实际结果:
2.账号正确,密码错误
入参:账号:woshijinyao300 密码:lemonban
预期结果:{"code": 1, "msg": "账号或密码不正确"}
实际结果:
3.账号错误,密码正确
入参:账号:woshijinya 密码:lemonbanpy30
预期结果:{"code": 1, "msg": "账号或密码不正确"}
实际结果:
4.账号为空
入参:账号为空 密码:lemonbanpy30
预期结果:{"code": 1, "msg": "所有的参数不能为空"}
实际结果:
5.密码为空
入参:账号:woshijinyao300 密码为空
预期结果:{"code": 1, "msg": "所有的参数不能为空"}
实际结果:
'''
# s = login_check("python27","lemonban")
# # 比对期望和实际
# if s == {"code": 0, "msg": "登录成功"}:
# print("用例通过!")
# else:
# print("用例失败!")
#
#
# s = login_check("python27","lemonban")
# # 比对期望和实际
# if s == {"code": 0, "msg": "登录成功。。"}:
# print("用例通过!")
# else:
# print("用例失败!")
# 用例之间是独立的。你失败或者成功,跟另外一个用例的执行+结果都是没有关系的。
4.test_0_modex.py文件
'''
==================================
cooding:utf-8
@Time :2020/6/139:13
@Author :henry
@Email :yinpingwei@gmail.com
@File :test_0_modex.py
@Software:PyCharm
===================================
'''
import unittest
class TestDemo(unittest.TestCase):
def test_hello(self):
self.assertTrue(True)
if __name__ == '__main': # 单独想要运行这个文件
unittest.main()
2020年06月12日--12----python单元测试unittest框架(下)
最新推荐文章于 2024-08-11 15:29:59 发布