UnitTest笔记

UnitTest——测试模块

其他相关:使用coverage工具统计python单元测试覆盖率

一、简单示例

待测类/方法 book.py

# 待测类
class Book(object):
    _page = 2000
    def __init__(self, bookname, author):
        self.name = bookname
        self.author = author

    def get_page(self):
        return self._page
    
# 待测方法
def get_name(book):
    return book.name

测试类test_book.py

# 每个测试方法均以 test 开头,否则是不被unittest识别的。
class TestBook(unittest.TestCase):

    def test_init(self):
        print('test init()')
        book = main_class.Book('bookname', 'author')
        self.assertEquals(book.name, 'bookname')
        self.assertEquals(book.author, 'author')
        self.assertEquals(book._page, 2000)
        self.assertTrue(isinstance(book, main_class.Book))

    def test_get(self):
        print('test get_name()')
        self.assertEquals(main_class.get_name(main_class.Book('bookname', 'author')), 'bookname')

运行

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

结果

test get_name()
.
test init()
.
----------------------------------------------------------------------
Ran 2 tests in 0.001s

OK

​ 给出的结果标识,成功是 .,失败是 F,出错是 E,跳过是 S

​ 测试的执行跟方法的顺序没有关系。

二、测试类

创建

  • 继承unittest.TestCase。
  • 以“test”开头的测试方法,每一类分别添加一个测试方法。
  • 按需添加内置判断条件如:assertEquals()、assertRaises(Error)。

运行

1、pyCharm直接运行

​ pycharm还是比较智能的,可以直接运行测试,不过有个地方需要特别注意,pyCharm会自动识别并测试鼠标所在当前代码块,所以有可能你ctrl+shift+f10后,可能运行结果就只是测试一个方法(笔者可是让这个弄的莫名其妙,一顿不得其解)。

2、main方法

​ 在测试文件结尾添加

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

然后命令行运行

python xxxx.py
3、命令行运行

在命令行通过参数-m unittest直接运行单元测试:

$ python -m unittest xxxx

这是推荐的做法,因为这样可以一次批量运行很多单元测试,并且,有很多工具可以自动来运行这些单元测试。

环境准备和尾处理

如果每个测试之前都需要准备环境如连接数据库、打开文件,或尾处理如关闭数据库、关闭数据流,不可能每个测试方法都写一遍。

setUp()

​ 在每个测试方法运行之前运行

tearDown()

​ 在每个测试方法运行之后运行

setUpClass()

​ 在每个单元测试开始之前运行

tearDownClass()

​ 在每个单元测试结束之后运行

示例:

class TestBook(unittest.TestCase):

    def setUp(self):
        print('setUp++++++++')

    @classmethod
    def setUpClass(cls):
        print('setUpClass--------')

    def tearDown(self):
        print('tearDown++++++++++')

    @classmethod
    def tearDownClass(cls):
        print('tearDownClass--------')

    def test_init(self):
        print('test init()')

    def test_get(self):
        print('test get_name()')

运行结果:

(UnitTest) D:\sHui\learn\UnitTest>python -m  unittest test_class
setUpClass--------
setUp++++++++
test get_name()
tearDown++++++++++
.setUp++++++++
test init()
tearDown++++++++++
.tearDownClass--------

----------------------------------------------------------------------
Ran 2 tests in 0.003s

OK

跳过某case

测试跳过某个case?unittest提供了几种方法。

1、skip装饰器
  • unittest.skip(reason) skip无条件跳过
  • unittest.skipIf(condition, reason) skipIf当condition为True时跳过
  • unittest.skipUnless(condition, reason) skipUnless当condition为False时跳过。

示例:

class TestBook(unittest.TestCase):
    
    def test_init(self):
        print('test init()')

    @unittest.skip('skip this func ')
    def test_get(self):
        print('test get_name()')

结果:

Skipped: skip this func 
test init()


Ran 2 tests in 0.002s

OK (skipped=1)

运行了两个测试,但test_get被跳过了

2、TestCase.skipTest()

测试类的skipTest()方法可以跳过当前测试方法。

class TestBook(unittest.TestCase):
    def test_init(self):
        print('test init()')
    
    # 跳过此方法
    def test_get(self):
        self.skipTest('skip this func')
        print('test get_name()')

结果同上

调整测试顺序

新建文件test_suite.py

import unittest
import test_class


if __name__ == '__main__':
    suite = unittest.TestSuite()
    tests = [test_class.TestBook('test_init'), test_class.TestBook('test_get')]
    suite.addTests(tests)
    runner = unittest.TextTestRunner(verbosity=2)
    runner.run(suite)

输出:

test init()
test get_name()
test_init (test_class.TestBook) ... ok
test_get (test_class.TestBook) ... ok

----------------------------------------------------------------
Ran 2 tests in 0.000s
OK

三、测试输出

1、输出信息

verbosity参数可以控制执行结果的输出

  • 0 是简单报告
  • 1 是一般报告
  • 2 是详细报告。

2、输出到文件

if __name__ == '__main__':
    suite = unittest.TestSuite()
    suite.addTests(unittest.TestLoader().loadTestsFromTestCase(test_class.TestBook))

    with open('Unittest.txt', 'a') as f:
        runner = unittest.TextTestRunner(stream=f, verbosity=2)
        runner.run(suite)

