python自动化测试三部曲之untitest框架
终于等到十一,有时间写博客了,准备利用十一这几天的假期把这个系列的博客写完
该系列文章本人准备写三篇博客
第一篇:介绍python自动化测试框架unittest
第二篇:介绍django框架+request库实现接口测试
第三篇:介绍利用Jenkins实现持续集成
今天进入第一篇,unittest框架介绍
一、unittest简述
unittest是python语言的单元测试框架,在python的官方文档中,对unittest单元测试框架进行了详细的介绍,感兴趣的读者可以到https://www.python.org/doc
网站去了解;本篇博客重点介绍unittest单元测试框架在自动化测试中的应用
unittest单元测试框架提供了创建测试用例,测试套件,和批量执行测试用例的方法,在python安装成功后,unittest单元测试框架可以直接导入使用,他属于
python的标准库;作为单元测试的框架,unittest单元测试框架也是对程序的最小模块进行的一种敏捷化的测试。在自动化测试i中,我们虽然不需要做白盒测试,
但是必须知道所使用语言的单元测试框架,这是因为后面我们测试,就会遇到用例组织的问题,虽然函数式编程和面向对象编程提供了对代码的重构,但是对于所
编写的每个测试用例,不可能编写成一个函数来调用执行;利用单元测试框架,可以创建一个类,该类继承unittest的TestCase,这样可以把每个TestCase看成是
一个最小的单元,由测试套件组织起来,运行时直接执行即可,同时可引入测试报告。unittest各个组件的关系如果
TestCase------------------------------->TestFixture(测试固件)
|
|
|
|
|
|
|
|
|
TestSuite(测试套件)----------------------->TestRunner(测试执行)-------------------->TestReport(测试报告)
# TestCase
# 类,必须要继承unittest.TestCase
# 一个类class继承 unittest.TestCase,就是一个测试用例。一个TestCase的实例就是一个测试用例,就是一个完整的测试流程。
# 包括测试前环境准备setUp()|setUpClass()、执行代码run()、测试环境后的还原tearDown()|tearDownClass()。
# 继承自unittest.TestCase的类中,测试方法的名称要以test开头。且只会执行以test开头定义的方法(测试用例)。
二、测试固件(TestFixture)
在unittest单元测试框架中,测试固件用于处理初始化的操作,例如,在对百度的搜索进行测试前,首先需要打开浏览器并且进入百度的首页;测试结束后,
需要关闭浏览器;测试固件提哦功能了两种执行形式,一种是每执行一个测试用例,测试固件就会被执行一次;另外一种就不管有多少个用例i,测试固件只会执
行一次
# 用于一个测试环境的准备和销毁还原。
# 当测试用例每次执行之前需要准备测试环境,每次测试完成后还原测试环境,比如执行前连接数据库、打开浏览器等,执行完成后需要还原数据库、关闭浏览器等操作。
# 这时候就可以启用testfixture。
# setUp():准备环境,执行每个测试用例的前置条件;
# tearDown():环境还原,执行每个测试用例的后置条件;
# setUpClass():必须使用@classmethod装饰器,所有case执行的前置条件,只运行一次;
# tearDownClass():必须使用@classmethod装饰器,所有case运行完后只运行一次;
1、测试固件每次均执行
unittest单元测试框架提供了名为setUp的tearDown的测试固件。下面,我们通过编写一个例子来看测试固件的执行方式,测试代码如下
1 import unittest
2
3 class Test1(unittest.TestCase):
4
5 # 测试固件之前置条件
6 def setUp(self):
7 print("这是前置条件")
8
9 # 测试固件之后置条件
10 def tearDown(self):
11 print("这是后置条件")
12
13 def test_case1(self):
14 print("test_case1")
15
16 def test_case2(self):
17 print("test_case2")
18
19
20 if __name__ == '__main__':
21 unittest.main(verbosity=2)
执行结果如下

他的执行顺序是先执行setUp方法,在执行具体的用例,最后执行tearDown方法
2、测试固件只执行一次
钩子方法setUp和tearDown虽然经常使用,但是在自动化测试中,一个系统的测试用例多达上千条,每次都执行一次的setUp和tearDown方法会耗费大量的性能,
在unittest单元测试框架中还可以使用另外一种测试固件来解决这一问题,他就是setUpClass和tearDownClass方法,该测试固件方法是类方法,需要在方法上
面加装饰器@classmethod,使用该测试固件,不管有多少个用例,测试固件只执行一次,具体代码如下
1 import unittest
2
3 class Test1(unittest.TestCase):
4 # def setUp(self):
5 # print("这是前置条件")
6 #
7 # def tearDown(self):
8 # print("这是后置条件")
9
10 @classmethod
11 def setUpClass(cls):
12 print("这是类方法前置条件")
13
14 @classmethod
15 def tearDownClass(cls):
16 print("这是类方法后置条件")
17
18 def test_case1(self):
19 print("test_case1")
20
21 def test_case2(self):
22 print("test_case2")
23
24
25 if __name__ == '__main__':
26 unittest.main(verbosity=2)
结果如下

