UnitTest框架的基本使用方法
UnitTest框架介绍
框架:framework,为了解决一类事情的功能集合
UnitTest框架:是python自带的单元测试框架
自带的,可以直接使用,不需要格外安装
测试人员用来做自动化测试,作为自动化测试的执行框架,即管理和执行测试用例的
使用原因:
能够组织多个用例去执行
提供丰富的断言方法
能够生成测试报告
核心要素(组成):
-TestCase测试用例,这个测试用例是UnitTest的组成部分,作用是用来书写真正的用例代码(脚本)
-TestSuite测试套件,作用是用来组装TestCase的,即可以将多个用例脚本文件组装到一起
-TestRunner测试执行,作用是用来执行TestSuite的
-TestLoader测试加载,是对TestSuite功能的补充,作用是用来组装TestCase的
-Fixture测试夹具,是一种代码结构,书写前置方法代码和后置方法代码,即用例执行顺序:前置–>用例–>后置
TestCase测试用例
书写真正的用例代码(脚本)
步骤:
-1.导包unittest
-2.定义测试类
-3.书写测试方法
-4.执行
注意事项:
代码文件名字要满足标识符的规则
代码文件名不要使用中文
代码:
#导包
import unittest
#定义测试类,只要继承unittest.TestCase类,就是测试类
class TestDemo(unittest.TestCase):
#书写测试方法,方法中的代码就是真正的用例代码,方法名必须以test开头
def test_method1(self):
print("测试方法一")
def test_method2(self):
print("测试方法二")
#执行
#在类名或者方法名后边右键运行
#在类名后边,执行类中的所有测试方法
#在方法名后边,只执行当前的测试方法
#在主程序中使用unittest.main()来执行
if __name__ == '__main__':
unittest.main()
TestCase常见错误
1.文件名包含中文-------执行可能报错
2.右键运行没有unittest for …
解决方法一:新建一个代码文件,将之前的代码复制过来
解决方法二:使用unittest.main()运行
解决方法三:
TestSuite和TestRunner的使用
TestSuite测试套件:将多条脚本集合在一起,就是套件,即用来组装用例的
1.导包unittest
2.实例化套件对象unittest.TestSuite()
3.添加用例方法,套件对象.addTest(测试类名(测试方法名))
TestRunner测试执行:用来执行套件对象
1.导包unittest
2.实例化执行对象unittest.TextTestRunner()
3.执行对象执行套件对象,执行对象.run(套件对象)
整体步骤:
1.导包unittest
2.实例化套件对象unittest.TestSuite()
3.添加用例方法,套件对象.addTest(测试类名(测试方法名))
4.实例化执行对象unittest.TextTestRunner()
5.执行对象执行套件对象,执行对象.run(套件对象)
代码案例
套件可以用来组装用例,创建多个代码用例
#导包
import unittest
#定义测试类,只要继承unittest.TestCase类,就是测试类
class TestDemo1(unittest.TestCase):
#书写测试方法,方法中的代码就是真正的用例代码,方法名必须以test开头
def test_method1(self):
print("测试方法1-1")
def test_method2(self):
print("测试方法1-2")
#导包
import unittest
#定义测试类,只要继承unittest.TestCase类,就是测试类
class TestDemo2(unittest.TestCase):
#书写测试方法,方法中的代码就是真正的用例代码,方法名必须以test开头
def test_method1(self):
print("测试方法2-1")
def test_method2(self):
print("测试方法2-2")
#1.导包unittest
import unittest
from unittest1.TestCase.yongli1 import TestDemo2
from unittest1.TestCase.yongli2 import TestDemo1
#2.实例化套件对象unittest.TestSuite()
suite=unittest.TestSuite()
#3.添加用例方法,套件对象.addTest(测试类名(测试方法名))
suite.addTest(TestDemo1('test_method1'))
suite.addTest(TestDemo1('test_method2'))
suite.addTest(TestDemo2('test_method1'))
suite.addTest(TestDemo2('test_method2'))
#4.实例化执行对象unittest.TextTestRunner()
runner=unittest.TextTestRunner()
#5.执行对象执行套件对象,执行对象.run(套件对象)
runner.run(suite)
添加整个测试类中的方法
方法一
套件对象.addTest(unittest.defaultTestLoader.loadTestsFromTestCase(测试类名))
#把指定测试类中的测试用例全部添加到测试套件中
方法二
套件对象.addTest(unittest.makeSuite(测试类名))
#1.导包unittest
import unittest
from unittest1.TestCase.yongli1 import TestDemo2
from unittest1.TestCase.yongli2 import TestDemo1
#2.实例化套件对象unittest.TestSuite()
suite=unittest.TestSuite()
#3.添加用例方法,套件对象.addTest(unittest.defaultTestLoader.loadTestsFromTestCase(测试类名))
suite.addTest(unittest.defaultTestLoader.loadTestsFromTestCase(TestDemo1))
suite.addTest(unittest.makeSuite(TestDemo2))
#4.实例化执行对象unittest.TextTestRunner()
runner=unittest.TextTestRunner()
#5.执行对象执行套件对象,执行对象.run(套件对象)
runner.run(suite)
查看测试结果
TestLoader测试加载:
作用和TestSuite作用一样,组装用例代码,同样也需要使用TextTestRunner()方法去执行
TestLoader加载用例更加方便
1.导包import unittest
2.实例化加载对象并加载用例---->得到的是套件对象
3.实例化执行对象并执行
#1.导包
import unittest
#2.实例化加载对象并加载用例---->得到的是套件对象
suite=unittest.TestLoader().discover('.','yongli*.py') #参数1:用例所在目录,参数2:用例代码文件名
#3.实例化执行对象并执行
runner=unittest.TextTestRunner()
runner.run(suite)
练习
练习1
用例代码
#导包
import unittest
#定义测试类,只要继承unittest.TestCase类,就是测试类
class TestDemo1(unittest.TestCase):
#书写测试方法,方法中的代码就是真正的用例代码,方法名必须以test开头
def test_method(self):
print("测试方法1")
执行代码
import unittest
suite=unittest.TestLoader().discover('./case','test_*.py')
unittest.TextTestRunner().run(suite)
练习2
import unittest
from tools1 import add
class TestDemo(unittest.TestCase):
def test_method1(self):
if add(1,1) == 2:
print("测试通过")
else:
print("测试失败")
def test_method2(self):
if add(2,1) == 3:
print("测试通过")
else:
print("测试失败")
def test_method3(self):
if add(3,4) == 7:
print("测试通过")
else:
print("测试失败")
def test_method4(self):
if add(4,5) == 9:
print("测试通过")
else:
print("测试失败")
import unittest
suite=unittest.TestLoader().discover('.','test_*.py')
unittest.TextTestRunner().run(suite)
fixture说明
代码结构,在用例执行前后会自动执行的代码结构
tpshop登录
1.打开浏览器(一次)
2.打开网页,点击登录(每次)
3.输入用户名,密码,验证码,点击登录(每次)
4.关闭页面(每次)
5.关闭浏览器(一次)
方法级别Fixture:
在每个用例执行前后都会自动调用,方法名是固定的
def setUp(self): #前置方法,每个用例执行前调用
pass
def tearDown(self): #后置方法,每个用例执行之后都会调用
pass
类级别Fixture:
在类中所有的测试方法执行前后,会自动执行的代码,类开始前执行和类执行结束时执行一次
类级别的Fixture需要写作类方法
@classmethod
def setUpClass(cls): #前置方法,类执行前调用
pass
@classmethod
def tearDownClass(cls): #后置方法,类执行之后都会调用
pass
模块级别Fixture:
模块就是代码文件,在代码文件执行前后执行一次
在类外部定义函数
def setUpModule(): #前置
pass
def tearDownpModule(): #前置
pass
Fixture实现
测试用例
import unittest
class TestDemo(unittest.TestCase):
@classmethod
def setUpClass(cls):
print("打开浏览器")
@classmethod
def tearDownClass(cls):
print("关闭浏览器")
def setUp(self):
print("打开网页,点击登录")
def tearDown(self):
print("关闭页面")
def test_method1(self):
print("输入用户名密码验证码1,点击登录")
def test_method2(self):
print("输入用户名密码验证码2,点击登录")
def test_method3(self):
print("输入用户名密码验证码1,点击登录")
测试运行
import unittest
suite=unittest.TestLoader().discover('.','test_*.py')
unittest.TextTestRunner().run(suite)
断言的使用
断言
使用代码自动判断预期结果和实际结果是否相等
练习
import unittest
from tools1 import add
class TestDemo(unittest.TestCase):
def test_method1(self):
self.assertEqual(2,add(1,1))
def test_method2(self):
self.assertEqual(3,add(1, 2))
def test_method3(self):
self.assertEqual(7,add(3, 4))
def test_method4(self):
self.assertEqual(9,add(4, 5))
import unittest
suite=unittest.TestLoader().discover('.','test_*.py')
unittest.TextTestRunner().run(suite)
实现参数化
参数化环境安装
通过参数的方式来传递数据,从而实现数据和脚本分离,并且可以实现用例的重复执行。(在书写用例方法的时候,测试数据使用变量代替,在执行的时候进行数据传递)
-unittest测试框架,本身不支持参数化,但是可以通过安装unittest扩展插件parameterized来实现。
因为参数化的插件不是unittest自带的,所以想要使用,需要进行安装
安装:pip install -i http://pypi.douban.com/simple parameterized
参数化
1.导包 from parameterized import parameterized
2.修改测试方法,将测试方法中的测试数据使用变量表示
3.组织测试数据,格式[(),(),()],一个元组就是一组测试数据
4.参数化,在测试方法上方使用装饰器@parameterized.expand(测试数据)
5.运行(直接运行TestCase或者使用suite运行)
import unittest
from parameterized import parameterized
from tools1 import add
class TestDemo(unittest.TestCase):
list = [(1, 1, 2), (1, 2, 3), (3, 4, 7), (2, 3, 5)]
@parameterized.expand(list)
def test_method1(self,a,b,expect):
self.assertEqual(expect,add(a,b))
练习1
import json
def getDate():
with open('../package1/one.json', 'r', encoding='utf-8') as f:
list=json.load(f)
list1=[]
for i in list:
list1.append(tuple(i.values()))
return list1
import unittest
from parameterized import parameterized
from lianxi2.getDate import getDate
from tools1 import add
class TestDemo(unittest.TestCase):
@parameterized.expand(getDate())
def test_method1(self,a,b,expect):
self.assertEqual(expect,add(a,b))
测试报告和跳过
测试报告
使用第三方的报告模板,生成报告HTMLTestReport,本质是TestRunner
安装
pip install -i http://pypi.doouban.com/simple/ HTMLTestReport
使用
1.导包unittest;HTMLTestReport
2.组装用例(套件,loader)
3.使用HTMLTestReport中的runner执行
4.查看报告
import unittest
from htmltestreport import HTMLTestReport
if __name__ == '__main__':
#套件
suite = unittest.TestLoader().discover('.', 'test_*.py')
#运行runner=HTMLTestReport(报告文件目录, 报告标题,其他描述信息)
runner=HTMLTestReport('report.html', '测试报告','add')
runner.run(suite)
使用绝对路径
将来的项目是分目录书写的,使用相对路径,可能会出现找不到文件的情况,此时需要使用绝对路径
方法:
1.在项目的根目录,创建一个python文件(app.py或者config.py)
2.在这个文件中获取项目的目录,在其他代码中使用路径拼接完成绝对路径的书写
import os
#获取项目绝对路径
path1=os.path.abspath(__file__) #__file__ 是特殊变量,表示当前代码文件名
base_addr=os.path.dirname(path1)
import os
import unittest
from htmltestreport import HTMLTestReport
from base_addr import base_addr
if __name__ == '__main__':
#套件
suite = unittest.TestLoader().discover('.', 'test_*.py')
#运行runner=HTMLTestReport(报告文件目录, 报告标题,其他描述信息)
#runner=HTMLTestReport('report.html', '测试报告','add')
#绝对路径
filepath=os.path.join(base_addr,'lianxi2/report/report.html')
runner=HTMLTestReport(filepath, '测试报告','add')
runner.run(suite)
案例
tools.py
def login(username,password):
if username=='admin' and password=='123456':
return '登录成功'
else:
return '登录失败'
测试数据one.json
[{
"desc": "正确的用户名和密码",
"username": "admin",
"password":"123456",
"excpet":"登录成功"
}, {
"desc": "错误密码",
"username": "admin",
"password":"admin",
"excpet":"登录失败"
}, {
"desc": "错误用户名",
"username": "admin1",
"password":"123456",
"excpet":"登录失败"
}]
获取测试数据getDate.py
import json
def getDate():
with open('../package1/one.json', 'r', encoding='utf-8') as f:
list=json.load(f)
list1=[]
for i in list:
list1.append(tuple(i.values())[1:])
return list1
测试用例
import unittest
from parameterized import parameterized
from lianxi2.getDate import getDate
from tools import login
class TestDemo(unittest.TestCase):
@parameterized.expand(getDate())
def test_method1(self,a,b,expect):
self.assertEqual(expect,login(a,b))
执行并生成测试报告
import os
import unittest
from htmltestreport import HTMLTestReport
from base_addr import base_addr
if __name__ == '__main__':
#套件
suite = unittest.TestLoader().discover('.', 'test_*.py')
#运行runner=HTMLTestReport(报告文件目录, 报告标题,其他描述信息)
#绝对路径
filepath=os.path.join(base_addr,'lianxi2/report/report.html')
runner=HTMLTestReport(filepath, '测试报告','login')
runner.run(suite)
报告
跳过
对于一些未完成的或者不满足测试条件的测试函数和测试类,可以执行跳过(简单来说,不想执行的代码的存测试方法,可以设置跳过)
直接将测试函数标记成跳过
@unittest.skip(“跳过原因”)
根据条件判断测试函数是否跳过
@unittest.skipIf(判断条件,reason=‘原因’) #判断条件为True,执行跳过
import unittest
from parameterized import parameterized
from lianxi2.getDate import getDate
from tools1 import login
version=30
class TestDemo(unittest.TestCase):
@parameterized.expand(getDate())
def test_method1(self,a,b,expect):
self.assertEqual(expect,login(a,b))
@unittest.skip("跳过举例")
def test_method2(self):
print("测试方法二")
@unittest.skipIf(version>30,"版本大于30跳过")
def test_method3(self):
print("测试方法三")
@unittest.skipUnless(version<30,"版本小于30跳过")
def test_method4(self):
print("测试方法四")