unittest单元测试框架

Python中的单元测试框架:doctest、unittest、pytest、nose等。

单元测试:通过一段代码去验证另一段代码。

unittest是一个python版本的junit,junit是java中的单元测试框架。

1.认识unittest

1.1四个重要的概念

Test Case

Test Case是最小的测试单元,即测试用例,用于检查特定输入集合的特定返回值。unittest提供了Test Case基类,我们创建的测试类需要继承该基类,它可以用来创建新的测试用例。包括测试前准备环境的搭建(setUp),执行测试代码(run),以及测试后环境的还原(tearDown)。单元测试(unit test)的本质也就在这里,一个测试用例是一个完整的测试单元,通过运行这个测试单元,可以对某一个问题进行验证。

Test Suite

经常被翻译成"测试套件",也有人称为"测试套",是测试用例或测试套件的集合,一般用来把需要一起执行的用例组合到一起。TestLoader是用来加载TestCase到TestSuite中的,其中有几个loadTestsFrom__()方法,就是从各个地方寻找TestCase,创建它们的实例,然后add到TestSuite中,再返回一个TestSuite实例。

Test Runner

一个组件,用于执行测试用例并向用户提供结果。unittest提供了TextTestRunner类运行测试用例,为了生成HTML格式的测试报告,后面会选择HTMLTestRunner运行类。run(test)会执行TestSuite/TestCase中的run(result)方法,测试的结果会保存到TextTestResult实例中,包括运行了多少测试用例,成功了多少,失败了多少等信息。

Test Fixture

Test Fixture代表一个或多个测试所需的环境准备,以及关联的清理动作。例如:创建临时或代理把数据库、目录,或启动服务器进程。unittest中提供了setUp()/tearDown()、setUpClass()/tearDownClass()等方法来完成这些操作。

总之,test fixture的功能可以理解成是初始化和清理测试数据及环境,test case是测试用例,test suite是用例集合,test runner的作用是运行用例并返回结果。这样整个流程就清楚了,首先是要写好TestCase,然后由TestLoader加载TestCase到TestSuite,然后由TextTestRunner来运行TestSuite,运行的结果保存在TextTestResult中,整个过程集成在unittest.main模块中。

1.2断言方法

方法检查点
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 2.7
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) 也支持unhashable对象
assertDictContainsSubset(a, b)a里面所有的键值对都在b中存在

举例

①创建一个被测试文件 calculator.py

#计算器类
class Calculator:
    """用于完成两个数的加减乘除"""
    def __init__(self,a,b):
        self.a = int(a)
        self.b = int(b)
    #加
    def add(self):
        return self.a +  self.b
    def sub(self):
        return self.a -  self.b
    def mul(self):
        return self.a *  self.b
    def div(self):
        return self.a /  self.b

②创建测试文件test_calculator.py

import unittest
from calculator import Calculator

class TestCalculator(unittest.TestCase):
    #测试用例前置动作
    def setUp(self):
        print("test start:")

    # 测试用例后置动作
    def tearDown(self):
        print("test end:")

    def test_add(self):
        c = Calculator(3,5)
        result = c.add()
        self.assertEqual(result,8)
    def test_sub(self):
        c = Calculator(7,2)
        result = c.sub()
        self.assertEqual(result,5)
    def test_mul(self):
        c = Calculator(3,3)
        result = c.mul()
        self.assertEqual(result,10)
    def test_div(self):
        c = Calculator(6,2)
        result = c.div()
        self.assertEqual(result,3)
if __name__ == '__main__':
    #创建测试套件
    suit = unittest.TestSuite()
    suit.addTest(TestCalculator("test_add"))
    suit.addTest(TestCalculator("test_sub"))
    suit.addTest(TestCalculator("test_mul"))
    suit.addTest(TestCalculator("test_div"))
    #创建测试运行器
    runner = unittest.TextTestRunner()
    runner.run(suit)

setUp()/tearDown()方法,用于定义测试用例的前置和后置动作,因为在当前用例用不上,所以只做了一些简单的打印。