3、两种测试固件并存
import unittest class Test1(unittest.TestCase):
def setUp(self):
print("这是前置条件") def tearDown(self):
print("这是后置条件") @classmethod
def setUpClass(cls):
print("这是类方法前置条件") @classmethod
def tearDownClass(cls):
print("这是类方法后置条件") def test_case1(self):
print("test_case1") def test_case2(self):
print("test_case2") if __name__ == '__main__':
unittest.main(verbosity=2)
执行结果如下

结果表明,先执行被@classmethod装饰器装饰的测试固件,在执行普通的测试固件
三、测试执行
在以上事例中,可以看到测试用例的执行是在主函数中,unittest调用的是main,代码如下,TestProjram还是一个类,再来看该类的构造函数,代码如下
main = TestProgram
TestProjram还是一个类,再来看该类的构造函数,代码如下
class TestProgram(object):
"""A command-line program that runs a set of tests; this is primarily
for making test modules conveniently executable.
"""
# defaults for testing
module=None
verbosity = 1
failfast = catchbreak = buffer = progName = warnings = None
_discovery_parser = None def __init__(self, module='__main__', defaultTest=None, argv=None,
testRunner=None, testLoader=loader.defaultTestLoader,
exit=True, verbosity=1, failfast=None, catchbreak=None,
buffer=None, warnings=None, *, tb_locals=False):
if isinstance(module, str):
self.module = __import__(module)
for part in module.split('.')[1:]:
self.module = getattr(self.module, part)
else:
self.module = module
if argv is None:
argv = sys.argv self.exit = exit
self.failfast = failfast
self.catchbreak = catchbreak
self.verbosity = verbosity
self.buffer = buffer
self.tb_locals = tb_locals
if warnings is None and not sys.warnoptions:
# even if DeprecationWarnings are ignored by default
# print them anyway unless other warnings settings are
# specified by the warnings arg or the -W python flag
self.warnings = 'default'
else:
# here self.warnings is set either to the value passed
# to the warnings args or to None.
# If the user didn't pass a value self.warnings will
# be None. This means that the behavior is unchanged
# and depends on the values passed to -W.
self.warnings = warnings
self.defaultTest = defaultTest
self.testRunner = testRunner
self.testLoader = testLoader
self.progName = os.path.basename(argv[0])
self.parseArgs(argv)
self.runTests()
在unittest模块中包含的main方法,可以方便的将测试模块转变为可以运行的测试脚本。main使用unittest.TestLoader类来自动查找和加载模块内的测试用例,TestProgram类中的该部分的代码如下
def createTests(self):
if self.testNames is None:
self.test = self.testLoader.loadTestsFromModule(self.module)
else:
self.test = self.testLoader.loadTestsFromNames(self.testNames,
self.module)
在执行测试用例时候,在main方法中加入了verbosity=2,代码如下
if __name__ == '__main__':
unittest.main(verbosity=2)
下面解释一下verbosity部分,在verbosity中默认是1。0代表执行的测试总数和全局结果,2代表详细的信息
四、测试套件,TestSuite
# TestSuite
# 上述简单的测试会产生两个问题,可不可以控制test测试用例的执行顺序?若不想执行某个测试用例,有没有办法可以跳过?
# 对于执行顺序,默认按照test的 A-Z、a-z的方法执行。若要按自己编写的用例的先后关系执行,需要用到testSuite。
# 把多个测试用例集合起来,一起执行,就是testSuite。testsuite还可以包含testsuite。
# 一般通过addTest()或者addTests()向suite中添加。case的执行顺序与添加到Suite中的顺序是一致的。
1、直接执行案例
我们在func.py这个文件中定义加减乘除4个测试函数
#Auther Bob
#--*--conding:utf-8 --*--
def add(a,b):
return a + b
def minus(a,b):
return a - b
def multi(a,b):
return a * b
def divide(a,b):
return a / b

