【如何学习Python自动化测试】—— Python 的 unittest 框架

10 、Python 的 unittest 框架

10.1 Unittest 框架介绍

      Unittest是Python语言中的一种测试框架,是Python标准库中的一个模块。它可以帮助开发者编写自动化测试,可以进行单元测试、集成测试、功能测试等各种类型的测试。 Unittest的特点是简单易学,文档齐全,可以为每个测试用例创建独立的环境,可以根据测试结果输出详细的测试报告。
      Unittest模块中提供了很多方便测试的工具,如assertEqual、assertTrue、assertFalse、assertRaises等。使用Unittest测试框架可以提高开发的质量和效率,有效减少开发期和维护期中出现的问题,对于大型项目特别是团队合作开发中,使用Unittest测试框架可以提高代码的可维护性,降低开发和维护的成本。
      Unittest 是 python 的单元测试框架,原名为 PyUnit,由 java 的 junit 演化而来。
      Unittest 提供了 test case、test suites、test fixtures、test runnet。

  • Test case(测试用例):是一个单独的测试单元,用于测试一个或多个特定的代码路径。
  • Test suite(测试套件):是一系列测试用例的集合。测试套件是按照测试计划所定义的各个阶段的测试目标决定的,即先有测试计划,后面才有测试套件。
  • Test fixture(测试固件):是为测试提供必要的环境和资源(如数据库连接)的代码。在测试之前和之后执行。(setup + test case + teardown 的组合)
  • Test runner(测试运行器):是执行多个测试用例或测试套件的程序组件。它收集测试结果并生成测试报告。

      在 Python 中,unittest 是一个内置的测试框架,可用于编写单元测试。它提供了类和方法来组织和运行测试用例。使用 unittest,我们可以轻松地编写和运行单元测试并生成详细的测试报告。

      Unittest 结构:
在这里插入图片描述

10.2 Unittest 框架详解

10.2.1 测试用例

      在 unittest 中没有明确究竟 test 的 class 是测试用例,还是 class 中的 test 开头的方法 是测试用例,在下面的案例中,我们将 test 开头的方法作为测试用例来执行。
      先看一个简单的案例:

import unittest
在使用 unittest 框架时,需要先导入 unittest

class login_test(unittest.TestCase):
创建一个测试类,该类继承 unittest 的 TestCase。 

	def setUp(self):
		Setup 是测试执行之前的操作, 会在用例执行之前先执行这里的内容,通常用来初始化环境
		self.testa=10
		self.testb=10
		
	def test_login(self):
		要执行的测试 1
		self.assertTrue(self.testa == self.testb)
		
	def test_login2(self):
		要执行的测试 2
		try:
		self.testc=30
		self.assertTrue(self.testa == self.testc)
		except AssertionError:
		self.fail("test is false")
		
	def tearDown(self):
		执行结束之后的操作, 通常用来执行还原测试环境的操作
		print('Test Runner End')
		
if __name__ == '__main__':
	unittest.main()
	调用 unittest 的开始执行

      在使用 unittest 前,需要先导入 unittest 的包,在这个包中包含了 unittest 提供的各种类,如:TestCase、TestSuite、TextTestRunner、TestLoader、main 等等。
      创建一个 login_test 的 class,用来测试,该类继承 TestCase,从而能够使用 TestCase 中的方法。
      Setup 方法是 TestCase 中的方法,这里是重写 TestCase 的 setup 方法,该方 法用来做测试执行前的操作,比如构建测试数据,打开浏览器、链接数据库等操作。
      下面的 tearDown 方法相同,区别在不该方法用于执行测试执行结束后的操作,比如关闭浏览器,释放数据库连接操作。
      中间以 test 开头的方法,则会被当做测试用例来执行,运行该脚本时,unittest 会自动加载这些 test 开头的方法,来执行测试。
      Unitest.main 是调用 unittest 的执行方法,这里是测试执行的入口。

10.2.2 测试套

      测试套又称测试集,也叫测试套件,通常是一组测试用例的集合,通过 suite 可以执行一组测试用例。 下面的代码是针对 LMD 的登陆测试,如果登陆成功,则获取他的 title,判断 title 是否不预期结果一致,如果一致,则测试成功,否则用例执行失败。 这个案例通过 suite 实现的。代码如下:

#coding=utf-8
__author__ = 'Administrator'
import unittest
from selenium import webdriver
import HTMLTestRunner
from selenium.webdriver.support import expected_conditions
class login_test2(unittest.TestCase) :
	def setUp(self):
		self.driver = webdriver.Firefox()
		self.driver.maximize_window()

	def test_login(self):
		driver = self.driver
		driver.get('http://www.chuangyijia.com/login')
		driver.find_element_by_id('email').send_keys('810155067@qq.com')
		driver.find_element_by_id('pwd').send_keys('a654321')
		driver.find_element_by_css_selector('#submit').click()
		test=expected_conditions.title_is(u'创意家,登录') self.assertTrue(test(driver))

def tearDown(self):
	self.driver.quit()

if __name__ == '__main__':
	suite=unittest.TestLoader().loadTestsFromTestCase(login_test2)
		unittest.TextTestRunner().run(suite)

      这段代码中,上面的内容和之前没有上面差别,主要在 if name==’ main__’的内容,这句话的意思为“Make a script both importable and executable”,解释过来就是让你写的脚本模块既可以导入到别的模块中用,另外 该模块自己也可执行。试代码的时候,在”if name == ‘main’ “中加入一些 我们的调试代码,我们可以让外部模块调用的时候不执行我们的调试代码,但是如果 我们想排查问题的时候,直接执行该模块文件,调试代码能够正常运行!

      Unittest.TestLoader:源代码解释为“This class is responsible for loading tests according to various criteria and returning them wrapped in a TestSuite ”意思可以通过该类完成测试用例的加载,将用例加载到 siuter 中,但是需要调用该类的 loadTestFromTestCase 方法来加载用例,该方法接收参数为测试类,也就是 我们上面定义的 login_test2 的类名。这句代码就会将该类中以 test 开头的方法加载到 suiter 中。 Suiter 变量用来接收加载后的结果。
      通过 unittest 调用他的 TextTestRunner 类中的 run 方法来执行测试,run 方法 需要将 suiter 作为参数传入。TextTestRunner 是以文本形式显示测试结果,如果测试失败,会显示失败的测试名称,并统计测试的结果。run 方法是运行传入的 case 或 suiter。

10.2.3 断言

      在编程中,通常会做一些假设,使用断言,去判断一个代码处理的结果是否和自己的预期相符,如果符合则为 True,否则为 false。在测试中,我们也会有这样的需求,执行一个测试,给一个预期结果,来断言实际结果不预期结果是否符合,不符合 则测试失败,符合则执行成功。
      在 unittest 的 TestCase 中给我们提供了很丰富的断言操作,下面罗列出了常用的一些断言。

  • assertTrue:检查表达式返回值是否为真 True ,返回值类型为布尔类型。
  • assertFalse:不上面相反,检查表达式返回是否为假 False ,布尔类型。
  • assertEqual(arg1, arg2, msg=None):验证 arg1 和 arg2 是否相等。
  • assertNotEqual(arg1, arg2, msg=None):验证 arg1 和 arg2 是否不相等。
  • assertIs(arg1, arg2, msg=None):验证 arg1 和 arg2 是否为同一个对象。
  • assertIsNot(arg1, arg2, msg=None):验证 arg1 和 arg2 是否不为同一个对象。
  • assertIsNone(expr, msg=None):验证 expr 是否为 none,是则返回 True。
  • ssertIsNotNone(expr, msg=None):验证 expr 是否不为 none,是则返回 True。
  • assertIn(arg1, arg2, msg=None):验证 arg1 是否在 arg2 中 ,是则 True
  • assertNotIn(arg1, arg2, msg=None):验证 arg1 不在 arg2 的中,是则 fail

示例:

