老李分享:走读unittest源码

 

poptest是国内唯一一家培养测试开发工程师的培训机构,以学员能胜任自动化测试,性能测试,测试工具开发等工作为目标。poptest测试开发工程师就业培训感兴趣,请大家咨询qq:908821478,最近学员的就业推荐开始,帮助学员梳理学习的知识点,其中涉及到我们在学习中的单元测试框架unittest,在下面和大家分享下里面涉及到的内容,以及源码情况。

一,用法

unittest模块的用法很简单,定义个 TestCase的子类,然后根据需要重载Setup()和TearDown()两个方法。并且在类中定义一些测试用例条目的“方法” ,以test开头命名即可

import laoli

import unittest

class ProductTestCase(unittest.TestCase):

def setUp(self):

print 'units test begin'+'#'*20

def tearDown(self):

print 'unittest end'+'#'*20

def testxx(self):

print 'this is just test'

def testIntegerProduct(self):

for x in xrange(-10,10):

for y in xrange(-10,10):

p = kk.product(x,y)

self.failUnless(p == x*y,'integer multiplication failture')

def testFractalProduct(self):

for x in xrange(-10,10):

for y in xrange(-10,10):

x = x/10.0

y = y/10.0

p = kk.product(x,y)

self.failUnless(p == x*y,'fractal multiplication failture')

if __name__ == '__main__':

unittest.main()

其中laoli为被测模块

注意到代码中的testIntegerProduct(self) 及 testFractalProduct(self) 两个以test开头命名的方法即是测试用例条目,整个类为TestCase的子类,unittest通过这两个信息(红色标注部分)来识别测试用例和用例下的条目。

通过调用unitest.main()方法来启动单元测试。

二.unittest 模块流程概述

首先明确unittest中对测试用例的封装,即TestSuit  是 TestCase类的一个“集合”:

源码中作者对TestSuit的注释:

class TestSuite(object):

"""A test suite is a composite test consisting of a number of TestCases.

For use, create an instance of TestSuite, then add test case instances.

When all tests have been added, the suite can be passed to a test

runner, such as TextTestRunner. It will run the individual test cases

in the order in which they were added, aggregating the results. When

subclassing, do not forget to call the base class constructor.

"""

往TestSuit内增加TestCase的代码片段为:

def addTest(self, test):

# sanity checks

if not hasattr(test, '__call__'):

raise TypeError("the test to add must be callable")

if isinstance(test, type) and issubclass(test, (TestCase, TestSuite)):

raise TypeError("TestCases and TestSuites must be instantiated "

"before passing them to addTest()")

self._tests.append(test)

def addTests(self, tests):

if isinstance(tests, str):

raise TypeError("tests must be an iterable of tests, not a string")

for test in tests:

self.addTest(test)

其中形参test 是TestCase的实例。

明确这一点后,unittest的大体流程其实是比较好理解的:

1.调用unittest.main()

调用unittest中的main方法其实是创建TestProgram类的实例

main = TestProgram

##############################################################################

# Executing this module from the command line

##############################################################################

if __name__ == "__main__":

main(module=None)

TestProgram类“实施”了unittest的全部流程(创建测试用例,执行测试用例,输出结果):

2.解析参数和构造TestSuit

unittest支持命令行参数,TestProgram通过调用parseArgs()方法完成参数的解析

并且根据传入参数来对TestSuit进行构建,传递的参数可以包含到具体的测试用例或测试条目 例如支持这样的命令:python Myunittest.py Mytestcase.testsomething 等

所以paresArgs()方法会根据不同的参数调用不同的加载测试用例的方法:有loadTestFromMoudle() 、loadTestFromName()、loadTestFromCase()等,这些方法都属于TestLoader类。

需要提前知道的是,这些Load测试用例的方法返回的都是TestSuit类。

def parseArgs(self, argv):

import getopt

long_opts = ['help','verbose','quiet']

try:

options, args = getopt.getopt(argv[1:], 'hHvq', long_opts)

for opt, value in options:

if opt in ('-h','-H','--help'):

self.usageExit()

if opt in ('-q','--quiet'):

self.verbosity = 0

if opt in ('-v','--verbose'):

self.verbosity = 2

if len(args) == 0 and self.defaultTest is None:

self.test = self.testLoader.loadTestsFromModule(self.module)# 通过调用loadTestFromModule加载测试用例

return

if len(args) > 0:

self.testNames = args

else:

self.testNames = (self.defaultTest,)

self.createTests()#若指定测试用例参数,则执行createTest(),即调用loadTestFromName

except getopt.error as msg:

self.usageExit(msg)

def createTests(self):

self.test = self.testLoader.loadTestsFromNames(self.testNames,

self.module)

3.加载完测试用例即获得TestSuit后,则执行runtest方法开始执行测试

def runTests(self):

if isinstance(self.testRunner, type):

try:

testRunner = self.testRunner(verbosity=self.verbosity)

except TypeError:

# didn't accept the verbosity argument

testRunner = self.testRunner()

else:

# it is assumed to be a TestRunner instance

testRunner = self.testRunner

self.result = testRunner.run(self.test)

if self.exit:

sys.exit(not self.result.wasSuccessful())

随后将分为“加载测试用例” “执行测试用例”记录

概念:

TestCase:testcase实例就是一个测试用例。

什么是测试用例呢?就是一个完整的测试流程,包括测试前准备环境的搭建(setUp),执行测试代码(run),以及测试后环境的还原(tearDown)。元测试(unit test)的本质也就在这里,一个测试用例是一个完整的测试单元,通过运行这个测试单元,可以对某一个问题进行验证。

TestSuite: 多个测试用例集合在一起,就是TestSuite,TestSuite可以嵌套TestSuite。