然后在myunittest.py文件中定义我们的测试代码,这里用到了断言,我们后面会介绍
from test1 import func class Test2(unittest.TestCase):
def setUp(self):
print("前置条件") def tearDown(self):
print("后置条件") def test_add(self):
self.assertEqual(3,func.add(1,2)) def test_minus(self):
self.assertEqual(4,func.minus(5,1)) def test_multi(self):
self.assertEqual(4,func.multi(2,2)) def test_divide(self):
self.assertEqual(10,func.divide(100,10)) if __name__ == '__main__':
unittest.main(verbosity=2)
执行结果如下

2、添加案例到测试套件中
上述简单的测试会产生两个问题,可不可以控制test测试用例的执行顺序?若不想执行某个测试用例,有没有办法可以跳过?
对于执行顺序,默认按照test的 A-Z、a-z的方法执行。若要按自己编写的用例的先后关系执行,需要用到testSuite。
把多个测试用例集合起来,一起执行,就是testSuite。testsuite还可以包含testsuite。
一般通过addTest()或者addTests()向suite中添加。case的执行顺序与添加到Suite中的顺序是一致的。 如果用到测试套件TestSuite,则需要先写好测试代码,但是先不要执行 我们同样在myunittest.py文件中定义我们的测试代码
from test1 import func class Test3(unittest.TestCase):
def setUp(self):
print("前置条件") def tearDown(self):
print("后置条件") def test_add(self):
self.assertEqual(3,func.add(1,2)) def test_minus(self):
self.assertEqual(4,func.minus(5,1)) def test_multi(self):
self.assertEqual(4,func.multi(2,2)) def test_divide(self):
self.assertEqual(10,func.divide(100,10))
我们在test_suit.py文件中引入测试案例,然后通过TestSuite类的addTests方法把测试用例添加到测试套件中
import unittest
from test1.myunittest import Test3
# from test1.myunittest2 import Test3 as t3 if __name__ == '__main__':
# 输出信息到控制台 # 实例化一个TestSuite类
suite = unittest.TestSuite() # 把需要执行的案例放在一个list中
tests = [Test3("test_add"), Test3("test_minus"), Test3("test_multi"), Test3("test_divide")] # 把案例添加到实例化好的测试套件中
suite.addTests(tests)
# t = [t3("test_add"), t3("test_minus"), t3("test_multi"), t3("test_divide")]
# suite.addTests(tests) # 实例化一个参数执行类
runner = unittest.TextTestRunner(verbosity=2) # 测试执行类的实例执行测试套件
runner.run(suite)
以上的案例我们是添加一个文件的测试案例,我们同样可以添加多个文件中的案例到一个测试套件中,然后执行这个测试套件即可
import unittest
from test1.myunittest import Test3
from test1.myunittest2 import Test3 as t3 if __name__ == '__main__':
# 输出信息到控制台 # 实例化一个TestSuite类
suite = unittest.TestSuite() # 把需要执行的案例放在一个list中
tests = [Test3("test_add"), Test3("test_minus"), Test3("test_multi"), Test3("test_divide")] # 把案例添加到实例化好的测试套件中
suite.addTests(tests) # 添加另外一个文件中的测试案例到测试套件中
t = [t3("test_add"), t3("test_minus"), t3("test_multi"), t3("test_divide")]
suite.addTests(t) # 实例化一个参数执行类
runner = unittest.TextTestRunner(verbosity=2) # 测试执行类的实例执行测试套件
runner.run(suite)
上面的执行方式是输出结果到控制台,我们也可以输出结果到文件中
import unittest
from test1.myunittest import Test3
from test1.myunittest2 import Test3 as t3 if __name__ == '__main__': # 输出信息到txt文件中
suite = unittest.TestSuite()
tests = [Test3("test_add"), Test3("test_minus"), Test3("test_multi"), Test3("test_divide")]
suite.addTests(tests)
t = [t3("test_add"), t3("test_minus"), t3("test_multi"), t3("test_divide")]
suite.addTests(t)
with open('UnittestTextReport.txt', 'a') as f:
runner = unittest.TextTestRunner(stream=f, verbosity=2)
runner.run(suite)
3、直接添加测试类到测试套件中
案例一个一个添加还是比较麻烦,我们可以直接添加一个测试类到测试套件中
利用下面的方法加载一个测试类
unittest.TestLoader().loadTestsFromTestCase(t3)
import unittest
from unittest import TestLoader from test1 import myunittest from test1.myunittest2 import Test3 as t3 if __name__ == '__main__':
suite = unittest.TestSuite()
loader = TestLoader()
test_cases1 = unittest.TestLoader().loadTestsFromTestCase(t3)
# 参数是一个类,而这个类必须是unittest.TestCase的子类或者孙类
suite.addTests(test_cases1)
runner = unittest.TextTestRunner(verbosity=2)
runner.run(suite)
4、直接加载一个模块到测试套件中,如果这个模块中有多个类,则会把所有的类的测试案例加载到测试套件中
unittest.TestLoader().loadTestsFromModule(myunittest)
import unittest
from unittest import TestLoader from test1 import myunittest from test1.myunittest2 import Test3 as t3 if __name__ == '__main__':
suite = unittest.TestSuite()
loader = TestLoader()
test_cases1 = unittest.TestLoader().loadTestsFromModule(myunittest)
# 参数是一个模块,会把这个模块里的所有case加载进来
suite.addTests(test_cases1)
runner = unittest.TextTestRunner(verbosity=2)
runner.run(suite)
我给大家截图看下