#coding=utf-8
__author__ = 'Administrator'
import unittest
class Test_Asser(unittest.TestCase):
	def test_assertTrue(self):
		self.assertTrue(5>4)
		5>4 则返回 True,否则返回 False
		
	def test_assertFalse(self) :
		self.assertFalse(5<4)
		表达式成立则返回 False,否则返回 True
	
	def test_assertEqual(self) :
		self.assertEqual(u"中国",u"中国")
		两个字符串相等,则返回 True,否则返回 False
	
	def test_assertNotEqual(self):
		self.assertNotEqul(u"中国 1",u"中国 2")
		两个字符串不相等,返回 True,否则返回 false
	
	def test_assertIs(self):
		a=10
		a=20
		self.assertIs(a,a)
		a 是一个变量,下面的是对 a 重新赋值,所以依然是一个对象, 所以此处返回 True,否则返回 false。
	
	def test_assertIsNot(self) :
		a=10
		b=20
		self.assertIsNot(a,b)
		a 和 b 是两个变量,不属于同一个对象 ,所以此处返回 True, 否则返回 False
	
	def test_assertIsNone(self):
		a=None
		self.assertIsNone(a)
		None 在 python 中是一个特殊的空值,即表示空值,也可以表 示为空对象。在这里给 a 赋值为 None,那么 a 就是一个空对象,此处 返回 True,否则返回 false
		def test_assertIsNotNone(self):
		c=10
		self.assertIsNotNone(c)
		与上面相反, c 是一个有值的对象,这里判断 c 是不是不为 None,是则返回 True,否则返回 Falsedef test_assertIsIn(self):
	text="abcdef"
	t='c'
	self.assertIn(t,text)
	判断 t 的值是否在 text 中,如果在则返回 True,否则返回 Falsedef test_assertIsNotIn(self):
		text="abcdef"
		self.assertNotIn('h',text)
		判断字符 h 是否不在 text 中,不在则返回 True,否则返回 false.
		
if __name__ == '__main__':
	unittest.main()

      当然在 unittest 中不叧是这些断言,还有其他断言,后续会慢慢加入。

10.3 测试批量执行

下面做两个测试的案例,先创建目录结构:
      主目录:Lmd_auto_test
      次目录:Lmd_auto_test\test_case
      在 test_case 目录中有 login_auto.py 和 Release_Creative.py 两个脚本。
      将下面的代码保存为 login_auto.py

#coding=utf-8
__author__ = 'Administrator'
from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions
import time
import unittest

class login_test_case(unittest.TestCase):
	def setUp(self):
		self.driver = webdriver.Firefox()
		self.driver.maximize_window()
		self.driver.get('http://www.chuangyijia.com/login')
		def tearDown(self):
		self.driver.quit()
		
	def test_login(self):
		self.driver.find_element_by_id('email').send_keys('810155067@qq.com')
		self.driver.find_element_by_id('pwd').send_keys('a654321')
		self.driver.find_element_by_id('submit').click()
		#self.driver.implicitly wait(5)
		time.sleep(3)
		WebDriverWait(self.driver,30).until(expected_conditions.visib
		ility_of_element_located((By.CSS_SELECTOR,'.logo')))
		print self.driver.title
		is_title = expected_conditions.title_is(u'首页-创意家') 	
		self.assertTrue(is_title(self.driver))

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

下面的文件保存为 Release_Creative.py