TestLoader:作用是加载TestCase到TestSuite中的,其中有几个loadTestsFrom__()方法,就是从各个地方寻找TestCase,创建它们的实例,然后add到TestSuite中,再返回一个TestSuite实例。

TextTestRunner:是来执行测试用例的,其中的run(test)会执行TestSuite/TestCase中的run(result)方法。

TextTestResult:测试的结果会保存到TextTestResult实例中,包括运行了多少测试用例,成功了多少,失败了多少等信息。

老李分享:走读unittest源码的更多相关文章

  1. Omega System Trading and Development Club内部分享策略Easylanguage源码 (第二期)

    更多精彩内容,欢迎关注公众号:数量技术宅,也可添加技术宅个人微信号:sljsz01,与我交流. 我们曾经在前文(链接),为大家分享我们精心整理的私货:"System Trading and ...

  2. 修改unittest源码之tearDown

    需求 最近在写selenium自动化平台,想把每条用例后面都带上截图,最开始是每条用例加上封装好的截图函数,但是发现太麻烦,就决定加在tearDown函数里面,每条用例结束后执行截图操作. 那么问题来 ...

  3. 【腾讯Bugly干货分享】深入源码探索 ReactNative 通信机制

    Bugly 技术干货系列内容主要涉及移动开发方向,是由 Bugly 邀请腾讯内部各位技术大咖,通过日常工作经验的总结以及感悟撰写而成,内容均属原创,转载请标明出处. 本文从源码角度剖析 RNA 中 J ...

  4. 最近在研究电台类app,分享2个源码大家一起讨论

    好像去年有一阵,电台类的app特别火爆,喜马拉雅和蜻蜓FM互相还撕逼.听老罗,听好好说话,都得在电台app里,所以我想研究研究这些app.我没那么多资源,只好从app的开发架构方面去研究. 我看api ...

  5. 语音分享应用ios源码

    该源码是语音分享应用源码,本demo使用了科大讯飞语音识别作为分享内容的输入方式,同时也支持手动键盘输入分享内容,限制分享内容文字不能超过180个字符,分享内容输入完成后可以直接分享,分享SDK使用的 ...

  6. 《分享》Koa2源码分析

    曾经在公司内部做的一起关于koa源码的分享,希望对你有帮助: koa2 源码分析整理 koa2(2.4.1版本)源码主要包含四个js,包括application.js, context.js, req ...

  7. Omega System Trading and Development Club内部分享策略Easylanguage源码

    更多精彩内容,欢迎关注公众号:数量技术宅.关于本期分享的任何问题,请加技术宅微信:sljsz01 关于 Omega System Trading and Development Club " ...

  8. 分享一个jdk源码链接

    请查看下面的链接:http://hg.openjdk.java.net/jdk7u/jdk7u/jdk/file/bcba89ce0a8c/src/share/classes/,进入页面后,点击列表中 ...

  9. 分享学习 PHP 源码的方法

            ​每天抽一点时间来看看 PHP 源码方面的书,说实话,无法在调试器下观察 PHP 运行状态的上下文实在是一件痛苦的事情.不过还好不是一无所获,虽然内容比较多,但是掌握方法挨着看下去还是 ...

随机推荐

  1. [转]ios 数据的传递

    情景1: A-->B  需要把数据传递到B里 代码: // 跳转 -- 执行login2contacts这个segue [self performSegueWithIdentifier:@&qu ...

  2. linux下基于rsync + find命令实现文件同步机制

    rsync和find是linux系统自带的命令,如果没有安装可以找到系统安装盘或者ISO文件,里面有rpm包,安装一下就可以了.       具体思路如下:             1)可以实现定时进 ...

  3. WebApi接口传参不再困惑:传参详解

    原文出处: 懒得安分 前言:还记得刚使用WebApi那会儿,被它的传参机制折腾了好久,查阅了半天资料.如今,使用WebApi也有段时间了,今天就记录下API接口传参的一些方式方法,算是一个笔记,也希望 ...

  4. MySQL Innodb 并发涉及参数

    1 参数作用 MySQL的各个插件式引擎中,都会对事务及线程做一定的处理和优化.在Innodb引擎中,总是尝试保持 innodb内 操作系统的线程数(暂命名为innodb_thread) 应该小于或等 ...

  5. sass、less、stylus的安装及使用

    一.什么是CSS预处器 CSS预处理器定义了一种新的语言,其基本思想是,用一种专门的编程语言,为CSS增加了一些编程的特性,将CSS作为目标生成文件,然后开发者就 只要使用这种语言进行编码工作.通俗的 ...

  6. 【杂】poj2482 Stars in Your Windows 题面的翻译

    原地址:http://poj.org/problem?id=2482 神题,被誉为最浪漫的题目,一位acmer以自己独特的方式写下的殷殷情语 你窗前的星星 纵时光飞逝如梭,也我对你的回忆也永不黯然.从 ...

  7. 深入理解Python中协程的应用机制: 使用纯Python来实现一个操作系统吧!!

    本文参考:http://www.dabeaz.com/coroutines/   作者:David Beazley 缘起: 本人最近在学习python的协程.偶然发现了David Beazley的co ...

  8. 关于js模拟c#的Delegate(委托)实现

    这是我的第一篇博文,想来讲一讲js的函数.我的标题是js模拟c#的Delegate. 一.什么是Delegate(委托) 在jquery中有delegate函数,作用是将某个dom元素的标签的事件委托 ...

  9. 求int型正整数在内存中存储时1的个数

    题目描述: 输入一个int型的正整数,计算出该int型数据在内存中存储时1的个数. 输入描述: 输入一个整数(int类型) 输出描述: 这个数转换成2进制后,输出1的个数 输入例子: 5 输出例子: ...

  10. MyBastis初次环境配置讲解

    MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis .20 ...