5、通过案例名称添加案例到测试套件中
test_cases1 = unittest.TestLoader().loadTestsFromName('test1.myunittest2.Test3.test_minus')
import unittest
from unittest import TestLoader from test1 import myunittest from test1.myunittest2 import Test3 as t3 if __name__ == '__main__': suite = unittest.TestSuite()
loader = TestLoader()
test_cases1 = unittest.TestLoader().loadTestsFromName('test1.myunittest2.Test3.test_minus')
# 加载某个cese
runner = unittest.TextTestRunner(verbosity=2)
suite.addTests(test_cases1)
runner.run(suite)
我截图给大家看下目录结构

五、忽略执行案例
在实际的项目中,有些案例我们可能暂时不需要执行,如果有这样的问题,我们该怎么办,unittest框架已经为我们提供了解决方案
1、无条件跳过该案例,用该装饰器修饰要执行的案例,则该案例会被忽略不执行
@unittest.skip("do not exec")
@unittest.skip("do not exec")
# 无条件跳过执行该案例
def test_add(self):
self.assertEqual(3,func.add(1,2))
2、满足某个条件才跳过该案例
@unittest.skipIf(4 > 3,"2 > 3 do not exec")
@unittest.skipIf(4 > 3,"2 > 3 do not exec")
# 满足某个条件才跳过执行
def test_minus(self):
self.assertEqual(4,func.minus(5,1))
3、不满足某个条件才跳过案例
@unittest.skipUnless(4 < 3,"hahah")
@unittest.skipUnless(4 < 3,"hahah")
# 不满足某个条件才跳过执行
def test_multi(self):
self.assertEqual(4,func.multi(2,2))
4、我们也可以在案例里面定义忽略执行这条案例
def test_divide(self):
self.skipTest("wydd")
self.assertEqual(10,func.divide(100,10))
六、断言
断言就是判断实际测试结果与预期结果是否一致,一致则测试通过,否则失败。因此,在自动化测试中,无断言的测试用例是无效的,这是因为当一个功能自动化已经全部实现,在每次版本迭代中执行测试用例时,执行的结果必须是权威的,也就是说自动化测试用例执行结果应该无功能性或者逻辑性问题,在自动化测试中最忌讳的就是自动化测试的用例虽然是通过的,但是被测试的功能却是存在问题的,自动化测试用例经常应用在回归测试中,发现的问题不是特别多,如果测试结果存在功能上的问题,则投入了人力去做的自动化参数就没有多大的意义了,所以每一个测试用例必须要有断言;在测试的结果中只有两种可能,一种是执行通过,另外一种是执行失败,也就是功能存在问题,在TestCase类中提供了assert方法来检查和报告失败,常用的方法如下
self.assertEqual(3,func.add(1,2))
# 判断是否相等 self.assertNotEqual()
# 判断是否不等于 self.assertTrue()
# 判断布尔值是否为True self.assertFalse()
# 判断布尔值是否为False self.assertIs()
# 判断类型是否相同 self.assertIsNot()
# 判断类型是否不同 self.assertIsNone()
# 判断是否为None self.assertIsNotNone()
# 判断是否不为None self.assertIn()
# 判断在某个范围内 self.assertNotIn()
# 判断是否不在某个范围内 self.assertIsInstance()
# 判断是否为某个类的实例 self.assertNotIsInstance()
python自动化测试三部曲之untitest框架的更多相关文章
- python自动化测试三部曲之request+django实现接口测试
国庆期间准备写三篇博客,介绍和总结下接口测试,由于国庆期间带娃,没有按照计划完成,今天才完成第二篇,惭愧惭愧. 这里我第一篇博客的地址:https://www.cnblogs.com/bainianm ...
- python自动化测试(3)- 自动化框架及工具
python自动化测试(3) 自动化框架及工具 1 概述 手续的关于测试的方法论,都是建立在之前的文章里面提到的观点: 功能测试不建议做自动化 接口测试性价比最高 接口测试可以做自动化 后面所谈到 ...
- 【转】推荐4个不错的Python自动化测试框架
之前,开发团队接手一个项目并开始开发时,除了项目模块的实际开发之外,他们不得不为这个项目构建一个自动化测试框架.一个测试框架应该具有最佳的测试用例.假设(assumptions).脚本和技术来运行每一 ...
- selenium + python自动化测试unittest框架学习(二)
1.unittest单元测试框架文件结构 unittest是python单元测试框架之一,unittest测试框架的主要文件结构: File >report >all_case.py &g ...
- python自动化测试框架unittest
对于刚学习python自动化测试的小伙伴来说,unittest是一个非常适合的框架: 通过unittest,可以管理测试用例的执行,自动生成简单的自动化测试报告: 首先我们尝试编写编写一个最简单的un ...
- selenium + python自动化测试unittest框架学习(五)webdriver的二次封装
因为webdriver的api方法很长,再加上大多数的定位方式是以xpath方式定位,更加让代码看起来超级长,为了使整体的代码看起来整洁,对webdriver进行封装,学习资料来源于虫师的<se ...
- 《selenium2 python 自动化测试实战》(21)——unittest单元测试框架解析
unittest是展开自动化测试的基础——这个框架很重要! 我们先自己写一个测试类: 1.被测试类 Widthget.py: # coding: utf-8 class Widthget: de ...
- python自动化测试(4)-使用第三方python库技术实现
python自动化测试(4)-使用第三方python库技术实现 1 概述 关于测试的方法论,都是建立在之前的文章里面提到的观点: 功能测试不建议做自动化 接口测试性价比最高 接口测试可以做自动化 ...
- (学习网址)Python 自动化测试
1.Python自动化测试地址 http://www.wtoutiao.com/author/python-selenium.html 2.unittest参考网址: 1)python自动化测试报告H ...
随机推荐
- 设计模式(C#)——05适配器模式
推荐阅读: 我的CSDN 我的博客园 QQ群:704621321 自然界有一条规则--适者生存.意思是生物要使用自然界的变化:在程序界中则需要新环境调用现存对象.那么,如何在新环境中 ...
- JNI开发流程
交叉编译 在一个平台上去编译另一个平台上可以执行的本地代码 cpu平台 arm x86 mips 操作系统平台 windows linux mac os 原理 模拟不同平台的特性去编译代码 jni开发 ...
- 栅格数据的批量镶嵌(附Python脚本)
栅格数据的批量镶嵌(附Python脚本) 博客小序:在数据处理的过程中,会遇到需要大量镶嵌的情况,当数据较多时手动镶嵌较为麻烦,自己最近对分省的DEM数据进行镶嵌,由于利用python进行镶嵌较为方便 ...
- 《高效休息法》IT从业者如何高效休息
这本书主要讲什么? 大脑疲劳和身体疲劳不同,身体再怎么休息,大脑疲劳还是会在不知不觉中积累 大脑是一个重量仅仅占体重2%,却消耗着20%能量的大胃王,这些能量大部分都用在了预设模式网络(Default ...
- 使用element-ui中table expand展开行控制显示隐藏
问题讲解:在使用vue版本的ElementUI中的table功能的时候还是遇到了一些问题,可以说饿了么团队在这个UI框架的文档撰写已经非常不错了,不过还是有一些方法乍一看让人摸不着头脑,有些table ...
- 2014-2015 Petrozavodsk Winter Training Camp, Contest.58 (Makoto rng_58 Soejima contest)
2014-2015 Petrozavodsk Winter Training Camp, Contest.58 (Makoto rng_58 Soejima contest) Problem A. M ...
- CF995B Suit and Tie 贪心 第十三
Suit and Tie time limit per test 2 seconds memory limit per test 256 megabytes input standard input ...
- [HNOI2002]沙漠寻宝 题解
一道大模拟 代码 #include <cstdio> #include <iostream> #include <cstring> #include <str ...
- js中鼠标点击、移动和光标移动的事件触发
事件有三要素:事件源.事件数据.事件处理程序 事件冒泡:当元素嵌套的时候,内部元素激发某个事件后,默认情况下外部元素相应的事件也会跟着依次触发 可以加return false;是阻止默认操作 oncl ...
- TypeScript && React
环境搭建 我们当然可以先用脚手架搭建React项目,然后手动配置成支持TypeScript的环境,虽然比较麻烦,但可以让你更清楚整个过程.这里比较麻烦,就不演示了,直接用命令配置好. npx crea ...