一、UnitTest框架介绍
1、什么是框架?
-
框架英文单词framework
-
为解决一类事情的功能集合
2、UnitTest框架
-
是python自带的一个单元测试框架,不用额外安装,即可直接使用
-
测试人员用来做自动化测试(接口/UI自动化),作为自动化测试的执行框架,即管理和执行测试用例
3、使用UnitTest框架的原因
-
能够组织多个用例去执行:能把多个测试用例放在一起,一起去执行
-
提供丰富的断言方法:代替人工自动的判断实际结果和预期结果是否相符
-
能够生成测试报告
4、UnitTest框架核心要素(组成部分)
-
TestCase:测试用例,作用是用来书写真正的用例代码(脚本)
-
TestSuite:测试套件,作用是用来组装(打包)TestCase(测试用例)的,既可以将多个用例脚本文件组装到一起
-
TestRunner:测试执行(测试运行),作用是用来执行TestSuite(测试套件)的
-
TestLoader:测试加载,是对TestSuite(测试套件)功能的补充,也是用来 组装(打包)TestCase(测试用例)的
-
Fixture:测试夹具,是一种代码结构,相当于书写前置方法(执行用例之前的方法)代码和后置方法(执行用例之后)代码,即用例执行顺序为前置->用例->后置
二、TestCase:测试用例
1、作用
-
用来书写真正的用例代码(脚本)
-
单独一个测试用例,也可以执行
2、定义测试用例的步骤
步骤1:导包--->import unittest 步骤2:定义测试类--->新建测试类 必须 继承unittest.TestCase类,习惯性类名以Test开头 步骤3:定义测试方法--->测试方法名称命名 必须 以test开头 步骤4:执行
3、注意事项
-
代码文件名,要满足标识符的规则:字母数字下划线组成,不能以数字开头
-
代码文件名,不要使用中文
4、执行测试用例的两种方式
-
方式1:使用pycharm在代码上点击鼠标右键,选择使用UnitTest运行
-
在类名后边右键运行:会执行测试类中所有的测试方法
-
在方法名后边右键运行:只执行当前的测试方法
-
-
方式2:调用unittest.main()来运行
5、举例说明
'''
学习TestCase(测试用例)的使用
'''
# 1、导包
import unittest
# 2、定义测试类:只需要让类继承unittest.TestCase类,这个类就是测试类
class TestDemo(unittest.TestCase):
# 3、定义测试方法:测试方法中的代码就是真正的用例代码,测试方法名必须以test开头
def test_method1(self):
print('测试方法一')
def test_method2(self):
print('测试方法二')
'''
4、执行测试用例的4种方式
4.1 在类名或者方法名后边右键运行
4.1.1在类名后边右键运行:会执行测试类中所有的测试方法
4.1.2在方法名后边右键运行:只执行当前的测试方法
4.2 使用unittest.main()执行测试用例
'''
# 4.2
if __name__ == '__main__':
unittest.main()
6、可能出现的错误
(1)文件名包含中文
(2)右键运行 没有unit test for......
-
解决方案1:新建一个代码文件,将之前的代码复制过来
-
解决方案2:在主程序使用unittest.main()来执行
-
解决方案3:使用减号,将python中内容移除
三、TestSuite(测试套件)和TestRunner(测试执行)
1、TestSuite的作用
-
将多条用例脚本集合在一起就是套件,即TestSuite是用来组装用例的
2、将用例脚本集合到测试套件中的步骤
步骤1: 导包--->import unittest 步骤2:实例化套件对象---> suite = unittest.TestSuite() 步骤3:添加用例方法(1)一次添加一个测试方法--->suite.addTest(ClassName(‘MethodName’))#ClassName:测试类名 MethodName:测试方法名(2) 一次添加整个测试类--->suite .addTest(unittest.makeSuite(测试类名))#在不同的Python版本中,可能没有提示(3)一次添加整个测试类-> suite.addTest(unittest.defaultTestLoader.loadTestsFromTestCase(ClassName))#把指定测试类中的测试方法全部添加到测试套件中
3、TestRunner的作用
-
用来执行测试用例和测试套件
4、执行对象执行测试套件的步骤
步骤1: 导包--->import unittest 步骤2:实例化执行对象(运行对象)---> runner = unittest.TextTestRunner() 步骤:3:执行对象执行套件对象---> runner.run(suite)#执行对象.run(套件对象)
5、整体步骤
步骤1: 导包--->import unittest 步骤2: 实例化套件对象---> suite = unittest.TestSuite() 步骤3:添加用例方法 步骤4:实例化执行对象(运行对象)---> runner = unittest.TextTestRunner() 步骤:5:执行对象执行套件对象---> runner.run(suite)
6、注意事项
-
TextSuite需要配合TestRunner才能被执行
7、举例说明
(1)需求
-
创建2个文件,并在每个文件中定义1个测试类和2个测试方法
-
批量执行所有的测试用例
(2)代码实现
# 步骤1:导包--->import unittest
import unittest
# 导包:导入其他包含测试类测试方法的Python文件
from hm_02_testcase1 import TestDemo1
from hm_02_testcase2 import TestDemo2
# 步骤2:实例化套件对象---> suite = unittest.TestSuite()
suite = unittest.TestSuite()
'''
步骤3:添加用例方法
3.1 方式1:一次添加一个测试方法--->套件对象.addTest(测试类名('测试方法名'))
3.2 方式2:一次添加整个测试类->套件对象.addTest(unittest.defaultTestLoader.loadTestsFromTestCase(ClassName))
#把指定测试类中的测试方法全部添加到测试套件中
3.3 方式3:一次添加整个测试类--->套件对象.addTest(unittest.makeSuite(测试类名))
#在不同的Python版本中,可能没有提示
'''
# 3.1
suite.addTest(TestDemo1('test_method1'))
suite.addTest(TestDemo1('test_method2'))
suite.addTest(TestDemo2('test_method1'))
suite.addTest(TestDemo2('test_method2'))
# 3.2
suite.addTest(unittest.defaultTestLoader.loadTestsFromTestCase(TestDemo1))
suite.addTest(unittest.defaultTestLoader.loadTestsFromTestCase(TestDemo2))
# 3.3
suite.addTest(unittest.makeSuite(TestDemo1))
suite.addTest(unittest.makeSuite(TestDemo2))
# 步骤4:实例化执行对象(运行对象)---> runner = unittest.TextTestRunner()
runner = unittest.TextTestRunner()
# 步骤5:执行对象执行套件对象---> runner.run(suite)
runner.run(suite)
(3)查看执行结果
四、TestLoader:测试加载
1、作用
-
作用和 TestSuite一样,也是 用来组装测试用例的,同样需要使用 TextTestRunner()去 执行
2、为什么有了TestSuite还要用TestLoader?
-
TestSuite:假如有10个用例脚本,通过makeSuite(测试类名)也需要10次才能将所有用例脚本都添加到测试套件中
-
TestLoader:使用unittest.TestLoader,通过该类下面的discover()方法自动搜索指定目录下指定开头的.py文件,并将查找到的测试用例组装到套件中 ,一行代码就可以将10个用例脚本都添加到套件中
-
结论:使用 TestLoader加载用例脚本更方便
3、通过TestLoader批量添加用例方法到套件中的步骤
步骤1: 导包--->import unittest 步骤2:实例化加载对象 并加载用例-- -> 得到的是套件对象suite = unittest.TestLoader().discover('用例所在的目录','用例代码文件名*.py')
步骤3:实例化执行对象并执行套件对象
4、注意事项
-
unittest.TestLoader().discover( '用例所在的目录','用例代码文件名*.py' )最终返回的还是套件对象,执行套件对象需要使用TestRunner
5、TestLoader与TestSuite区别
五、Fixture:测试夹具
1、Fixture引入案例
tpshop网页登录用例:
1、打开浏览器(一般只打开一次)
2、打开网页,点击登录(每次)
3、输入用户名、密码、验证码,点击【登录】(每次)
4、关闭页面(每次)
5、关闭浏览器(一般只关闭一次)
如果有3条用例:
1、打开浏览器(一般只打开一次,类,使用类
级别
Fixture)
2、打开网页,点击登录(每次)
3、输入用户名1、密码1、验证码1,点击【登录】(每次,测试方法,使用
方法级别
Fixture)
4、关闭页面(每次)
2、打开网页,点击登录(每次)
3、输入用户名2、密码2、验证码2,点击【登录】(每次,测试方法,使用
方法级别
Fixture)
4、关闭页面(每次)
2、打开网页,点击登录(每次)
3、输入用户名3、密码3、验证码3,点击【登录】(每次,测试方法,使用
方法级别
Fixture)
4、关闭页面(每次)
5、关闭浏览器(一般只关闭一次,类,使用类
级别
Fixture)
结论:
-
对于1、打开浏览器,2、打开网页,3、关闭网页,4、关闭浏览器,每个测试方法中都需要写,很麻烦,使用Fixture的话,这部分代码只写一次就可以了,执行每个测试用例方法前后都会自动执行Fixture写的2、4、这部分的代码
2、Fixture介绍
(1)作用
-
是一种代码结构,会在用例执行前后自动执行
-
简单理解就是对一个测试用例环境的初始化和销毁
(2)Fixture控制级别
-
方法级别 Fixture:在每个用例执行前、后都会自动调用,方法名是固定的
-
类级别 Fixture:在类中所有的测试方法执行前、后会自动执行的代码,一个类中只执行一次,类级别的Fixture需要写作类方法
-
模块级别 Fixture (了解):模块就是代码文件,模块级别就是在这个代码文件执行前、后会自动执行的代码,在类外部定义函数
3、方法级别Fixture
(1)使用方式
-
初始化(前置处理)
- def setUp(self): #每个用例执行之前都会自动调用
-
销毁(后置处理)
- def tearDown(self): #每个用例执行之后都会自动调用
(2)总结
-
运行于测试方法的始末,即:运行一次用例就会运行一次setUp和tearDown
4、类级别Fixture
(1)使用方式
-
初始化(前置处理)
- @classmethod
- def setUpClass(cls): #类前置方法,方法名不能变,因为这里相当于覆盖式重写了父类unittest中的setUpClass方法
-
销毁(后置处理)
- @classmethod
- def tearDownClass(cls): #类后置方法
(2)总结
-
运行于测试类的始末,即:每个测试类只会运行一次setUpClass和tearDownClass
-
类前置 方法前置 用例 方法后置 方法前置 用例 方法后置 类后置
5、模块级别Fixture(了解)
(1)使用方式
-
初始化(前置处理)
- def setUpModule(): #首先自动执行
-
销毁(后置处理)
- def tearDownModule(): #最后自动执行
(2)总结
-
运行于整个模块的始末,即:整个模块只会运行一次setUpModule和tearDownModule
6、注意
-
Fixture不一定是成对出现的,需要前置写前置,需要后置写后置即可
7、Fixture实现引入案例的实现代码
import unittest
class TestLogin(unittest.TestCase):
def setUp(self) -> None:
print('2、打开网页,点击登录')
def tearDown(self) -> None:
print('4、关闭网页')
@classmethod
def setUpClass(cls) -> None:
print('1、打开浏览器')
@classmethod
def tearDownClass(cls) -> None:
print('5、关闭浏览器')
def test_1(self):
print('3、输入用户名1、密码1、验证码1,点击【登录】')
def test_2(self):
print('3、输入用户名2、密码2、验证码2,点击【登录】')
def test_3(self):
print('3、输入用户名3、密码3、验证码3,点击【登录】')
六、练习1
1、需求
-
创建一个目录case,作用就是用来存放用例脚本
-
在case目录中创建5个用例代码文件,test_case1.py......
-
使用TestLoader去执行用例
2、注意
-
实际应用中,用例都是存放在单独的目录中的
3、实现代码
七、练习2
1、需求
-
定义一个tools模块,在这个模块中定义add方法,add方法可以对两个数字求和,返回求和结果
def add(a,b):
return a+b
-
这个add函数相当于开发的功能代码,进行自动化测试时可以调用开发的代码,但是不能修改开发的代码
-
书写用例,通过多组数据对add()函数进行测试
1,1,2
1,2,3
3,4,7
4,5,9
2、代码实现
#测试用例
import unittest
from lx2.tools import add
class TestAdd(unittest.TestCase):
def test_tools_add1(self):
if 2 == add(1, 1):
print(f'用例{1}{1}{2}测试通过')
else:
print(f'用例{1}{1}{2}测试不通过')
def test_tools_add2(self):
if 3 == add(1, 2):
print(f'用例{1}{2}{3}测试通过')
else:
print(f'用例{1}{2}{3}测试不通过')
def test_tools_add3(self):
if 7 == add(3, 4):
print(f'用例{3}{4}{7}测试通过')
else:
print(f'用例{3}{4}{7}测试不通过')
def test_tools_add4(self):
if 9 == add(4, 5):
print(f'用例{4}{5}{9}测试通过')
else:
print(f'用例{4}{5}{9}测试不通过')