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

news2024/11/30 0:44:28

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)

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

用 Addon 增强 Node.js 和 Electron 应用的原生能力

前言 Node.js Addon 是 Node.js 中为 JavaScript 环境提供 C/C 交互能力的机制。其形态十分类似 Java 的 JNI&#xff0c;都是通过提供一套 C/C SDK&#xff0c;用于在 C/C 中创建函数方法、进行数据转换&#xff0c;以便 JavaScript / Java 等语言进行调用。这样编写的代码通常…

突破技术障碍:软件工程师如何应对项目中的难题?

在软件开发项目中&#xff0c;工程师常常会遇到各种技术难题。这些难题可能涉及到复杂的算法、不兼容的系统、难以预见的软件行为&#xff0c;或者其他许多方面。 以下是一些策略和方法&#xff0c;可以帮助软件工程师有效地应对这些挑战&#xff1a; 1、理解问题&#xff1a;…

MySQL数据库——存储函数(介绍、案例)

目录 介绍 案例 介绍 存储函数是有返回值的存储过程&#xff0c;存储函数的参数只能是IN类型的。具体语法如下&#xff1a; CREATE FUNCTION 存储函数名称 ([ 参数列表 ]) RETURNS type [characteristic ...] BEGIN-- SQL语句RETURN ...;END ; characteristic说明&#xf…

Matplotlib子图的创建_Python数据分析与可视化

Matplotlib子图的创建 plt.axes创建子图fig.add_axes()创建子图 plt.axes创建子图 前面已经介绍过plt.axes函数&#xff0c;这个函数默认配置是创建一个标准的坐标轴&#xff0c;填满整张图。 它还有一个可选的参数&#xff0c;由图形坐标系统的四个值构成。这四个值表示为坐…

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

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

C语言之指针知识点总结

C语言之指针知识点总结 文章目录 C语言之指针知识点总结1. 初识指针1.1 取地址操作符 &1.2 指针变量1.3 解引用操作符 *1.4 指针变量1.4.1 大小1.4.2 指针类型的意义 1.5 void*指针1.6 const关键字1.61 const修饰变量1.6.2 const修饰指针变量 1.7 指针的运算1.7.1 指针-整数…

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

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

MIPI 打怪升级之DSI篇

MIPI 打怪升级之DSI篇 目录 1 Overview2 DSI Mode 2.1 Video 模式2.2 Command 模式3 DSI Physical Layer 3.1 数据流控3.2 双向性3.3 Video Mode Interfaces3.4 Command Mode Interfaces3.5 Clock4 多通道管理 4.1 通道数匹配4.2 线上数据分布5 DSI 协议 5.1 包格式 5.1.1 短包…

Scrapy爬虫异步框架(一篇文章齐全)

1、Scrapy框架初识 2、Scrapy框架持久化存储&#xff08;点击前往查阅&#xff09; 3、Scrapy框架内置管道&#xff08;点击前往查阅&#xff09; 4、Scrapy框架中间件&#xff08;点击前往查阅&#xff09; Scrapy 是一个开源的、基于Python的爬虫框架&#xff0c;它提供了…

CleanMyMac X4.14.5Crack最新Mac电脑清理优化最佳应用

CleanMyMac X 4.14.5是用于清理和优化Mac的最佳应用程序和强大工具。它看起来很棒而且很容易理解。该软件可以清理、保护、优化、稳定和维护您的 Mac 系统。您可以立即删除不必要的、不寻常的、无用的垃圾文件、损坏的文件垃圾&#xff0c;并释放大量内存空间。此外&#xff0c…

【Unity实战】切换场景加载进度和如何在后台异步加载具有庞大世界的游戏场景,实现无缝衔接(附项目源码)

文章目录 最终效果前言一、绘制不同的场景二、切换场景加载进度1. 简单实现2. 优化 三、角色移动和跳跃控制四、添加虚拟摄像机五、触发器动态加载场景六、最终效果参考源码完结 最终效果 前言 观看本文后&#xff0c;我的希望你对unity场景管理有更好的理解&#xff0c;并且能…

Error PostCSS plugin autoprefixer requires PostCSS 8

文章目录 一、情况一二、情况二三、总结 在启动 vue项目时&#xff0c;突然控制台报错&#xff1a; Error: PostCSS plugin autoprefixer requires PostCSS 8。然后依次出现下面几种情况&#xff0c;依次解决完&#xff0c;项目就可以正常启动了 一、情况一 error in ./src/…

04 _ 系统设计目标(二):系统怎样做到高可用?

这里将探讨高并发系统设计的第二个目标——高可用性。 高可用性&#xff08;High Availability&#xff0c;HA&#xff09;是你在系统设计时经常会听到的一个名词&#xff0c;它指的是系统具备较高的无故障运行的能力。 我们在很多开源组件的文档中看到的HA方案就是提升组件可…

蓝桥杯第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…

使用Python的turtle库绘制随机生成的雪花

1.1引言 在这篇文章中&#xff0c;我们将使用Python的turtle库来绘制一个具有分支结构的雪花。该程序使用循环和随机颜色选择来绘制20个不同大小和颜色的雪花。turtle库是一个流行的绘图库&#xff0c;常用于创建图形用户界面和简单的动画。这个代码实现了一个有趣的应用&…

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

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

Windows服务设置多个服务依赖项避免服务启动失败找不到数据库

添加多个服务依赖项建议通过命令行的方式添加&#xff1a; winr键打开命令行 cmd 命令行添加命令如下&#xff1a; sc config "thinvent-auth" depend "MySQL57"/"RabbitMQ"/"Redis" sc config "服务A" depend "服务…

【C++干货铺】优先队列 | 仿函数

个人主页点击直达&#xff1a;小白不是程序媛 C系列专栏&#xff1a;C干货铺 代码仓库&#xff1a;Gitee 目录 优先队列&#xff08;priority_queue &#xff09;的介绍和使用 priority_queue的介绍 priority_queue的使用 大堆 小堆 priority_queue的模拟实现 仿…

算法-技巧-中等-颜色分类

记录一下算法题的学习12 颜色分类 题目&#xff1a;给定一个包含红色、白色和蓝色、共 n 个元素的数组 nums &#xff0c;原地对它们进行排序&#xff0c;使得相同颜色的元素相邻&#xff0c;并按照红色、白色、蓝色顺序排列。 我们使用整数 0、 1 和 2 分别表示红色、白色和蓝…

Linux进程管理,用户管理,文件压缩命令

gcc与g区别(补充了解): 比如有两个文件:main.c,mainc.cpp(分别用C语言和C语言写的)如果要用gcc编译呢? gcc -o mainc main.c gcc -o mainc mainc.cpp -lstdc 指明用c的标准库; 区别一: gcc默认只链接C库,并不会链接C的库;g会默认链接c标准库. 区别二: gcc编译.c文件,则按照C语…