测试用例的执行,方法①:调用Testsuite类下面的addTest()来添加用例,一条一条按顺序执行。unittest.TestSuite().addTest()的参数是这样的:unittest.TestSuite().addTest(TestFun("test_name"));其中TestFun是继承于TestCase的类,test_name是里面的测试函数。unittest、discover()默认根据ASCII码加载测试用路,因此如果想让某个测试文件先执行,可以在命名上加以控制。(test_aaa.py会先于test_bbb.py执行) 而用unittest.TestSuite().addTest()方法执行测试用例的顺序加载测试用例的顺序相同,即书写顺序。

然后,再调用TextTestRunner类下面的run()运行测试组件。

方法②如果是main()方法,这样用,unitest.main()函数用来测试 类中以 test 开头的测试用例

import unittest
from  leap_year import LeapYear
class TestLeapYear(unittest.TestCase):
    def tset_2000(self):
        ly = LeapYear(2000)
        self.assertEqual(ly.answer(),"2000是润年")

    def tset_2004(self):
        ly = LeapYear(2004)
        self.assertEqual(ly.answer(),"2004是润年")

    def tset_2017(self):
        ly = LeapYear(2017)
        self.assertEqual(ly.answer(),"2017不是润年")

    def tset_2100(self):
        ly = LeapYear(2100)
        self.assertEqual(ly.answer(),"2100不是润年")

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

如何执行多个测试文件:unittest中的TestLoader类提供的discover()方法可以从多个文件中查找测试用例。unittest提供了可以共享的defaultTestLoader类,可以使用其子例或方法创建实例。

discover(start_dir,pattern='test*.py',top_level_dir= None)

找到指定目录下所有测试模块,并可递归查到子目录下的测试模块,只有匹配到文件名时才加载

  • start_dir:要测试的模块名或测试用例目录
  • pattern='test*.py':表示用例文件名的匹配原则。此处匹配以“test”开头的.py 类型的文件,* 表示任意多个字符
  • top_level_dir= None 测试模块的顶层目录,如果没有顶层目录,默认为None

discover()方法会自动根据测试用例目录找到测试用例文件(test*.py),并将找到的测试用例添加到测试套件中,因此,可以直接通过run()方法执行测试套件suits。

1.3跳过测试和预期失败

在运行测试时,有时需要直接跳过某些测试用例,或者当测试用例符合某个条件时跳过测试,又或者直接将测试用例设置为失败。unittest提供了实现这些需求的装饰器。

@unittest.skip(reason):无条件地跳过装饰的测试,需要说明跳过测试的原因

@unittest.skipIf(condition,reason):如果条件为真,则跳过装饰的测试

@unittest.skipUnless(condition,reason):当条件为真时,执行装饰的测试

@unittest.expectedFailure():不管执行结果是否正确,都将测试标记为失败

import unittest
class MyTest(unittest.TestCase):
    @unittest.skip("直接跳过测试")
    def test_skip(self):
        print("test aaa")

    @unittest.skipIf(3>2,"条件为真时跳过测试")
    def test_skip_if(self):
        print("test bbb")

    @unittest.skipUnless(3>2,"当条件为真时执行测试")
    def test_skip_unless(self):
        print("test ccc")

    @unittest.expectedFailure
    def test_expected_failure(self):
        self.assertEqual(2,2)

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

1.4Fixture

setUpModule()/tearDownModule():在整个模块的开始与结束时被执行

setUpClass()/tearDownClass():在测试类的开始与结束时被执行,这两个为类方法,需要通过@classmethod进行装饰

setUp()/tearDown():在测试用例的开始与结束时被执行

import unittest
def setUpModule():
    print("test module start >>>>>>")
def tearDownModule():
    print("test module end >>>>>>")
class MyTest(unittest.TestCase):

    @classmethod
    def setUpClass(cls):
        print("test class start")
    @classmethod
    def tearDownClass(cls):
        print("test class end")

    def setUp(self):
        print("test case start")
    def tearDown(self):
        print("test case end")

    def test_case1(self):
        print("test case1")

    def test_case2(self):
        print("test case2")

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

结果:

test module start >>>>>>
test class starttest case start
test case1
test case end
test case start
test case2
test case end
test class end
test module end >>>>>> 

 2.HTML测试报告

HTMLTestRunner是unittest的一个扩展,它可以生成易于使用的HTML测试报告。

HTMLTestRunner下载地址: http://tungwaiyip.info/software/HTMLTestRunner.html

因为这个模块原本给python2.0用的,我用的python是3.x,所以下载后需要做些修改:

 

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值