Web自动化—UnitTest框架


官方文档: https://docs.python.org/zh-cn/3/library/unittest.html

1 概念

框架framework是解决一类事情的功能集合
UnitTest是Python自带的一个单元测试框架,能够组织多个用例去执行,提供丰富的断言方法,能够生成测试报告。

2 UnitTest的核心要素

2.1 TestCase

TestCase用于新建测试用例。

2.1.1使用步骤

step1:导入unittest包:import unittest
step2:定义测试类,必须继承unittest.TestCase
step3:定义测试方法,方法名必须以test开头
step4:执行测试用例:

  • (1)使用pycharm在代码上点击鼠标右键,选择使用UnitTest运行

    • 运行所有用例: 光标定位到类
    • 运行单个用例: 光标定位到测试方法
  • (2)直接调用unittest.main():

    if __name__ == '__main__':
       unittest.main()
    

举个🌰:

# 导入unittest
import unittest
# 定义测试类
class Test01(unittest.TestCase):
    # 定义测试方法
    def test_01(self):
        print("第一个测试方法")
    def test_02(self):
        print("第二个测试方法")
# 执行测试方法
if __name__ == "__main__"  :
    unittest.main()

2.1.2 常见问题解决方案

(1)鼠标右键无法找到Run “TestUnits for XXX”

  • 解决方案:
    • step1: 依次点击Preferences…➡️ Tools ➡️ Python Integrated Tools

    • step2: 选择UnitTest后,点击OK
      在这里插入图片描述

    • step3:重新右键运行

(2)报错:AttributeError: module ‘unittest’ has no attribute ‘TestCase’

  • 解决方案:检查工程目录中是否存在名为“unittest”的文件,若存在则重命名文件

2.2 TestSuite和TestRunner

TestSuite用于归档需要一起执行的测试。多条测试用例集合在一起就是一个TestSuite。
TestRunner是一个用于执行和输出测试结果的组件。这个运行器可能使用图形接口、文本接口,或返回一个特定的值表示运行测试的结果。

2.2.1 使用步骤

step1:导入unittest包:import unittest

step2:实例化TestSuite:

  • suite = unittest.TestSuite()

step3:添加用例:

  • 添加指定类中指定的测试方法:suite.addTest(类名(“方法名”))
  • 添加指定类中所有以test开头的方法:suite.addTest(unittest.makeSuite(类名))

step4: 执行用例:

  • runner = unittest.TextTestRunner()
  • runner.run(suite)

2.3 TestLoader和TestRunner

搜索符合条件的TestCase到TestSuite中,即加载满足条件的测试用例,并把测试用例封装成测试套件。

2.3.1 使用步骤

step1: 导入unittest包

step2: 搜索指定目录下指定开头的.py文件,并将查找到的测试用例组装到测试套件中:
suite = unittest.TestLoader().discover(test_dir,pattern=“test*.py”)

suite = unittest.defaultTestLoader.discover(test_dir,pattern=“test*.py”)
defaultTestLoader是TestLoader的实例化

  • test_dir: 指定的目录文件
  • pattern:指定字母开头的模块文件,默认为"test*.py"

step3: 执行用例:

  • runner = unittest.TextTestRunner()
  • runner.run(suite)

2.4 Fixture

测试脚手架,表示为了开展一项或多项测试所需要进行的准备工作,以及所有相关的清理操作。Fixture是一个概述,对一个测试用例环境的初始化和销毁就是一个Fixture。
Fixture有3个控制级别,分别是函数级别,类级别和模块级别

2.4.1 函数级别

初始化:def setUp()
销毁:def tearDown()
每个测试函数执行之前都会执行 setUp,执行之后都会执行tearDwon,运行一次测试方法就会运行一次setUp和tearDown。

2.4.2 类级别

(1)初始化:
@classmethod
def setUpClass(cls)

(2)销毁
@classmethod
def tearDownClass(cls)

