UnitTest核心要素(unitest的组成)
1. TestCase(最核心的模块)
Testcase(测试用例),注意这个测试用例是unittest框架的组成部分,不是手工和自动化中我们所说的用例( Test Case)
主要作用:每个Testcase(测试用例)都是一个代码文件,在这个代码文件中来书写真正的用例代码
2. TestSuite
Testsuite(测试套件),用来管理组装(打包)多个TestCase(测试用例)的
3. TestRunner
TestRunner(测试执行,测试运行),用来执行TestSuite(测试套件)的
4. TestLoader
TestLoader(测试加载),功能是对Testsuite(测试套件)功能的补充,管理组装(打包)多个Testcase(测试用例)的
5.Fixture
Fixture(测试夹具),书写在Testcase(测试用例)代码中,是一个代码结构,可以在每个方法执行前后都会执行的内容
举例:
登录的测试用例,每个用例中重复的代码就可以写在Fixture代码结构中,只写一遍,但每次用例方法的执行,都会执行 Fixture中的代码
1.打开浏览器2.输入网址
----------------------------------------------------------
1. TestCase(最核心的模块)
在一个项目中Testcase(测试用例)的代码,一般放在一个单独的目录(case)
1.是一个代码文件,在代码文件中来书写真正的用例代码
2.代码文件的名字必须按照标识符的规则来书写(可以将代码的作用在文件的开头使用注释说明)
步骤
1.导包(unittest)
2.自定义测试类
3.在测试类中书写测试方法
4.执行用例
"""代码的目的:学习TestCase(测试用例)模块的书写方法"""
# 1,导包
import unittest
# 2,自定义测试类,需要继承unittest模块中的 Testcase类即可
class TestDemo1(unittest.TestCase):
# 3,书写测试方法,用例代码
# 书写要求,测试方法必须以test_开头(本质是以test开头)
def test_method1(self):
print('测试方法1')
def test_method2(self):
print('测试方法2')
# 4,执行用例(方法)
# 4.1 将光标放在类名的后边运行,会执行类中的所有的测试方法
# #4.2将光标放在方法名的后边运行,只执行当前的方 法
2. TestSuite TestRunner
Testsuite(测试套件),用来管理组装(打包)多个TestCase(测试用例)的
TestRunner(测试执行,测试运行),用来执行TestSuite(测试套件)的
步骤
1.导包(unittestR
2.实例化(创建对象)套件对象
3.使用套件对象添加用例方法
4.实例化运行对象
5.使用运行对象去执行套件对象
"""学习TestSuite和 TestRunner的使用"""
# 1.导包(unittest)
import unittest
# 2。实例化(创建对象)套件对象,
from TestCase import TestDemo1, TestDemo2
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'))
# 方式二 将一个测试类中的所有方法进行添加
# 套件对象. addTest(unittest.makeSuite(测试类名))
# #缺点:makeSuite()不会提示
suite.addTest(unittest.makeSuite(TestDemo1))
suite.addTest(unittest.makeSuite(TestDemo2))
# 4.实例化运行对象
runner = unittest.TextTestRunner()
# 5.使用运行对象去执行套件对象
# 运行对象.run(套件对象)
runner.run(suite)
3,TestLoader (测试加载)
TestLoader(测试加载),作用和TestSuite 的作用是一样的,对TestSuite 功能的补充,用来组装测试用例的比如:如果Testcase 的代码文件有很多,(10 20,30 )-使用步骤
1.导包
2.实例化测试加载对象并添加用例--->得到的是suite对象
3.实例化运行对象
4.运行对象执行套件对象
# 在一个项目中Testcase(测试用例)的代码,一般放在一个单独的目录(case)
"""学习TestLoader的使用"""
# 1.导包(unittest)
import unittest
# 2,实例化加载对象并添加用例
# unittest.TestLoader( ).discover( '用例所在的路径','用例的代码文件名')
# 用例所在的路径,建议使用相对路径,用例的代码文件名可以使用*(任意多个任意字符)通配符
suite = unittest.TestLoader().discover('./case', 'test*.py') # 'test*.py' 所有以test开头的都匹配 ;'*.py' 所有文件
# 3.实例化运行对象
runner = unittest.TextTestRunner()
# 4.使用运行对象去执行套件对象
# 运行对象.run(套件对象)
runner.run(suite)
# unittest.TextTestRunner.run(suite)
===============================================================================
Fixture(测试夹具)
Fixture(测试夹具)是一种代码结构
在某些特定的情况下会自动执行
方法级别[掌握]
在每个测试方法(用例代码)执行前后都会自动调用的结构
#方法执行之前
def setup(self): # 每个测试方法执行之前都会执行
pass
#方法执行之后
def teardown(self):
pass
# 每个测试方法执行之后都会执行
类级别[掌握]
在每个测试类中所有方法执行前后都会自动调用的结构(在整个类中执行之前执行之后个一次)
#类级别的Fixture方法,是一个类方法
#类中所有方法之前
@classmethod
def setupclass(cls):
pass
#类中所有方法之后@classmethod
def teardownClass(cls):
pass
模块级别[了解]
模块:代码文件
在每个代码文件执行前后执行的代码结构
#模块级别的要写在类的外边直接定义函数即可#代码文件之前
def setupModule() :
pass
#代码文件之后
def teardownModule():
pass
方法级别和类级别的前后的方法,不需要同时出现,根据用例代码的需要自行的选择使用
案例
1.打开浏览器(整个测试过程中就打开一次浏览器)类级别
2.输入网址(每个测试方法都需要一次)方法级别
3.输入用户名密码验证码点击登录(不同的测试数据)测试方法
4.关闭当前页面(每个测试方法都需要一次)方法级别
5.关闭浏览器(整个测试过程中就关闭一次浏览器)类级别
1.打开浏览器(整个测试过程中就打开一次浏览器)类级别
2.输入网址(每个测试方法都需要一次)方法级别
3.输入用户名密码验证码点击登录(不同的测试数据)测试方法
4.关闭当前页面(每个测试方法都需要一次)方法级别
2.输入网址(每个测试方法都需要一次)方法级别
3.输入用户名密码验证码点击登录(不同的测试数据)测试方法
4.关闭当前页面(每个测试方法都需要一次)方法级别
2.输入网址(每个测试方法都需要一次)方法级别
3.输入用户名密码验证码点击登录(不同的测试数据)测试方法
4.关闭当前页面(每个测试方法都需要一次)方法级别
5.关闭浏览器(整个测试过程中就关闭一次浏览器)类级别
import unittest
class TestLogin(unittest.TestCase):
@classmethod
def setupclass(cls) -> None:
print("1,打开浏览器")
# 类中所有方法之后@classmethod
@classmethod
def teardownClass(cls) -> None:
print("5,关闭浏览器")
# 方法执行之前
def setUp(self) -> None: # 每个测试方法执行之前都会执行
print("2,输入网站")
def tearDown(self) -> None:
print("4,关闭页面")
# 方法执行之后
def test_1(self):
print('输入正确用户名密码验证码,点击登录1')
def test_2(self):
print('输入错误用户名密码验证码,点击登录2')
# 2,实例化加载对象并添加用例
suite = unittest.TestSuite()
suite.addTest(unittest.makeSuite(TestLogin))
# 3.实例化运行对象
runner = unittest.TextTestRunner()
# 4.使用运行对象去执行套件对象
# 运行对象.run(套件对象)
runner.run(suite)
# unittest.TextTestRunner.run(suite)
=================================================================
断言
让程序代替人工自动的判断预期结果和实际结果是否相符.
断言的结果有两种:
> True,用例通过
> False,代码抛出异常,用例不通过
在unittest中使用断言,都需要通过self.断言方法来试验
常见断言方法:
assertTrue(expr, msg=None) 验证expr是true,如果为false,则fail
assertFalse(expr, msg=None) 验证expr是false,如果为true,则fai
assertEqual(expected, actual,msg=None) 验证expected==actual,不等则fail【掌握】
assertNotEqual(first, second,msg=None) 验证first != second,相等则fail
assertlsNon(obj, msg=None) 验证obj是None,不是则fail
assertlsNotNone(obj, msg=None) 验证obj不是None,是则fail
assertln(member, container,msg=None) 验证是否member in container【掌握】
assertNotIn(member, container,msg=None) 验证是否member not in container
assertEqual
assertEqual(预期结果,实际结果)#判断预期结果和实际结果是否相等
1.如果相等,用例通过
2.如果不相等,用例不通过,抛出异常
assertIn
assertIn(预期结果,Y实际结果)#判断预期结果是否包含在实际结果中
1.包含,用例通过
2.不包含,用例不通过,抛出异常
assertIn( 'admin ' , 'admin')#包含
assertIn( 'admin', 'adminnnnnnnn ')#包含
assertIn( ' admin', 'aaaaaadmin')# 包含
assertIn( ' admin ', 'aaaaaadminnnnnnn ')#包含
assertIn( ' admin' , 'addddddmin ')#不是包含
import unittest
def login(name, pwd):
"""正确的用户名和密码:admin,123456,登录成功"""
if name == 'admin' and pwd == '123456':
return "登录成功"
else:
return "登录失败"
# 在一个项目中Testcase(测试用例)的代码,一般放在一个单独的目录(case)
"""学习TestLoader的使用"""
# 1.导包(unittest)
import unittest
class TestLogin(unittest.TestCase):
def test__username_password_ok(self):
"""正确的用户名和密码:admin。123456。登录成功"""
self.assertEqual('登录成功', login('admin', '123456'))
def test_username_error(self):
"""正确的用户名和密码:root。123456。登录失败"""
self.assertEqual('登录失败', login('root', '123456'))
def test_password_error(self):
"""正确的用户名和密码:admin。123123。登录失败"""
self.assertEqual('登录失败', login('admin', '123123'))
登录失败 != 登录成功
Expected :登录成功
Actual :登录失败
========================================================
参数化
参数化在测试方法中,使用变量来代替具体的测试数据,然后使用传参的方法将测试数据传递给方法的变量
好处:相似的代码不需要多次书写.
工作中场景:
1.测试数据─般放在json文件中
2.使用代码读取json文件,提取我们想要的数据--->[(),()] or [[],[]]
安装插件
unittest框架本身是不支持参数化,想要使用参数化,需要安装插件来完成
pip install parameterized
验证
pip list #查看到parameterized
参数化代码步骤
1.导包unittest/ pa
2.定义测试类
3.书写测试方法(用到的测试数据使用变量代替)
4.组织测试数据并传参
def Budil_Data():
with open("./case/data.json", encoding="utf-8") as fp:
data = []
result = json.load(fp)
for i in result:
data.append((i.get('name'), i.get('pwd'), i.get('expect')))
return data
class TestLogin(unittest.TestCase):
@parameterized.parameterized.expand(Budil_Data)
def test_login(self, name, pwd, expect):
"""正确的用户名和密码:admin。123456。登录成功"""
self.assertEqual(expect, login(name, pwd))
-------------------------------------------------------------
跳过
对于一些未完成的或者不满足测试条件的测试函数和测试类,不想执行,可以使用跳过使用方法,装饰器完成
代码书写在Testcase文件
直接将测试函数标记成跳过
@unittest.skip(‘跳过额原因’)
根据条件判断测试函数是否跳过,判断条件成立,跳过
@unittest.skipIf(判断条件,'跳过原因)
# 1,导包
import unittest
ver = 30
# 2,自定义测试类,需要继承unittest模块中的 Testcase类即可
class TestDemo1(unittest.TestCase):
def test_method1(self):
print('测试方法1-1')
@unittest.skip('没用')
def test_method2(self):
print('测试方法1-2')
@unittest.skipIf(ver > 70, '跳过')
def test_method3(self):
print('测试方法2-1')
def test_method4(self):
print('测试方法2-2')
suite = unittest.TestSuite()
suite.addTest(unittest.makeSuite(TestDemo1))
runner = unittest.TextTestRunner()
runner.run(suite)
----------------------------------------------
3.HTMLTestRunner【重点】
3.1 HTMLTestRunner介绍
.HTMLTestRunner是一个第三方的类库,用来执行测试用例并生成HTML格式的测试报告·网上有多种不同的实现版本,用法都类似,只是生成的HTML报告样式有差别
·注意:下载的文件要与Python的版本兼容(有些版本只支持Python2.x)
本课程中介绍两种模板文件,HTMLTestRunner .py 和 HTMLTestRunner_PY3.py
HTMLTestRunner.py :样式比较简单,不需要依赖外部JS和CSS文件
HTMLTestRunner_PY3.py :样式比较美观,需要依顿外部JS和CSS文件
3.2测试报告截图
#1。获取第三方的测试运行类模块,将其放在代码的目录中
2。导包unittest
3.使用套件对象,加载对象去添加用例方法
#4.实例化第三方的运行对象并运行套件对象
# 1。获取第三方的测试运行类模块,将其放在代码的目录中
# 2。导包unittest
import unittest
from HtmlTestRunner import HTMLTestRunner
# 3.使用套件对象,加载对象去添加用例方法
suite = unittest.defaultTestLoader.discover('.', 'TestParameterized.py')
# 4.实例化第三方的运行对象并运行套件对象
# self, output="./reports/", verbosity=2, stream=sys.stderr,
# descriptions=True, failfast=False, buffer=False,
# report_title=None, report_name=None, template=None, resultclass=None,
# add_timestamp=True, open_in_browser=False,
# combine_reports=False, template_args=None
# stream=sys.stdout,必填,测试报告的文件对象(open ),注意点,要使用wb打开
# verbosity=1,可选,报告的详细程度,默认1简略,2详细
# titLe=None,可选,测试报告的标题
# description=None可选,描述信息,Python 的版本,pycharm 版本
fileName = "./reports.html"
with open(fileName, 'wb') as fp:
runner = HTMLTestRunner(fp)
runner = unittest.TextTestRunner(suite)
==========================================================================
总结 整体流程:
1.组织用例文件(TestCase 里边),书写参数化,书写断言,书写Fixture,书写跳过,如果单个测试测试文件,直接运行,得到测试报告,如果有多个测试文件,需要组装运行生成测试报告
2.使用套件对象组装,或者使用加载对象组装
3.运行对象运行
3.1运行对象=第三方的运行类(文件对象(打开文件需要使用wb方式))
3.2运行对象.run(套件对象)