? ? ? ? 毛泽东说:“我一生最大的爱好是读书”,“饭可以一日不吃,觉可以一日不睡,书不可以一日不读”。
---毛泽东的读书学习生涯(上)
????????学习是文明传承之途、人生成长之梯、政党巩固之基、国家兴盛之要。
---谈论学习也不行?
? ? ? ??退伍回来10个多月,奈何没有相关的软件测试工作经验和经历,而且毕业四五年没碰过了软件专业了,加之现在疫情的变化无常,报培训班时间不够自由,所以回来边恶补专业知识,边找相关工作。只能是四处碰壁,让我学习的欲望更加强烈。
? ? ? ? 今天也恰巧看到CSDN话题挑战赛第2期中的《学习笔记》这个参赛话题很符合我,正好把我近期学习的(四)自动化测试-unittest框架简单总结一下,方便自己以后找出来看看。
CSDN话题挑战赛第2期
参赛话题:学习笔记
目? ? 录
? ? ? ? 一、前期脚本问题
? ? ? ? 二、融入unittest框架
? ? ? ? 1、unittest框架好处
????????2、unittest框架工作原理
? ? ? ? 三、unittest框架拆分介绍
????????1、导入unittest包
????????2、创建测试用例类
????????3、测试用例类中的五种特殊方法(包含使用场景及执行顺序)
????????4、创建测试用例
????????5、测试用例执行
????????6、断言
?????????7、python代码和运行结果
? ? ? ? 四、脚本优化
????????1、测试用例主执行文件
????????2、测试结果优化
????????3、测试报告输出---SMTP(未完结)
????????五、项目结构(未完结)
????????1、public
????????2、test_cases
????????3、test_datas
????????4、test_reports
????????5、test.py
????????6、attachments
????????7、confs
? ? ? ? 一、前期脚本问题
? ? ? ? 1、测试用例过多,只能单一执行,或者导包执行。
? ? ? ? 2、断言方式简单且不实用,日志只能体现在控制台输出,无法体现在报告中。
? ? ? ? 3、无法体现测试报告中的效果:测试用例数量、执行数量、通过数量、失败数量以及失败原因。
? ? ? ? 二、融入unittest框架
????????不仅仅是代码级别的功能测试、逻辑覆盖
? ? ? ? 1、unittest框架好处
? ? ? ? (1)提供用例组织与执行
? ? ? ? (2)提供丰富的断言方法
? ? ? ? (3)提供丰富的日志和报告(HTML格式更直观展示)
????????2、unittest框架工作原理
????????(1)Fixture(固定件)
????????TestCase:测试用例、脚本
????????TestSuite:测试集合、套件、文件夹、统一管理多条测试用例
????????TestRunner:测试运行器
????????TestLoader:测试用例加载器
????????TestRusult:测试结果、字典类型
? ? ? ? (2)单元测试代码段
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# author:bigbear
# datetime:2022/9/3 16:39
# software: PyCharm
"""
单元测试:
测试对象:类中的方法(函数)
"""
class MyMath:
"""定义运算函数:实现加减乘除算法"""
@staticmethod
def add(a, b):
"""加法"""
# 测试问题:若a是字符串,b是整型,应该是字符串拼接运算
if isinstance(a, str) and isinstance(b, int):
b = str(b)
return a + b
else:
return a + b
@staticmethod
def subtract(a, b):
"""减法"""
return a - b
@staticmethod
def multiply(a, b):
"""乘法"""
return a * b
@staticmethod
def divide(a, b):
"""除法"""
if b == 0:
return "除数不能是0,小学生都知道的啊"
else:
return a / b
if __name__ == '__main__':
"""单元测试-代码功能验证"""
mm = MyMath()
# 实现第一条加法测试用例
actual_value = mm.add(1, 1)
expect_value = 2
if actual_value == expect_value:
print("加法功能实现正确")
# 实现第二条加法测试用例:can only concatenate str (not "int") to str
try:
actual_value = mm.add("a", 1)
expect_value = "无法运算"
if actual_value == expect_value:
print("加法功能实现正确")
except Exception as e:
print(f"加法功能实现正确:{e}")
# 实现第三条加法测试用例
try:
actual_value = mm.add("a", "b")
expect_value = "ab"
if actual_value == expect_value:
print("加法功能实现正确")
except Exception as e:
print(f"加法功能实现正确:{e}")
? ? ? ? 三、unittest框架拆分介绍
????????1、导入unittest包
import unittest
????????2、创建测试用例类
????????继承单元测试框架的单元测试用例的类unittest.TestCase
class MyMathUnittest(unittest.TestCase):
"""继承单元测试框架的单元测试用例类"""
????????3、测试用例类中的五种特殊方法(包含使用场景及执行顺序)
????????setUp()、test_xxx()、tearDown()执行顺序与位置无关,且每执行一条测试用例,setUp()和tearDown()都会执行一次(无论该测试用例是否通过)。
????????@classmethod注解的方法是类方法,不用创建对象也可以用的方法,在对象进入内存之前就已经存在的方法,随着类一起进内存。
????????(1)setUp()? #?初始化、环境搭建
????????(2)test_xxx()? #?测试用例方法、步骤
????????(3)tearDown()? #?还原测试用例环境
? ? ? ? (4)@classmethod-setUpClass()? #?对当前测试用例类的所有测试用例进行初始化,只在类执行开始执行一次
? ? ? ? (5)@classmethod-tearDownClass()? #?对当前测试用例类的所有测试用例资源进行释放,只在类执行结束执行一次
import unittest
# from importlib import import_module
from my_math import MyMath
class MyMathUnittest(unittest.TestCase):
"""继承单元测试框架的单元测试用例类"""
# 注解:给方法指定特殊含义
@classmethod
def setUpClass(cls) -> None:
print("setUpClass方法")
@classmethod
def tearDownClass(cls) -> None:
print("tearDownClass方法")
def setUp(self) -> None:
"""方法名固定、self参数不能少"""
self.mm = MyMath()
print("setUp方法")
def test_add(self):
"""test_是测试用例:加法运算-正向"""
add_value = self.mm.add(1, 1)
# 断言方法,判断预期结果和实际结果是否相等
# AssertionError: 2 != 3 : 预期和实际结果不相等
self.assertEqual(add_value, 2, "预期和实际结果不相等")
print("test_add方法")
def tearDown(self) -> None:
"""方法名固定、self参数不能少"""
print("tearDown方法")
????????4、创建测试用例
? ? ? ? (1)test_开头
import unittest
from my_math import MyMath
class MyMathUnittest(unittest.TestCase):
"""继承单元测试框架的单元测试用例类"""
def test_add(self):
"""test_是测试用例:加法运算-正向"""
print("test_add方法")
def test_add_1(self):
"""test_是测试用例:加法运算-反向"""
add_value = self.mm.add("a", 1)
self.assertNotEqual(add_value, "a1", "预期和实际结果不相等")
print("test_add_0方法")
def test_add_2(self):
"""test_是测试用例:加法运算-正向"""
add_value = self.mm.add("a", "b")
self.assertEqual(add_value, "ab", "预期和实际结果不相等")
print("test_add_1方法")
????????5、测试用例执行
? ? ? ? (1)main()执行方法
????????unittest.main()? #?所有测试用例执行一遍,但无法控制执行顺序(默认按照字母顺序执行)
if __name__ == '__main__':
"""此文件运行时执行"""
# 执行测试用例类中所有的测试用例
unittest.main()
? ? ? ? (2)TestSuite()自带加载执行方法
????????test_suite = unittest.TestSuite()? #?创建测试套件对象
????????test_suite.addTest(类名("用例名"))? #?将一条测试用例添加到测试套件,可以多次添加,任意调换顺序即执行顺序
????????test_suite.addTests([类名("用例名"),...])? #?将可迭代测试集(列表、字典)中的测试用例添加到测试套件,列表中任意调换顺序即执行顺序
????????test_suite.addTests(map(类名, ["用例名",...]))? #?使用map()方法将类应用于用例返回列表
????????test_suite.run(unittest.TestResult())? #?运行测试套件,并存储测试结果?
if __name__ == '__main__':
"""此文件运行时执行"""
# addTest(类名("用例名")):将一条测试用例添加到测试套件,可以多次添加,任意调换顺序即执行顺序
test_suite = unittest.TestSuite()
# 在测试套件中添加一条测试用例
test_suite.addTest(MyMathUnittest("test_add"))
test_result = unittest.TestResult()
test_suite.run(test_result)
print(test_result.__dict__)
if __name__ == '__main__':
"""此文件运行时执行"""
# addTests([类名("用例名"),...]):将可迭代测试集(列表、字典)中的测试用例添加到测试套件,列表中任意调换顺序即执行顺序
test_suites = unittest.TestSuite()
# 在测试套件中添加多条测试用例
test_list = map(MyMathUnittest, ["test_add_2", "test_add_1", "test_add"])
test_suites.addTests(test_list)
test_results = unittest.TestResult()
test_suites.run(test_results)
print(test_results.__dict__)
? ? ? ? (3)TestLoader()特定加载方法
????????test_loader = unittest.TestLoader()? #?创建测试用例加载器对象
????????loader_suite = test_loader.loadTestsFromName("模块名")? #?将某模块中的所有测试用例加载到测试套件中
????????loader_suite = test_loader.loadTestsFromName("模块名.类名")? #?将某模块中的某类中的的所有测试用例加载到测试套件中
????????loader_suite = test_loader.loadTestsFromName(name="类名", module=import_module("模块名"))? #?将某模块中的某类中的的所有测试用例加载到测试套件中
????????loader_suite = test_loader.loadTestsFromName("模块名.类名.测试用例名")? #?将某一条测试用例加载到测试套件中
????????loader_suite = test_loader.loadTestsFromName(name="类名.测试用例名", module=import_module("模块名"))? #?将某一条测试用例加载到测试套件中
????????#?__import__(name):通过python解释器导入模块,非通用
????????loader_suite = test_loader.loadTestsFromModule(__import__("模块名"))? #?将某模块中的所有测试用例加载到测试套件中
????????#?importlib.import_module(name):以编程方式导入模块
????????loader_suite = test_loader.loadTestsFromModule(import_module("模块名"))? #?将某模块中的所有测试用例加载到测试套件中
????????loader_suite = test_loader.discover("./模块目录", "模块名正则表达式.py")? #?将指定模块中的所有测试用例一次性加载
if __name__ == '__main__':
"""此文件运行时执行"""
# 加载测试用例到测试套件中
test_loader = unittest.TestLoader()
# loadTestsFromName("模块名"):将某模块中的所有测试用例加载到测试套件中
# loader_suite = test_loader.loadTestsFromName("unittest_frame")
# loadTestsFromName("模块名.类名"):将某模块中的某类中的的所有测试用例加载到测试套件中
# loader_suite = test_loader.loadTestsFromName("unittest_frame.MyMathUnittest")
# loader_suite = test_loader.loadTestsFromName(name="MyMathUnittest", module=import_module("unittest_frame"))
# loadTestsFromName("模块名.类名.测试用例名"):将某一条测试用例加载到测试套件中
# loader_suite = test_loader.loadTestsFromName("unittest_frame.MyMathUnittest.test_add")
# loader_suite = test_loader.loadTestsFromName(name="MyMathUnittest.test_add", module=import_module("unittest_frame"))
# __import__(name):通过python解释器导入模块,非通用
#loader_suite = test_loader.loadTestsFromModule(__import__("unittest_frame"))
# import_module(name):以编程方式导入模块
# loader_suite = test_loader.loadTestsFromModule(import_module("unittest_frame"))
# discover("./模块目录", "模块名正则表达式.py"):将指定模块中的所有测试用例一次性加载
# loader_suite = test_loader.discover("./", "unit*.py")
# defaultTestLoader是默认的共享加载器
discover = unittest.defaultTestLoader.discover("./", "unit*.py")
? ? ? ? (4)TestRunner()特定执行方法
? ? ? ? # TextTestRunner().run(测试套件):执行测试用例,并将结果以Text文本形式写入文件中
with open("unittest_result.txt", "w", encoding="utf-8") as f_txt:
????????# descriptions=True:测试用例是否显示注释;True表示显示,False表示不显示
????????# verbosity=1:日志详细等级;,0表示无日志,1表示只显示省略号,2表示每条测试用例是否执行成功都会显示
????????test_runner = unittest.TextTestRunner(f_txt,descriptions=True,verbosity=1)
????????test_runner.run(loader_suite)
????????f_txt.close()?
if __name__ == '__main__':
"""此文件运行时执行"""
with open("unittest_result.txt", "w", encoding="utf-8") as f_txt:
# TextTestRunner().run(测试套件):执行测试用例,并将结果以Text文本形式写入文件中
text_runner = unittest.TextTestRunner(f_txt, verbosity=2)
text_runner.run(discover)
f_txt.close()
????????6、断言
? ? ? ? (1)一个自动化测试用例:测试步骤和断言缺一不可
? ? ? ? (2)unittest自带断言方法
????????都可以在参数中设置错误提示信息, msg=""
assertEqual(a, b):a==b判断相等
assertNotEqual(a, b):a!=b判断不相等
assertTrue(x):bool(x) is True判断布尔值为True
assertFalse(x):booI(x) is False判断布尔值为False
assertIs(a, b):a is b判断身份(内存地址值)相等
assertIsNot(a, b):a is not b判断身份(内存地址值)不相等
assertIsNone(x):x is None判断为空指针
assertIsNotNone(x):x is not None判断不为空指针
assertIn(a, b):a in b判断a在b中
assertNotIn(a, b):a not in b判断a不在b中
assertIsInstance(a, b):isinstance(a,b)判断a是b的实例对象
assertNotIsInstance(a, b):not isinstance(a,b)判断a不是b的实例对象?
import unittest
class MyMathUnittest(unittest.TestCase):
"""继承单元测试框架的单元测试用例类"""
def test_ae(self):
"""断言方法assertEqual---判断相等"""
self.assertEqual(1, 1)
self.assertEqual(1, 2)
def test_ane(self):
"""断言方法assertNotEqual---判断不相等"""
self.assertNotEqual(1, 1)
self.assertNotEqual(1, 2)
def test_at(self):
"""断言方法assertTrue---判断布尔值为True"""
self.assertTrue(1 == 1)
self.assertTrue(1 == 2)
def test_af(self):
"""断言方法assertFalse---判断布尔值为False"""
self.assertFalse(1 == 1)
self.assertFalse(1 == 2)
def test_ais(self):
"""断言方法assertIs---判断身份(内存地址值)相等"""
a, b, c = 1, 1, 2
self.assertIs(a, b)
self.assertIs(a, c)
def test_ais_not(self):
"""断言方法assertIsNot---判判断身份(内存地址值)不相等"""
a, b, c = 1, 1, 2
self.assertIsNot(a, b)
self.assertIsNot(a, c)
def test_ais_none(self):
"""断言方法assertIsNone---判断为空指针"""
self.assertIsNone(None)
self.assertIsNone(1)
def test_ais_not_none(self):
"""断言方法assertIsNotNone---判断不为空指针"""
self.assertIsNotNone(None)
self.assertIsNotNone(1)
def test_ai(self):
"""断言方法assertIn---判判断a在b中"""
self.assertIn(1, [1, 2, 3])
self.assertIn(1, [2, 3, 4])
def test_ani(self):
"""断言方法assertNotIn---判断a不在b中"""
self.assertNotIn(1, [1, 2, 3])
self.assertNotIn(1, [2, 3, 4])
def test_aii(self):
"""断言方法assertIsInstance--- 判断a是b的实例对象"""
self.assertIsInstance(1, int)
self.assertIsInstance(1, str)
def test_anii(self):
"""断言方法assertNotIsInstance---判断a不是b的实例对象"""
self.assertNotIsInstance(1, int)
self.assertNotIsInstance(1, str)
?????????7、python代码和运行结果
????????(1)python代码
????????注意:
????????????????测试用例虽然失败,但是里面的两条断言中有一条是通过的!!!
????????????????只是为了方便测试此断言的运行结果!!!
? ? ? ? ? ? ? ? 里面运行了前两个测试套件的结果都会展示在运行窗口中!!!
? ? ? ? ? ? ? ? 测试用例加载器testloader()就相当于把测试用例加载到了测试套件中,所以返回的对象是测试套件,每次使用一种即可!!!
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# author:bigbear
# datetime:2022/9/6 10:47
# software: PyCharm
"""
unittest框架:
1、导入unittest包
2、创建测试用例类(继承单元测试框架的单元测试用例的类)
3、测试用例类中的五种特殊方法(包含使用场景及执行顺序)
(1)setUp()、test_xxx()、tearDown()执行顺序与位置无关,且每执行一条测试用例,setUp()和tearDown()都会执行一次(无论该测试用例是否通过)
(2)setUp() # 初始化、环境搭建
(3)test_xxx() # 测试用例方法、步骤
(4)tearDown() # 还原测试用例环境
(5) @classmethod注解的方法是类方法,不用创建对象也可以用的方法,在对象进入内存之前就已经存在的方法,随着类一起进内存
(6)@classmethod-setUpClass() # 对当前测试用例类的所有测试用例进行初始化,只在类执行开始执行一次
(7)@classmethod-tearDownClass() # 对当前测试用例类的所有测试用例资源进行释放,只在类执行结束执行一次
4、创建测试用例:test_开头
5、测试用例执行:
(1)main()执行方法
unittest.main() # 所有测试用例执行一遍,但无法控制执行顺序(默认按照字母顺序执行)
(2)TestSuite()自带加载执行方法
test_suite = unittest.TestSuite() # 创建测试套件对象
test_suite.addTest(类名("用例名")) # 将一条测试用例添加到测试套件,可以多次添加,任意调换顺序即执行顺序
test_suite.addTests([类名("用例名"),...]) # 将可迭代测试集(列表、字典)中的测试用例添加到测试套件,列表中任意调换顺序即执行顺序
test_suite.addTests(map(类名, ["用例名",...])) # 使用map()方法将类应用于用例返回列表
test_suite.run(unittest.TestResult()) # 运行测试套件,并存储测试结果
(3)TestLoader()特定加载方法
test_loader = unittest.TestLoader() # 创建测试用例加载器对象
loader_suite = test_loader.loadTestsFromName("模块名") # 将某模块中的所有测试用例加载到测试套件中
loader_suite = test_loader.loadTestsFromName("模块名.类名") # 将某模块中的某类中的的所有测试用例加载到测试套件中
loader_suite = test_loader.loadTestsFromName(name="类名", module=import_module("模块名")) # 将某模块中的某类中的的所有测试用例加载到测试套件中
loader_suite = test_loader.loadTestsFromName("模块名.类名.测试用例名") # 将某一条测试用例加载到测试套件中
loader_suite = test_loader.loadTestsFromName(name="类名.测试用例名", module=import_module("模块名")) # 将某一条测试用例加载到测试套件中
# __import__(name):通过python解释器导入模块,非通用
loader_suite = test_loader.loadTestsFromModule(__import__("模块名")) # 将某模块中的所有测试用例加载到测试套件中
# importlib.import_module(name):以编程方式导入模块
loader_suite = test_loader.loadTestsFromModule(import_module("模块名")) # 将某模块中的所有测试用例加载到测试套件中
loader_suite = test_loader.discover("./模块目录", "模块名正则表达式.py") # 将指定模块中的所有测试用例一次性加载
(4)TestRunner()特定执行方法
# TextTestRunner().run(测试套件):执行测试用例,并将结果以Text文本形式写入文件中
with open("unittest_result.txt", "w", encoding="utf-8") as f_txt:
# descriptions=True:测试用例是否显示注释;True表示显示,False表示不显示
# verbosity=1:日志详细等级;,0表示无日志,1表示只显示省略号,2表示每条测试用例是否执行成功都会显示
test_runner = unittest.TextTestRunner(f_txt,descriptions=True,verbosity=1)
test_runner.run(loader_suite)
f_txt.close()
6、断言
(1)一个自动化测试用例:测试步骤和断言缺一不可
(2)unittest自带断言方法
都可以在参数中设置错误提示信息, msg=""
assertEqual(a, b) # a==b判断相等
assertNotEqual(a, b) # a!=b判断不相等
assertTrue(x) # bool(x) is True判断布尔值为True
assertFalse(x) # booI(x) is False判断布尔值为False
assertIs(a, b) # a is b判断身份(内存地址值)相等
assertIsNot(a, b) # a is not b判断身份(内存地址值)不相等
assertIsNone(x) # x is None判断为空指针
assertIsNotNone(x) # x is not None判断不为空指针
assertIn(a, b) # a in b判断a在b中
assertNotIn(a, b) # a not in b判断a不在b中
assertIsInstance(a, b) # isinstance(a,b)判断a是b的实例对象
assertNotIsInstance(a, b) # not isinstance(a,b)判断a不是b的实例对象
7、测试用例主执行文件
使用默认的可共享的加载器更方便加载更多的测试用例
discover = unittest.defaultTestLoader.discover("./模块目录", "模块名正则表达式.py")
8、测试结果优化
(1)格式优化---HTML
# HTTPTestRunner().run(测试套件):执行测试用例,并将结果以HTML页面形式写入文件中
with open("unittest_result.html", "wb", encoding="utf-8") as f_html:
# wb:以字节形式写入文件
# verbosity=1:日志详细等级;,0表示无日志,1表示只显示省略号,2表示每条测试用例是否执行成功都会显示
# title="":网页标题
# descriptions="":测试描述
html_runner = HTTPTestRunner.HTMLTestRunner(f_html, verbosity=2, title="页面标题",description="测试描述")
html_runner.run(discover)
f_html.close()
(2)显示优化---文档注释
在每个测试用例中添加文档'''一行注释'''
(3)存储优化---文件名规范
# 文件命名:路径+时间格式+ .html
filename = f"../测试报告/{time.strftime('%Y-%m-%d-%H-%M-%S')}.html"
注意时间格式获取方法:
time.time() # 获取当前时间戳
time.ctime() # 获取当前时间的字符串格式
time.localtime() # 获取当前时间的结构化格式
time.strftime() # 获取当前时间,并可格式化为字符串
%Y Year with century as a decimal number.
%m Month as a decimal number [01,12].
%d Day of the month as a decimal number [01,31].
%H Hour (24-hour clock) as a decimal number [00,23].
%M Minute as a decimal number [00,59].
%S Second as a decimal number [00,61].
%z Time zone offset from UTC.
%a Locale's abbreviated weekday name.
%A Locale's full weekday name.
%b Locale's abbreviated month name.
%B Locale's full month name.
%c Locale's appropriate date and time representation.
%I Hour (12-hour clock) as a decimal number [01,12].
%p Locale's equivalent of either AM or PM.
"""
import HTTPTestRunner
import time
import unittest
# from importlib import import_module
from my_math import MyMath
class MyMathUnittest(unittest.TestCase):
"""继承单元测试框架的单元测试用例类"""
# 注解:给方法指定特殊含义
@classmethod
def setUpClass(cls) -> None:
print("setUpClass方法")
@classmethod
def tearDownClass(cls) -> None:
print("tearDownClass方法")
def setUp(self) -> None:
"""方法名固定、self参数不能少"""
self.mm = MyMath()
print("setUp方法")
def test_add(self):
"""test_是测试用例:加法运算-正向"""
add_value = self.mm.add(1, 1)
# 断言方法,判断预期结果和实际结果是否相等
# AssertionError: 2 != 3 : 预期和实际结果不相等
self.assertEqual(add_value, 2, "预期和实际结果不相等")
print("test_add方法")
def test_add_1(self):
"""test_是测试用例:加法运算-反向"""
add_value = self.mm.add("a", 1)
self.assertNotEqual(add_value, "a1", "预期和实际结果不相等")
print("test_add_0方法")
def test_add_2(self):
"""test_是测试用例:加法运算-正向"""
add_value = self.mm.add("a", "b")
self.assertEqual(add_value, "ab", "预期和实际结果不相等")
print("test_add_1方法")
def test_ae(self):
"""断言方法assertEqual---判断相等"""
self.assertEqual(1, 1)
self.assertEqual(1, 2)
def test_ane(self):
"""断言方法assertNotEqual---判断不相等"""
self.assertNotEqual(1, 1)
self.assertNotEqual(1, 2)
def test_at(self):
"""断言方法assertTrue---判断布尔值为True"""
self.assertTrue(1 == 1)
self.assertTrue(1 == 2)
def test_af(self):
"""断言方法assertFalse---判断布尔值为False"""
self.assertFalse(1 == 1)
self.assertFalse(1 == 2)
def test_ais(self):
"""断言方法assertIs---判断身份(内存地址值)相等"""
a, b, c = 1, 1, 2
self.assertIs(a, b)
self.assertIs(a, c)
def test_ais_not(self):
"""断言方法assertIsNot---判判断身份(内存地址值)不相等"""
a, b, c = 1, 1, 2
self.assertIsNot(a, b)
self.assertIsNot(a, c)
def test_ais_none(self):
"""断言方法assertIsNone---判断为空指针"""
self.assertIsNone(None)
self.assertIsNone(1)
def test_ais_not_none(self):
"""断言方法assertIsNotNone---判断不为空指针"""
self.assertIsNotNone(None)
self.assertIsNotNone(1)
def test_ai(self):
"""断言方法assertIn---判判断a在b中"""
self.assertIn(1, [1, 2, 3])
self.assertIn(1, [2, 3, 4])
def test_ani(self):
"""断言方法assertNotIn---判断a不在b中"""
self.assertNotIn(1, [1, 2, 3])
self.assertNotIn(1, [2, 3, 4])
def test_aii(self):
"""断言方法assertIsInstance--- 判断a是b的实例对象"""
self.assertIsInstance(1, int)
self.assertIsInstance(1, str)
def test_anii(self):
"""断言方法assertNotIsInstance---判断a不是b的实例对象"""
self.assertNotIsInstance(1, int)
self.assertNotIsInstance(1, str)
def test_multiply(self):
"""test_是测试用例:"""
multiply_value = self.mm.multiply(1, 1)
# 断言方法,判断预期结果和实际结果是否相等
self.assertEqual(multiply_value, 1, "预期和实际结果不相等")
print("test_multiply方法")
def tearDown(self) -> None:
"""方法名固定、self参数不能少"""
print("tearDown方法")
if __name__ == '__main__':
"""此文件运行时执行"""
# 执行测试用例类中所有的测试用例
# unittest.main()
# addTest(类名("用例名")):将一条测试用例添加到测试套件,可以多次添加,任意调换顺序即执行顺序
test_suite = unittest.TestSuite()
# 在测试套件中添加一条测试用例
test_suite.addTest(MyMathUnittest("test_add"))
test_result = unittest.TestResult()
test_suite.run(test_result)
print(test_result.__dict__)
# addTests([类名("用例名"),...]):将可迭代测试集(列表、字典)中的测试用例添加到测试套件,列表中任意调换顺序即执行顺序
test_suites = unittest.TestSuite()
# 在测试套件中添加多条测试用例
test_list = map(MyMathUnittest, ["test_add_2", "test_add_1", "test_add"])
test_suites.addTests(test_list)
test_results = unittest.TestResult()
test_suites.run(test_results)
print(test_results.__dict__)
# 加载测试用例到测试套件中
# test_loader = unittest.TestLoader()
# loadTestsFromName("模块名"):将某模块中的所有测试用例加载到测试套件中
# loader_suite = test_loader.loadTestsFromName("unittest_frame")
# loadTestsFromName("模块名.类名"):将某模块中的某类中的的所有测试用例加载到测试套件中
# loader_suite = test_loader.loadTestsFromName("unittest_frame.MyMathUnittest")
# loader_suite = test_loader.loadTestsFromName(name="MyMathUnittest", module=import_module("unittest_frame"))
# loadTestsFromName("模块名.类名.测试用例名"):将某一条测试用例加载到测试套件中
# loader_suite = test_loader.loadTestsFromName("unittest_frame.MyMathUnittest.test_add")
# loader_suite = test_loader.loadTestsFromName(name="MyMathUnittest.test_add", module=import_module("unittest_frame"))
# __import__(name):通过python解释器导入模块,非通用
# loader_suite = test_loader.loadTestsFromModule(__import__("unittest_frame"))
# import_module(name):以编程方式导入模块
# loader_suite = test_loader.loadTestsFromModule(import_module("unittest_frame"))
# discover("./模块目录", "模块名正则表达式.py"):将指定模块中的所有测试用例一次性加载
# loader_suite = test_loader.discover("./", "unit*.py")
# defaultTestLoader是默认的共享加载器
discover = unittest.defaultTestLoader.discover("./", "unit*.py")
with open("unittest_result.txt", "w", encoding="utf-8") as f_txt:
# TextTestRunner().run(测试套件):执行测试用例,并将结果以Text文本形式写入文件中
text_runner = unittest.TextTestRunner(f_txt, verbosity=2)
text_runner.run(discover)
f_txt.close()
????????(2)运行结果
? ? ? ? ?注意:此运行结果已存入(unittest_result.txt)文件中
test_add (unittest_frame.MyMathUnittest) test_是测试用例:加法运算-正向 ... ok test_add_1 (unittest_frame.MyMathUnittest) test_是测试用例:加法运算-反向 ... ERROR test_add_2 (unittest_frame.MyMathUnittest) test_是测试用例:加法运算-正向 ... ok test_ae (unittest_frame.MyMathUnittest) 断言方法assertEqual---判断相等 ... FAIL test_af (unittest_frame.MyMathUnittest) 断言方法assertFalse---判断布尔值为False ... FAIL test_ai (unittest_frame.MyMathUnittest) 断言方法assertIn---判判断a在b中 ... FAIL test_aii (unittest_frame.MyMathUnittest) 断言方法assertIsInstance--- 判断a是b的实例对象 ... FAIL test_ais (unittest_frame.MyMathUnittest) 断言方法assertIs---判断身份(内存地址值)相等 ... FAIL test_ais_none (unittest_frame.MyMathUnittest) 断言方法assertIsNone---判断为空指针 ... FAIL test_ais_not (unittest_frame.MyMathUnittest) 断言方法assertIsNot---判判断身份(内存地址值)不相等 ... FAIL test_ais_not_none (unittest_frame.MyMathUnittest) 断言方法assertIsNotNone---判断不为空指针 ... FAIL test_ane (unittest_frame.MyMathUnittest) 断言方法assertNotEqual---判断不相等 ... FAIL test_ani (unittest_frame.MyMathUnittest) 断言方法assertNotIn---判断a不在b中 ... FAIL test_anii (unittest_frame.MyMathUnittest) 断言方法assertNotIsInstance---判断a不是b的实例对象 ... FAIL test_at (unittest_frame.MyMathUnittest) 断言方法assertTrue---判断布尔值为True ... FAIL test_multiply (unittest_frame.MyMathUnittest) test_是测试用例: ... ok ====================================================================== ERROR: test_add_1 (unittest_frame.MyMathUnittest) test_是测试用例:加法运算-反向 ---------------------------------------------------------------------- Traceback (most recent call last): File "C:\Users\Songhe\PycharmProjects\bigbearTest\WEB自动化测试Python+Selenium\ps_unittest\unittest_frame.py", line 99, in test_add_1 add_value = self.mm.add("a", 1) File "C:\Users\Songhe\PycharmProjects\bigbearTest\WEB自动化测试Python+Selenium\ps_unittest\my_math.py", line 19, in add return a + b TypeError: can only concatenate str (not "int") to str ====================================================================== FAIL: test_ae (unittest_frame.MyMathUnittest) 断言方法assertEqual---判断相等 ---------------------------------------------------------------------- Traceback (most recent call last): File "C:\Users\Songhe\PycharmProjects\bigbearTest\WEB自动化测试Python+Selenium\ps_unittest\unittest_frame.py", line 112, in test_ae self.assertEqual(1, 2) AssertionError: 1 != 2 ====================================================================== FAIL: test_af (unittest_frame.MyMathUnittest) 断言方法assertFalse---判断布尔值为False ---------------------------------------------------------------------- Traceback (most recent call last): File "C:\Users\Songhe\PycharmProjects\bigbearTest\WEB自动化测试Python+Selenium\ps_unittest\unittest_frame.py", line 126, in test_af self.assertFalse(1 == 1) AssertionError: True is not false ====================================================================== FAIL: test_ai (unittest_frame.MyMathUnittest) 断言方法assertIn---判判断a在b中 ---------------------------------------------------------------------- Traceback (most recent call last): File "C:\Users\Songhe\PycharmProjects\bigbearTest\WEB自动化测试Python+Selenium\ps_unittest\unittest_frame.py", line 154, in test_ai self.assertIn(1, [2, 3, 4]) AssertionError: 1 not found in [2, 3, 4] ====================================================================== FAIL: test_aii (unittest_frame.MyMathUnittest) 断言方法assertIsInstance--- 判断a是b的实例对象 ---------------------------------------------------------------------- Traceback (most recent call last): File "C:\Users\Songhe\PycharmProjects\bigbearTest\WEB自动化测试Python+Selenium\ps_unittest\unittest_frame.py", line 164, in test_aii self.assertIsInstance(1, str) AssertionError: 1 is not an instance of <class 'str'> ====================================================================== FAIL: test_ais (unittest_frame.MyMathUnittest) 断言方法assertIs---判断身份(内存地址值)相等 ---------------------------------------------------------------------- Traceback (most recent call last): File "C:\Users\Songhe\PycharmProjects\bigbearTest\WEB自动化测试Python+Selenium\ps_unittest\unittest_frame.py", line 133, in test_ais self.assertIs(a, c) AssertionError: 1 is not 2 ====================================================================== FAIL: test_ais_none (unittest_frame.MyMathUnittest) 断言方法assertIsNone---判断为空指针 ---------------------------------------------------------------------- Traceback (most recent call last): File "C:\Users\Songhe\PycharmProjects\bigbearTest\WEB自动化测试Python+Selenium\ps_unittest\unittest_frame.py", line 144, in test_ais_none self.assertIsNone(1) AssertionError: 1 is not None ====================================================================== FAIL: test_ais_not (unittest_frame.MyMathUnittest) 断言方法assertIsNot---判判断身份(内存地址值)不相等 ---------------------------------------------------------------------- Traceback (most recent call last): File "C:\Users\Songhe\PycharmProjects\bigbearTest\WEB自动化测试Python+Selenium\ps_unittest\unittest_frame.py", line 138, in test_ais_not self.assertIsNot(a, b) AssertionError: unexpectedly identical: 1 ====================================================================== FAIL: test_ais_not_none (unittest_frame.MyMathUnittest) 断言方法assertIsNotNone---判断不为空指针 ---------------------------------------------------------------------- Traceback (most recent call last): File "C:\Users\Songhe\PycharmProjects\bigbearTest\WEB自动化测试Python+Selenium\ps_unittest\unittest_frame.py", line 148, in test_ais_not_none self.assertIsNotNone(None) AssertionError: unexpectedly None ====================================================================== FAIL: test_ane (unittest_frame.MyMathUnittest) 断言方法assertNotEqual---判断不相等 ---------------------------------------------------------------------- Traceback (most recent call last): File "C:\Users\Songhe\PycharmProjects\bigbearTest\WEB自动化测试Python+Selenium\ps_unittest\unittest_frame.py", line 116, in test_ane self.assertNotEqual(1, 1) AssertionError: 1 == 1 ====================================================================== FAIL: test_ani (unittest_frame.MyMathUnittest) 断言方法assertNotIn---判断a不在b中 ---------------------------------------------------------------------- Traceback (most recent call last): File "C:\Users\Songhe\PycharmProjects\bigbearTest\WEB自动化测试Python+Selenium\ps_unittest\unittest_frame.py", line 158, in test_ani self.assertNotIn(1, [1, 2, 3]) AssertionError: 1 unexpectedly found in [1, 2, 3] ====================================================================== FAIL: test_anii (unittest_frame.MyMathUnittest) 断言方法assertNotIsInstance---判断a不是b的实例对象 ---------------------------------------------------------------------- Traceback (most recent call last): File "C:\Users\Songhe\PycharmProjects\bigbearTest\WEB自动化测试Python+Selenium\ps_unittest\unittest_frame.py", line 168, in test_anii self.assertNotIsInstance(1, int) AssertionError: 1 is an instance of <class 'int'> ====================================================================== FAIL: test_at (unittest_frame.MyMathUnittest) 断言方法assertTrue---判断布尔值为True ---------------------------------------------------------------------- Traceback (most recent call last): File "C:\Users\Songhe\PycharmProjects\bigbearTest\WEB自动化测试Python+Selenium\ps_unittest\unittest_frame.py", line 122, in test_at self.assertTrue(1 == 2) AssertionError: False is not true ---------------------------------------------------------------------- Ran 16 tests in 0.003s FAILED (failures=12, errors=1)
? ? ? ? 四、脚本优化
????????1、测试用例主执行文件
? ? ? ? (1)使用默认的可共享的加载器更方便加载更多的测试用例
????????discover = unittest.defaultTestLoader.discover("./模块目录", "模块名正则表达式.py")
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# author:bigbear
# datetime:2022/9/16 10:18
# software: PyCharm
"""测试用例主执行文件"""
import unittest
discover = unittest.defaultTestLoader.discover("./", "unittest_frame_*.py")
with open("unittest_result1.txt", "a", encoding="utf-8") as f:
test_runner = unittest.TextTestRunner(f, verbosity=2)
test_runner.run(discover)
????????2、测试结果优化
? ? ? ? (1)格式优化---HTML
????????# HTTPTestRunner().run(测试套件):执行测试用例,并将结果以HTML页面形式写入文件中
with open("unittest_result.html", "wb", encoding="utf-8") as f_html:
????????# wb:以字节形式写入文件
????????# verbosity=1:日志详细等级;,0表示无日志,1表示只显示省略号,2表示每条测试用例是否执行成功都会显示
????????# title="":网页标题
????????# descriptions="":测试描述
????????html_runner =?HTTPTestRunner.HTMLTestRunner(f_html, verbosity=2, title="页面标题",description="测试描述")
????????html_runner.run(discover)
? ? ? ??f_html.close()
import HTTPTestRunner
...
if __name__ == '__main__':
"""此文件运行时执行"""
# 加载测试用例到测试套件中
discover = unittest.defaultTestLoader.discover("./", "unit*.py")
# wb写入字节格式,才能保存到html中
with open("unittest_result.html", "wb") as f_html:
# TextTestRunner().run(测试套件):执行测试用例,并将结果以Text文本形式写入文件中
html_runner = HTTPTestRunner.HTMLTestRunner(f_html, verbosity=2, title="unittest测试框架HTML格式测试结果",
description="运行XX测试用例的结果展示")
html_runner.run(discover)
f_html.close()
?????????(2)显示优化---文档注释
在每个测试用例中添加文档"""一行注释"""
class MyMathUnittest(unittest.TestCase):
"""继承单元测试框架的单元测试用例类"""
def test_add(self):
"""test_是测试用例:加法运算-正向"""
????????(3)存储优化---命名规范
????????# 文件命名:路径+时间格式+ .html
filename = f"../测试报告/{time.strftime('%Y-%m-%d-%H-%M-%S')}.html"
????????注意时间格式获取方法:
time.time() ?# 获取当前时间戳
time.ctime() ?# 获取当前时间的字符串格式
time.localtime() ?# 获取当前时间的结构化格式
time.strftime() ?# 获取当前时间,并可格式化为字符串
%Y Year with century as a decimal number.
%m Month as a decimal number [01,12].
%d Day of the month as a decimal number [01,31].
%H Hour (24-hour clock) as a decimal number [00,23].
%M Minute as a decimal number [00,59].
%S Second as a decimal number [00,61].
%z Time zone offset from UTC.
%a Locale's abbreviated weekday name.
%A Locale's full weekday name.
%b Locale's abbreviated month name.
%B Locale's full month name.
%c Locale's appropriate date and time representation.
%I Hour (12-hour clock) as a decimal number [01,12].
%p Locale's equivalent of either AM or PM.?
# 文件命名:路径+时间格式+ .html
time_format = time.strftime('%Y-%m-%d-%H-%M-%S')
filename = f"测试报告/{time_format}.html"
with open(filename, "wb") as f_html:
????????3、测试报告输出---SMTP(未完结)
????????集成右键自动发送:脚本运行结束后,将测试结果自动发送给相关负责人。
????????email模块:构造邮件
????????smtplib模块发送邮件
????????登录密码是授权码
????????五、项目结构
????????优点:方便分类、方便分工协作
????????1、public
????????公共模块,如登录和退出系统模块,被test_case中模块调用的模块(发邮件、写日志)
????????2、test_cases
????????测试用例文件py,每个文件可以有多个test_开头的测试方法(用例)
????????3、test_datas
????????测试数据,如csv、excel文件
????????4、test_reports
????????测试结果报告
????????5、test.py
????????主测试类
????????6、attachments
????????附件模块
????????7、confs
????????配置文件?
?
? ? ? ? 六、unittest框架下的数据驱动测试
????????1、再看数据存储
????????大部分自动化测试采用测试脚本与测试数据分离
????????好处:降低维护成本,迁移成本以及提高效率
????????
????????存储形式:
????????字典、列表(脚本内)
????????excel、csv、配置文件、数据库存储(脚本外)
测试数据分类管理示例
业务场景 | 普通登录 | 管理员登录 | 数据库连接 | 数据类型 | 基础数据 | 测试数据 | 临时数据 | 数据频次 | 偶尔 | 经常 | 一直 | 数据量级 | 几个 | 几十~几千 | 几万以上 |
????????2、数据驱动测试(DDT)
????????@ddt? ? ? ? ? ? ?# 标记测试类,支持DDR数据驱动
????????@data()? ? ? ? ?# 标记测试用例,传递参数
????????@unpack? ? ? # 当@data()中的参数时元组、列表时,用于分割序列中的元素
????????@file_data? ? # 标记测试用例,传递文件,支持yaml和json文件
????????实例1---脚本内字典列表(字典中存数据,列表中存字典)
????????流程:
(1)创建字典列表数据dict_data
(2)加载ddt模块(安装ddt、导包(from ddt import ddt, data)
(3)在测试类前加@ddt
(4)在测试用例方法前加@data(*dict_data))
(5)重新声明测试用例名称(添加传递数据的参数reg_data)
(6)使用reg_data["key"]可以按顺序取键对应的值
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# author:bigbear
# datetime:2022/9/16 17:38
# software: PyCharm
"""
数据驱动测试(DDT)
@ddt # 标记测试类,支持DDR数据驱动
@data() # 标记测试用例,传递参数
@unpack # 当@data()中的参数时元组、列表时,用于分割序列中的元素
@file_data # 标记测试用例,传递文件,支持yaml和json文件
1、脚本内字典列表(字典中存数据,列表中存字典)
(1)创建字典列表数据dict_data
(2)加载ddt模块
安装ddt
导包(from ddt import ddt, data)
在测试类前加@ddt
在测试用例方法前加@data(*dict_data)
(3)重新声明测试用例名称(添加传递数据的参数reg_data)
(4)使用reg_data["key"]可以按顺序取键对应的值
"""
import time
import unittest
import ddddocr
from ddt import ddt, data
from selenium import webdriver
from selenium.webdriver.common.by import By
@ddt
class VRegUsernameFalse(unittest.TestCase):
"""用户注册---反向测试用例---无效用户名"""
# 定义字典数据,用于存储注册数据(用户名、邮箱、密码、确认密码)
dict_data = [
{"username": "", "email": "eeee@16.com", "password": "123456", "repassword": "123456",
"except": "请设置用户名"},
{"username": "a123", "email": "ffff@16.com", "password": "123456", "repassword": "123456",
"except": "用户名不符合格式要求"},
{"username": "a1234567890123456", "email": "gggg@16.com", "password": "123456", "repassword": "123456",
"except": "用户名不符合格式要求"},
{"username": "1234a", "email": "hhhh@16.com", "password": "123456", "repassword": "123456",
"except": "用户名不符合格式要求"},
{"username": "a12*4", "email": "iiii@16.com", "password": "123456", "repassword": "123456",
"except": "用户名不符合格式要求"}]
def setUp(self) -> None:
"""搭建测试环境"""
pass
@data(*dict_data)
def test_reg_01(self, reg_data):
"""反向测试用例-用户名"""
# 创建浏览器驱动对象
driver = webdriver.Edge()
# 打开edge浏览器并跳转到verydows首页
driver.get("http://kkk.xmyxwl.com/")
# 点击首页“免费注册”按钮
driver.find_element(by=By.LINK_TEXT, value="免费注册").click()
time.sleep(1)
# 用户名可以包含字母、数字或下划线,须以字母开头,长度为5~16个字符
driver.find_element(value="username").send_keys(reg_data["username"])
# 请填写您常用的电子邮箱地址,邮箱可用来重置密码,接收订促销信息,订单状态等
driver.find_element(value="email").send_keys(reg_data["email"])
# 密码可包含字母、数字或特殊符号,长度为6~32个字符
driver.find_element(value="password").send_keys(reg_data["password"])
# 确认您所设置的密码
driver.find_element(value="repassword").send_keys(reg_data["repassword"])
# 输入验证码:先将验证码截图成png图片存储在变量中,再通过ddddocr图文识别插件将验证码转换为字符串存储到变量中
captcha_img = driver.find_element(value="captcha-img").screenshot_as_png
captcha = ddddocr.DdddOcr().classification(captcha_img)
driver.find_element(value="captcha").send_keys(captcha)
time.sleep(0.5)
# 默认已勾选已阅读完并同意 "用户注册协议"复选框
# driver.find_element(value="agree").click()
# 点击立即注册链接
driver.find_element(by=By.LINK_TEXT, value="立即注册").click()
time.sleep(5)
# 注册失败,用户名后侧提示“请设置用户名”或“用户名不符合格式要求”
actual_value = driver.find_element(by=By.XPATH, value="//*[@id='register-form']/div/dl[1]/dd/span/font").text
except_value = reg_data["except"]
self.assertEqual(except_value, actual_value, "注册username反向测试用例失败")
driver.quit()
def tearDown(self) -> None:
"""重置测试环境"""
pass
if __name__ == '__main__':
unittest.main(verbosity=2)
????????实例2---脚本外excel文件
????????流程:
(1)创建excel文件verydows_reg_email_false.xls
(2)导入ExcelUtil模块
(3)导入excel文件数据,并转换为字典列表dict_data
(4)加载ddt模块(安装ddt、导包(from ddt import ddt, data)
(5)在测试类前加@ddt
(6)在测试用例方法前加@data(*dict_data))
(7)重新声明测试用例名称(添加传递数据的参数reg_data)
(8)使用reg_data["key"]可以按顺序取键对应的值
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# author:bigbear
# datetime:2022/9/16 17:38
# software: PyCharm
"""
数据驱动测试(DDT)
@ddt # 标记测试类,支持DDR数据驱动
@data() # 标记测试用例,传递参数
@unpack # 当@data()中的参数时元组、列表时,用于分割序列中的元素
@file_data # 标记测试用例,传递文件,支持yaml和json文件
2、脚本外excel文件
(1)创建excel文件verydows_reg_email_false.xls
(2)导入ExcelUtil模块
(3)导入excel文件数据,并转换为字典列表dict_data
(2)加载ddt模块
安装ddt
导包(from ddt import ddt,data)
在测试类前加@ddt
在测试用例方法前加@data(*dict_data)
(3)重新声明测试用例名称(添加传递数据的参数reg_data)
(4)使用reg_data["key"]可以按顺序取键对应的值
"""
import os
import sys
import time
import unittest
import ddddocr
from ddt import ddt, data
from selenium import webdriver
from selenium.webdriver.common.by import By
# 先将目录追加到环境变量中
path = os.path.dirname(os.path.dirname(__file__)) + "\\public"
path1 = sys.path
path1.append(path)
from ExcelUtil import ExcelUtil
@ddt
class VRegEmailFalse(unittest.TestCase):
"""用户注册---反向测试用例---无效邮箱"""
# 获取excel文件路径
filepath = os.path.dirname(os.path.dirname(__file__)) + "\\test_datas\\verydows_reg_email_false.xls"
# 读取excel文件数据
excel_data = ExcelUtil(filepath)
# 将excel数据转换为字典列表
dict_data = excel_data.dict_data()
def setUp(self) -> None:
"""搭建测试环境"""
pass
@data(*dict_data)
def test_reg_01(self, reg_data):
"""反向测试用例-用户名"""
# 创建浏览器驱动对象
driver = webdriver.Edge()
# 打开edge浏览器并跳转到verydows首页
driver.get("http://kkk.xmyxwl.com/")
# 点击首页“免费注册”按钮
driver.find_element(by=By.LINK_TEXT, value="免费注册").click()
time.sleep(1)
# 用户名可以包含字母、数字或下划线,须以字母开头,长度为5~16个字符
driver.find_element(value="username").send_keys(reg_data["username"])
# 请填写您常用的电子邮箱地址,邮箱可用来重置密码,接收订促销信息,订单状态等
driver.find_element(value="email").send_keys(reg_data["email"])
# 密码可包含字母、数字或特殊符号,长度为6~32个字符
driver.find_element(value="password").send_keys(reg_data["password"])
# 确认您所设置的密码
driver.find_element(value="repassword").send_keys(reg_data["repassword"])
# 输入验证码:先将验证码截图成png图片存储在变量中,再通过ddddocr图文识别插件将验证码转换为字符串存储到变量中
captcha_img = driver.find_element(value="captcha-img").screenshot_as_png
captcha = ddddocr.DdddOcr().classification(captcha_img)
driver.find_element(value="captcha").send_keys(captcha)
time.sleep(0.5)
# 默认已勾选已阅读完并同意 "用户注册协议"复选框
# driver.find_element(value="agree").click()
# 点击立即注册链接
driver.find_element(by=By.LINK_TEXT, value="立即注册").click()
time.sleep(5)
# 注册失败,用户名后侧提示“请设置用户名”或“用户名不符合格式要求”
actual_value = driver.find_element(by=By.XPATH, value="//*[@id='register-form']/div/dl[2]/dd/span/font").text
except_value = reg_data["except"]
self.assertEqual(except_value, actual_value, "注册email反向测试用例失败")
driver.quit()
def tearDown(self) -> None:
"""重置测试环境"""
pass
if __name__ == '__main__':
unittest.main(verbosity=2)
?
????????3、参数化传递数据
????????paramunittest??# 参数化库,同时支持 unittest、Nose 和 pytest 单元测试框架
????????流程:
(1)导包(import paramunittest)
(2)在测试类前加@paramunittest.parametrized(
????????????????("value1", "value2"),? # 第一种数据:在元组中按对应参数位置放值
????????????????(("value1",), {"key2": "value2"}),? # 第二种数据:在嵌套元组中按对应参数位置放值并为字典传值留空,同时用字典指定某一键(和参数名一致)值
????????????????((), {"key1": "value1", "key2": "value2"}),? ?# 第三种数据:在嵌套元组中为字典传值留空,同时用字典指定所有键(和参数名一致)值
????????????????{"key1": "value1", "key2": "value2"})? # 第四种数据:直接用字典中的键(和参数名一致)值对传值
(3)重新声明测试用例名称(添加传递数据的参数key1、key2...)
????????注意:参数化数据中的key-value必须和参数key位置一一对应,参数化数据中的key必须和参数中的key一致
????????parameterized??# 参数化库,同时支持 unittest、Nose 和 pytest 单元测试框架
????????流程:
(1)导包(from parameterized import parameterized)
(2)在测试用例方法前加@parameterized.expand([("value1", "value2",...),...])
(3)重新声明测试用例名称(添加传递数据的参数key1、key2、...)
????????注意:参数化数据中的每一个元组中的value必须和参数key位置一一对应
????????愿你我都能为中华民族的伟大复兴尽一份绵薄力量,让中华文化的根扎根在中国这片绿水青山之上,让新一代中华儿女传承与发扬!!!
---无名之辈
以上内容均是本人自学,当然是有网上公布的内容,如有冒犯,请留言,立即改正,谢谢!
? ? ? ? 看完要是觉得对自己有用,动一下您那根金色的会一指禅的右手食指,按一下您的鼠标左键,在对应的那个位置点个赞,亦或者在评论区留下您的绝顶好句,亦或者收藏在您的收藏夹里,再走也不迟嘛!您说要不要得!谢谢您的阅读和赞赏!
|