赞
踩
Hello!大家好,我是BugBear,一个专注于分享软件测试干货的测试开发。
对于软件测试,我们先按照开发阶段来进行划分,将软件测试分为单元测试、集成测试、系统测试、验收测试,下面我们来聊聊单元测试。
在正式阐述什么是单元测试之前,我先给大家分享一个工厂组装手机的例子。
手机组装流水线按照图纸将各个电子元件组装焊接为各个模块组件(如喇叭,听筒,麦克,FPC,按键板,摄像头,LCD等),再将各个模块组件组装成一部完整的手机。
如果一起顺利,在给手机安装系统后就可以正常使用了。但是很不幸,大多数情况下的手机是无法使用的,那么就需要将已经组装好的手机重新拆机,逐个模块排查问题,在每个模块排查中需要对每个电子元件进行检测,通过花费大量的时间和精力才能定位到问题原因。
那么在后续的生产中,如何才能避免这种问题的发生呢?
你可能立即就会想到,为什么不在组装焊接前,就先测试每个要用到的电子元器件呢?这样你就可以先排除有问题的元器件,最大程度地防止组装完成后逐级排查问题的事情发生。
实践也证明,这的确是一个行之有效的好办法。
如果把手机的生产、测试和软件的开发、测试进行类比,你可以发现:
通过这个类比,相信你已经体会到了单元测试对于软件整体质量的重要性,那么单元测试到底是什么呢?
单元测试是指,对软件中的最小可测试单元在与程序其他部分相隔离的情况下进行检查和验证的工作,这里的最小可测试单元通常是指函数或者类。
好的单元测试应当包含四种特性:正确,清晰,完整,健壮
- 现在我也找了很多测试的朋友,做了一个分享技术的交流群,共享了很多我们收集的技术文档和视频教程。
- 如果你不想再体验自学时找不到资源,没人解答问题,坚持几天便放弃的感受
- 可以加入我们一起交流。而且还有很多在自动化,性能,安全,测试开发等等方面有一定建树的技术大牛
- 分享他们的经验,还会分享很多直播讲座和技术沙龙
- 可以免费学习!划重点!开源的!!!
- qq群号:110685036【暗号:csdn999】
可能大多数的测试人员不会接触到单元测试的编写,因为按照我个人的看法,开发人员根据自己写的代码编写单测用例是最合适不过的,也是最高效的。
虽然我们不需要实际去编写单测用例,但是我们还是需要了解怎么写单元测试。
单元测试的代码结构一般包含三部分:分别是准备、调用与断言
每个单元测试都应该能清晰地分出这三部分,当然有时调⽤断⾔两部分合在⼀起也是⽐较常见的。
下面我们来聊聊单元测试编写用例的相关知识,首先我们需要了解单元测试的三个重要部分,即驱动程序、桩程序、Mock
驱动程序:驱动程序(Driver)也称作驱动模块,用以模拟被测模块的上级模块,能够调用被测模块。在测试过程中,驱动模块接收测试数据,调用被测模块并把相关的数据传送给被测模块。
简单说就是你负责测试的模块没有main()方法入口,所以需要写一个带main的方法来调用你的模块或方法。这个就是驱动测试
桩程序:桩程序(Stub),也称桩模块,用以模拟被测模块工作过程中所调用的下层模块,即被测模块本身调用的其他关联函数。桩模块由被测模块调用,它们一般只进行很少的数据处理。
桩是指用来代替关联代码或者未实现的代码,为了让测试对象可以正常的执行,其实一般会硬编码一些输入和输出,保证被测模块能够正常运行
Mock:Mock除了保证Stub的功能之外,还可深入的模拟对象之间的交互方式,如:调用了几次、在某种情况下是否会抛出异常以及提供数据断言
接下来我们通过一个实例来学习单元测试用例的编写
- # 待测试的方法
- def calculator(type):
- # 调用桩代码获取数据
- num1 = __stub1()
- num2 = __stub2()
- # 调用mock
- mock_data = __mock_check()
-
- # +
- if type.lower() == 'add':
- type = 'add'
- ret = num1+num2
- assert ret == mock_data[type]
- print('{} + {} = {}'.format(num1,num2,ret))
- return ret
- # -
- if type.lower() == 'minus':
- type = 'minus'
- ret = num1-num2
- assert ret == mock_data[type]
- print('{} - {} = {}'.format(num1,num2,ret))
- return ret
- # *
- if type.lower() == 'multiply':
- type = 'multiply'
- ret = num1*num2
- assert ret == mock_data[type]
- print('{} * {} = {}'.format(num1,num2,ret))
- return ret
- # /
- if type.lower() == 'divide':
- type = 'divide'
- if num2 == 0:
- print('除法分母不能为0')
- return '除法分母不能为0'
- else:
- ret = num1/num2
- assert ret == mock_data[type]
- print('{} / {} = {}'.format(num1,num2,ret))
- return ret
-
- # 桩代码1
- def __stub1():
- output = 20
- print('my stub的值是{}'.format(output))
- return output
-
- # 桩代码2
- def __stub2():
- output = 5
- print('my stub的值是{}'.format(output))
- return output
-
- # Mock代码 => 提供断言数据
- def __mock_check():
- mock_result = {}
- mock_result['add'] = 25
- mock_result['minus'] = 15
- mock_result['multiply'] = 100
- mock_result['divide'] = 4
- return mock_result
-
- # 驱动程序
- if __name__=="__main__":
- print(calculator('add'))
- print(calculator('minus'))
- print(calculator('multiply'))
- print(calculator('divide'))
上面提供的是一个简单的单元测试,包含了驱动程序、被测对象、桩程序以及Mock代码
被测函数成功返回如下:
- my stub的值是20
- my stub的值是5
- 20 + 5 = 25
- 25
被测函数失败返回如下:
- my stub的值是20
- Traceback (most recent call last):
- my stub的值是5
- File "/Users/Desktop/demo/unittest_demo/ut_demo.py", line 73, in <module>
- print(calculator('add'))
- File "/Users/Desktop/demo/unittest_demo/ut_demo.py", line 21, in calculator
- assert ret == mock_data[type]
- AssertionError
最后感谢每一个认真阅读我文章的人,看着粉丝一路的上涨和关注,礼尚往来总是要有的,虽然不是什么很值钱的东西,如果你用得到的话可以直接拿走!
我们学习必然是为了找到高薪的工作,下面这些面试题是来自阿里、腾讯、字节等一线互联网大厂最新的面试资料,并且有字节大佬给出了权威的解答,刷完这一套面试资料相信大家都能找到满意的工作。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。