测试类运行之前运行一次setUpClass 类,运行之后运行一次tearDownClass类,每个测试类只会运行一次setUpClass和tearDownClass。

2.4.3 模块级别

初始化:def setUpModule()
销毁:def tearDownModule()
模块运行之前执行一次setUpModule ,运行之后运行一次tearDownModule,整个模块只会运行一次setUpModule和tearDownModule

2.4.4 常用场景

(1)初始化:隐式等待、浏览器最大化、获取浏览器实例化对象
(2)结束:关闭浏览器驱动对象

3 断言

3.1 概念

断言是让程序代替人为判断测试程序执行结果是否符合预期结果的过程;因为我们在执行自动化测试的时候,一般都无人值守,所以需要通过断言去检测实际结果与预期是否相符。

3.2 断言的使用方式及常用方法

断言方法定义在unittest.TestCase类中,在定义的测试类中直接调用断言方法:
(1)assertEqual(arg1,arg2,msg=None): 是否相等

(2)assertNotEqual(arg1, arg2,msg=None):是否不等

(3)assertTrue(expr, msg=None):是否为真

(4)assertFalse(expr,msg=None):是否为假

(5)assertIs(arg1, arg2,msg=None):谁否为同一个对象

(6)assertIsNot(arg1, arg2,msg=None):是否不是同一个对象

(7)assertIsNone(expr,msg=None):是否为None

(8)assertIsNotNone(expr,msg=None):是否不为None

(9)assertIn(arg1, arg2,msg=None):arg1是否为arg2的子串

(10)assertNotIn(arg1, arg2,msg=None):arg1是否不为arg2的子串

(11)assertIsInstance(obj, cls,msg=None):obj是否为cls的实例

(12)assertNotIsInstance(obj, cls,msg=None):obj是否不为cls的实例

(13)assertAlmostEqual (first,second, places = 7, msg = None, delta = None):验证first约等于second。 palces: 指定精确到小数点后多少位, 默认为7

(14):assertNotAlmostEqual (first,second, places, msg, delta):验证first不约等于second。 palces: 指定精确到小数点后多少位, 默认为7 注: 在上述的两个函数中,如果delta指定了值, 则first和second之间的差值必须
≤delta。

(15)assertGreater (first, second,msg = None):first 是否大于 second

(16)assertGreaterEqual (first,second, msg = None):first 是否大于等于second

(17)assertLess (first, second,msg = None):first 是否小于 second

(18)assertLessEqual (first,second, msg = None):first 是否小于等于 second

(19)assertRegexpMatches (text,regexp, msg = None):验证正则表达式regexp搜索匹配的文本text。regexp: 通常使用re.search()

(20)assertNotRegexpMatches(text, regexp, msg = None):验证正则表达式regexp搜索不匹配的文本text。regexp: 通常使用re.search() 说明: 两个参数进行比较(>、 ≥、 <、 ≤、 约等、 不约等)

(21)assertListEqual(list1, list2,msg = None):验证列表list1和list2是否相等

(22)assertTupleEqual (tuple1,tuple2, msg = None):验证两个元祖是否相等

(23)assertSetEqual (set1, set2,msg = None):验证两个集合是否相等

(24)assertDictEqual (expected,actual, msg = None):验证两个字典是否相等

以上方法判断结果若为false,会抛出AssertionError异常,可以通过捕获AssertionError异常进行相应的处理:

try:
    断言方法
except AssertionError as e:
    异常处理
    raise e