运行结束会在同目录下生成了Unittest.txt

3、输出为HTML

HTMLTestRunner是一个第三方的unittest HTML报告库,首先我们下载HTMLTestRunner.py,并放到当前目录下,或者你的’C:Python27Lib’下,就可以导入运行了。

示例:

from HTMLTestRunner import HTMLTestRunner

if __name__ == '__main__':
    suite = unittest.TestSuite()
    suite.addTests(unittest.TestLoader().loadTestsFromTestCase(test_class.TestBook))
    with open('HTMLReport.html', 'w') as f:
        runner = HTMLTestRunner(stream=f,
                                title='MathFunc Test Report',
                                description='generated by HTMLTestRunner.',
                                verbosity=2)
        runner.run(suite)

四、Coverage的使用

1.命令行方式

详见:http://coverage.readthedocs.io/en/latest/cmd.html

可以使用help命令查看帮助:$ coverage help

关键命令如下:

A.run

执行代码覆盖率统计,只需要通过coverage的run参数执行被统计代码即可。

$ coverage run test.py arg1 arg2

test.py是测试脚本,arg1 arg2是test.py执行需要的参数。跑完后,会自动生成一个覆盖率统计结果文件(data file):.coverage。

B.report

有了覆盖率统计结果文件,只需要再运行report参数,就可以在命令里看到统计的结果。

Stmts/Miss表示语句总数/未执行到的语句数

Cover=(Stmts-Miss)/Stmts

c. html

生成html的测试报告。

$ coverage html -d covhtml

生成的报告直接关联代码,高亮显示覆盖和未覆盖的代码,支持排序。-d指定html文件夹。

2.API方式

除了使用命令行,还可以在python代码中直接调用coverage模块执行代码覆盖率的统计。使用方法也非常简单:

import coverage

cov = coverage.coverage(source = ['totest'])
cov.start()
#coding
cov.stop()
cov.report()
cov.html_report(directory='covhtml')

source指定要执行统计的文件,source = ['totest']只统计totest.py的覆盖率

directory指定生成html的路径

五、常用函数

Method Checks that
assertEqual(a, b) a == b
assertNotEqual(a, b) a != b
assertTrue(x) bool(x) is True
assertFalse(x) bool(x) is False
assertIs(a, b) a is b
assertIsNot(a, b) a is not b
assertIsNone(x) x is None
assertIsNotNone(x) x is not None
assertIn(a, b) a in b
assertNotIn(a, b) a not in b
assertIsInstance(a, b) isinstance(a, b)
assertNotIsInstance(a, b) not isinstance(a, b)
assertRaises(exc, fun, *args, **kwds) fun(*args, **kwds) raises exc
assertRaisesRegexp(exc, r, fun, *args, **kwds) fun(*args, **kwds) raises exc and the message matches regex r
assertAlmostEqual(a, b) round(a-b, 7) == 0
assertNotAlmostEqual(a, b) round(a-b, 7) != 0
assertGreater(a, b) a > b
assertGreaterEqual(a, b) a >= b
assertLess(a, b) a < b
assertLessEqual(a, b) a <= b
assertRegexpMatches(s, r) r.search(s)
assertNotRegexpMatches(s, r) not r.search(s)
assertItemsEqual(a, b) sorted(a) == sorted(b) and works with unhashable objs
assertDictContainsSubset(a, b) all the key/value pairs in a exist in b
assertMultiLineEqual(a, b) strings
assertSequenceEqual(a, b) sequences
assertListEqual(a, b) lists
assertTupleEqual(a, b) tuples

参考文章:

官方文档

Python必会的单元测试框架 —— unittest

廖雪峰

优秀的个人博客,低调大师

微信关注我们

原文链接:https://yq.aliyun.com/articles/573108

转载内容版权归作者及来源网站所有!

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。

相关文章

发表评论

资源下载

更多资源
Oracle Database,又名Oracle RDBMS

Oracle Database,又名Oracle RDBMS

Oracle Database,又名Oracle RDBMS,或简称Oracle。是甲骨文公司的一款关系数据库管理系统。它是在数据库领域一直处于领先地位的产品。可以说Oracle数据库系统是目前世界上流行的关系数据库管理系统,系统可移植性好、使用方便、功能强,适用于各类大、中、小、微机环境。它是一种高效率、可靠性好的、适应高吞吐量的数据库方案。

Apache Tomcat7、8、9(Java Web服务器)

Apache Tomcat7、8、9(Java Web服务器)

Tomcat是Apache 软件基金会(Apache Software Foundation)的Jakarta 项目中的一个核心项目,由Apache、Sun 和其他一些公司及个人共同开发而成。因为Tomcat 技术先进、性能稳定,而且免费,因而深受Java 爱好者的喜爱并得到了部分软件开发商的认可,成为目前比较流行的Web 应用服务器。

Eclipse(集成开发环境)

Eclipse(集成开发环境)

Eclipse 是一个开放源代码的、基于Java的可扩展开发平台。就其本身而言,它只是一个框架和一组服务,用于通过插件组件构建开发环境。幸运的是,Eclipse 附带了一个标准的插件集,包括Java开发工具(Java Development Kit,JDK)。

Sublime Text 一个代码编辑器

Sublime Text 一个代码编辑器

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。