#coding=utf-8
__author__ = 'Administrator'
from selenium import webdriver
from selenium.webdriver.support import expected_conditions
from selenium.webdriver.common.action_chains import ActionChains
import unittest
import sys
import os,time
class release_creat(unittest.TestCase) :
def setUp(self):
	self.driver = webdriver.Firefox()
	self.driver.maximize_window()
	self.driver.get('http://www.chuangyijia.com/login')
	
	self.driver.find_element_by_id('email').send_keys('810155067@qq.com')
	
	self.driver.find_element_by_id('pwd').send_keys('a654321')
	self.driver.find_element_by_id('submit').click()
	time.sleep(3)
	#is title = expected conditions.title is(u'首页-创意家') #self.assertTrue(is title(self.driver))
	
	def test_release(self):
		self.driver.find_element_by_css_selector('.menu >ul:nth-child(1) > li:nth-child(1) > a:nth-child(1)').click()
		self.driver.find_element_by_css_selector('.c01 > a:nth-child(1)').click()
		
		self.driver.find_element_by_name('mobile').send_keys('1943235923')
		
		self.driver.find_element_by_css_selector('.idea_name').send_k eys(u"发布中文创意")
		self.driver.find_element_by_id('province').click()
		
		self.driver.find_element_by_xpath('//option[contains(text()," 江苏")]').click()
		self.driver.find_element_by_id('city').click()
		
		self.driver.find_element_by_xpath('//option[contains(text()," 南京")]').click()
		text=u"预售管理,后台管理员可以修改时间, 并且只能修改为 当月的日期, 不能修改年月"
 
		self.driver.find_element_by_css_selector('#pForm >table:nth-child(11) > tbody:nth-child(1) > tr:nth-child(1) > td:nth-child(1) > table:nth-child(1) > tbody:nth-child(1) >  tr:nth-child(6) > td:nth-child(2) > textarea:nth-child(1)').send_keys(text)
		self.driver.find_element_by_css_selector('#pForm >table:nth-child(11) > tbody:nth-child(1) > tr:nth-child(1) > td:nth-child(1) > table:nth-child(1) > tbody:nth-child(1) >  tr:nth-child(7) > td:nth-child(2) > textarea:nth-child(1)').send_keys(u"没有问题。。。。 ")
		self.driver.find_element_by_css_selector('#pForm >table:nth-child(11) > tbody:nth-child(1) > tr:nth-child(1) > td:nth-child(1) > table:nth-child(1) > tbody:nth-child(1) >  tr:nth-child(8) > td:nth-child(2) > textarea:nth-child(1)').send_keys(u"不需要解决")
		
		self.driver.find_element_by_name('support_end_date').send_keys('2017-8-18')
		time.sleep(2)
		
		self.driver.find_element_by_css_selector('.c_btn').click()
		
		self.driver.find_element_by_css_selector('.c_btn').click()
		os.system("H:\\pydj\\Lmd_auto_test\\testjpg.exe")
		time.sleep(2)
		put2 =self.driver.find_element_by_css_selector('#upimg_1')
		put1 =self.driver.find_element_by_css_selector('.cy_pic > ul:nth-child(1) > li:nth-child(1) > input:nth-child(3)')
		
		ActionChains(self.driver).move_to_element(put2).perform()
		self.driver.find_element_by_css_selector('.cy_pic >ul:nth-child(1) > li:nth-child(1) > input:nth-child(3)').click()
		os.system("H:\\pydj\\Lmd_auto_test\\testjpg.exe")
		#self.driver.find element by_css selector('.cy_pic >ul:nth-child(1) > li:nth-child(2) > input:nth-child(3)').click()
		#os.system("H:\pydj\Lmd auto test\testjpg.exe")
		
		self.driver.find_element_by_id('saveBtn').click()
		time.sleep(2)
		is_exist = self.driver.find_element_by_css_selector('div.item:nth-child(1) > div:nth-child(2) > a:nth-child(1)')
		Creat_Name = is_exist.text
		self.assertEqual(Creat_Name,u"发布中文创意")
		#self.assertTrue(is exist)

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

      上面的两个文件,一个是测试登陆功能的用例,另一个是测试创意发布的用例,这里对成功和失败都做了简单的判断,例如登陆,在判断登陆后,title 是否为登陆成功的title,是则执行通过,否则执行失败。创意发布时,判断提交后,该创意是否在发布的列表中,并在第一个,如果是,则执行成功,否则执行失败。
      在 test_case 的目录中创建__init__.py 文件,文件内容如下:

#coding=utf-8
__author__ = 'Administrator'
import login_auto
import Release_Creative

      在 Lmd_auto_test 目录下创建 run_test_case.py 文件,文件主要用来实现执行 test_case 目录下的测试脚本。文件内容如下:

#coding=utf-8
__author__ = 'Administrator'
# import test case
import unittest
from test_case import login_auto,Release_Creative
suiter = unittest.TestSuite()
suiter.addTest (unittest.makeSuite(login_auto.login_test_case)) 
suiter.addTest (unittest.makeSuite(Release_Creative.release_creat))
unittest.TextTestRunner().run(suiter)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/189111.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