import time
import unittest
from selenium import webdriver
class TestLogin(unittest.TestCase):
	def setUp(self):
		self.driver = webdriver.Chrome()
		self.driver.get("http://127.0.0.1")
		self.driver.implicitly_wait(10)
		self.driver.maximize_window()
		
	def test_login(self):
		self.driver.find_element_by_link_text("登录").click()
		self.driver.find_element_by_id("username").send_keys("13032820000")
		self.driver.find_element_by_id("password").send_keys("123456")
		self.driver.find_element_by_css_selector("[name='sbtbutton']").click()
		# 获取错误提示信息
		print(self.driver.find_element_by_css_selector(".layui-layer-content").text)
		try:
			# 断言
			self.assertIn("验证码不能为空", msg)
		except AssertionError as e:
			# 保存截图
			self.driver.get_screenshot_as_file("./imgs/img{}.png".format(time.strftime("%Y%m%d-%H%M%S")))
			raise e
	def tearDown(self):
		self.driver.quit()
		
if __name__ == '__main__':
	unittest.main()

4 参数化

unittest测试框架,通过安装unittest扩展插件parameterized来实现参数化用户数据驱动,避免写多个方法(冗余)。通过参数的方式来传递数据,从而实现数据和脚本分离,并且可以实现用例的重复执行。

4.1 使用步骤

step1: 安装parameterized插件: pip install parameterized
step2: 导包:from parameterized import parameterized
step3: 使用@parameterized.expand装饰器为测试函数的参数进行参数化

4.2 使用方式

测试两个参数相加:

def add(x, y):
	return x + y

4.2.1 方式1

@parameterized.expand([(1, 1, 2), (1, 0, 1), (0, 0, 0)])
	def test_add(self, x, y, expect):
		print("x={} y={} expect={}".format(x, y, expect))
		result = add(x, y)
		self.assertEqual(result, expect)

4.2.2 方式2

data = [(1, 1, 2), (1, 0, 1), (0, 0, 0)]
@parameterized.expand(data)
def test_add(self, x, y, expect):
	print("x={} y={} expect={}".format(x, y, expect))
	result = add(x, y)
	self.assertEqual(result, expect)

4.2.2 方式3

def build_data():
	return [(1, 1, 2), (1, 0, 1), (0, 0, 0)]
	
@parameterized.expand(build_data)
def test_add(self, x, y, expect):
	print("x={} y={} expect={}".format(x, y, expect))
	result = add(x, y)
	self.assertEqual(result, expect)

5 把测试函数标记成 跳过

对于一些未完成或不满足测试条件的测试函数和测试类,跳过执行。

5.1 直接将测试函数标记为跳过

@unittest.skip('代码未完成')

5.2 根据条件判断测试函数是否判断

@unittest.skipIf(条件, 描述)

6 生成HTML测试报告

6.1 Export Test Results

step1: 点击Export Test Results小图标
在这里插入图片描述
step2: 选择导出的文件格式,以及文件名和存放路径
在这里插入图片描述
step3: 查看报告
在这里插入图片描述

6.2 HTMLTestRunner

HTMLTestRunner是一个第三方的unittest HTML报告库

step1: 下载HTMLTestRunner.py : http://tungwaiyip.info/software/HTMLTestRunner.html

step2: 导入HTMLTestRunner和unittest包

step3: 生成测试套件

suite = unittest.TestSuite()
suite.addTest(类名("方法名")) 
# suite.addTest(unittest.makeSuite(类名))
# suite = unittest.defaultTestLoader.discover(test_dir, pattern="test*.py")

step3: 设置报告生成路径和文件名
file_name = "./report/report.html"

step4: 打开报告
with open(file_name,'wb') as f:

step5: 实例化HTMLTestRunner对象
runner = HTMLTestRunner(stream=f,[title],[description])
stream: 文件流,打开写入报告的名称及写入编码格式)
title:报告标题,可选
description:报告描述信息,可选

step6: 执行测试用例:
runner.run(suite)

import time
import unittest
from HTMLTestRunner import HTMLTestRunner
suite = unittest.defaultTestLoader.discover("./", "test*.py")
report_path = "./report/report{}.html".format(time.strftime("%Y%m%d%H%M%S"))
with open(report_path, "wb") as f:
	runner = HTMLTestRunner(stream=f, title="测试报告", description="测试报告的描述信息"
)
  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值