蓝桥杯第2119题 特殊时间 C++ 思维暴力

题目 思路和解题方法 1110 代表 1110年11月10号11点10分1110 4*4*4 有0111 1011 1101 1110 可以符合年 月日 时分秒的都有4种例如 1113有1113 1131 1311 3111 年份符合月日只有11 13 时分秒 只有11 13 11 31 13 11 无31 11 c 代码 #include <bits/stdc.h> using…

【开源】基于微信小程序的智慧家政系统

项目编号&#xff1a; S 063 &#xff0c;文末获取源码。 \color{red}{项目编号&#xff1a;S063&#xff0c;文末获取源码。} 项目编号&#xff1a;S063&#xff0c;文末获取源码。 目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块三、系统展示四、核心代码4.1 查询家政服…

如何理解2023vivo开发者大会,使用Rust语言编写蓝河操作系统(BlueOS)?

在2023年vivo开发者大会上&#xff0c;vivo宣布使用Rust语言编写其蓝河操作系统&#xff08;BlueOS&#xff09;。 什么是Rust语言&#xff1f; Rust 是一种开放源代码系统编程语言&#xff0c;可用于开发高效、安全的软件。 使用 Rust 可管理内存并控制其低级详细信息。 但你…

05 _ 系统设计目标(三):如何让系统易于扩展?

从架构设计上来说&#xff0c;高可扩展性是一个设计的指标&#xff0c;它表示可以通过增加机器的方式来线性提高系统的处理能力&#xff0c;从而承担更高的流量和并发。 你可能会问&#xff1a;“在架构设计之初&#xff0c;为什么不预先考虑好使用多少台机器&#xff0c;支持…

11.几何(曲线与曲面)

曲线 1.Bzier Curves 贝塞尔曲线. angents&#xff08;切线&#xff09;来定义贝塞尔曲线&#xff0c;规定了起点和终点必须是p0和p3&#xff0c;起始方向必须沿着p0p1方向&#xff0c;终点方向必须沿着p2p3方向 2. de Casteljau Algorithm&#xff08;算法&#xff09; 如何…

从0开始学习JavaScript--JavaScript事件:响应与交互

JavaScript的事件处理是Web开发中至关重要的一部分&#xff0c;通过事件&#xff0c;能够实现用户与页面的互动&#xff0c;使得网页更加生动和交互性。本文将深入探讨JavaScript事件的各个方面&#xff0c;包括事件的基本概念、事件类型、事件对象、事件冒泡与捕获、事件委托、…

【技术分享】RK3399 Ubuntu通过Python实现录音和播放功能

​本文基于IDO-SBC3968 Ubuntu 系统通过Python脚本实现录音和播放功能。 IDO-SBC3968采用RK3399国产六核64位CPU高性能处理器&#xff0c;支持4K HDMI2.0显示&#xff0c;接口丰富&#xff0c;拥有千兆以太网&#xff0c;全协议TypeC接口&#xff0c;USB3.0 &#xff0c;eDP 和…

使用ETLCloud实现CDC实时数据集成:从MySQL到ClickHouse的实时数据同步

背景 在上一篇文章中体验了 ETLCloud 的离线数据迁移功能&#xff0c;就像大数据领域里有离线计算和实时计算&#xff0c; ETLCloud 还提供了基于 CDC &#xff08;Change Data Capture&#xff09;的实时数据集成功能&#xff1a;实时数据集成是指通过变化数据捕获技术&#…

数组的申明

数组是一组相同类型的数据 数组中的数据需要通过数字索引来访问。 数组的声明需要使用new关键字 在声明数组时&#xff0c;可以使用{}来初始化数组中的数组 如果在数组声明之初没有使用大括号来初始化数组的元素&#xff0c;则需要指定数组的大小 在声明初始化元素的数组时…

调试器gdb

目录 一、调试 1、前言 2、 debug和release 二、基本操作 1、退出 quit 2、开始调试 r 3、打断点 b 4、查看断点 info b 5、查看代码 l 6、删除断点 d 7、逐过程 n 8、打印变量内容 p 9、逐语句&#xff08;进入函数&#xff09; s 10、查看函数调用堆栈 bt 11、…

Nginx反向代理实现负载均衡webshell

目录 本实验所用的环境&#xff1a; 问题一&#xff1a;由于nginx采用的反向代理是轮询的方式&#xff0c;所以上传文件必须在两台后端服务器的相同位置上传相同的文件 问题二&#xff1a;我们在执行命令时&#xff0c;无法知道下次的请求交给哪台机器去执行我们在执行hostn…

堆和栈的区别 重点来说一下堆和栈;堆与栈之间的联系

文章目录 堆和栈的区别重点来说一下堆和栈&#xff1a;那么堆和栈是怎么联系起来的呢? 堆与栈的区别 很明显&#xff1a; 今天来聊一聊java中的堆和栈&#xff0c;工作当中这两个也是经常遇到的&#xff0c;知识我们没有去注意理论上的这些内容&#xff0c;今天就来分享一下。…

Ps:拾色器 - 选取专色

在 Adobe 拾色器中&#xff0c;可点击“颜色库” Color Libraries按钮来选取专色。 首先在色库 Book列表中选择对应的色库&#xff0c;然后在中间的色相条中选择需要的样本组&#xff0c;再从左侧颜色列表中选取颜色。 可以直接键入颜色名称来选择。比如&#xff0c;键入 13&am…

【ArcGIS Pro微课1000例】0038:基于ArcGIS Pro的人口密度分析与制图

文章目录 一、人口密度二、人口密度分析1. 点密度分析2. 核密度分析三、结果比对一、人口密度 人口密度是指单位土地面积上居住的人口数,通常以每平方千米或每公顷内的常住人口为单位计算。人口密度同资源、经济密切结合,因此,科学准确地分析人口密度的分布情况,对合理制定…

【数据结构】树与二叉树(廿三):树和森林的遍历——层次遍历(LevelOrder)

文章目录 5.3.1 树的存储结构5. 左儿子右兄弟链接结构 5.3.2 获取结点的算法5.3.3 树和森林的遍历1. 先根遍历&#xff08;递归、非递归&#xff09;2. 后根遍历&#xff08;递归、非递归&#xff09;3. 森林的遍历4. 层次遍历a. 算法LevelOrderb. 算法解读c. 时间复杂度d.代码…

MATLAB在信号系统中的应用

1.产生一个幅度为1, 基频为2Hz&#xff0c;占空比为50%的周期方波.要求画出图形。 在MATLAB中&#xff0c;函数square(w0*t, DUTY)产生基本频率为w0 (周期T2*pi/w0)、占空比DUTY (τ/T)*100的周期矩形波&#xff08;方波&#xff09;&#xff0c;默认情况下占空比DUTY50。占空…

Nivision 图像处理方法-Brightness(BCGTransform)实现验证测试

测试发现NIvision中实际使用的公式是: int brightness199; float contrast61.38; float gamma0.52; uchar lut[256]; float k tan(contrast*CV_PI / 180); for (int i 0; i < 256; i) { lut[i] saturate_cast<uchar>(k*(pow(i, gamma)/ pow(255, gamma) * 2…

操作系统——操作系统概论s

一、操作系统基本概念 1 操作系统定义 操作系统是裸机上的第一层软件&#xff0c;它是对硬件系统功能的首次扩充&#xff0c; 用以填补人与机器之间的鸿沟。 OS定义&#xff1a;操作系统是控制和管理计算机系统内各种硬件和软件资源&#xff0c;有效地组织多道程序运行的系统软…

小程序中的大道理之四--单元测试

在讨论领域模型之前, 先继续说下关于测试方面的内容, 前面为了集中讨论相应主题而对此作了推迟, 下面先补上关于测试方面的. 测试覆盖(Coverage) 先回到之前的一些步骤上, 假设我们现在写好了 getPattern 方法, 而 getLineContent 还处于 TODO 状态, 如下: public String ge…

Python 前后端分离项目Vue部署应用

一、视图创建 from django.http import JsonResponse from django.shortcuts import render# Create your views here. from django.views import Viewclass IndexView(View):def get(self,request):# 前后端分离 &#xff08;前端JS代码渲染数据&#xff09;return JsonRespo…