Python 几种常见的测试框架

2021-01-05 10:22:26 浏览数 (62)

测试的常用规则

  1. 一个测试单元必须关注一个很小的功能函数,证明它是正确的;
  2. 每个测试单元必须是完全独立的,必须能单独运行。这样意味着每一个测试方法必须重新加载数据,执行完毕后做一些清理工作。通常通过setUp()和setDown()方法处理;
  3. 编写执行快速的测试代码。在某些情况下,测试需要加载复杂的数据结构,而且每次执行的时候都要重新加载,这个时候测试执行会很慢。因此,在这种情况下,可以将这种测试放置一个后台的任务中。
  4. 采用测试工具并且学着怎么使用它。
  5. 在编写代码前执行完整的测试,而且在编写代码后再重新执行一次。这样能保证你后来编写的代码不会破坏任何事情;
  6. 在提交代码前执行完整的测试;
  7. 如果在开发期间被打断了工作,写一个打断的单元测试,关于你下一步将要开发的。当你回来工作时,你能知道上一步开发到的指针;
  8. 单元测试函数使用长的而且具有描述性的名字。在正式执行代码中,可能使用square()或sqr()取名,但是在测试函数中,你必须取像test_square_of_number_2()、test_square_negativer_number()这些名字,这些名字描述更加清楚;
  9. 测试代码必须具有可读性;
  10. 单元测试对新进的开发人员来说是工作指南。

单元测试的目的是对一个模块、一个函数或者一个类来进行正确性检验,如果单元测试通过,说明我们测试的对象能够正常工作。如果单元测试不通过,要么测试对象有 bug,要么测试条件输入不正确。下面小编为大家介绍 Python 的几种测试框架。

推荐好课:Python 自动化管理Python 自动化办公

1. unittest

unittest 和 JUnit类似,可以说是python的标准单元测试框架,所以有时也被人称为 PyUnit。它使用起来和xUnit 家族其他成员类似。 用的人也比较多。兼容 python2 以及python3 。

个人比较喜欢用这个,主要之前用过JUnit,用这个上手就很快。而且属于python自动集成,不用额外的安装包,感觉是该有的都有了,用着方便。

示例:

import unittest

class TestStringMethods(unittest.TestCase):

    def test_upper(self):

        self.assertEqual('foo'.upper(), 'FOO')

    def test_isupper(self):

        self.assertTrue('FOO'.isupper())

        self.assertFalse('Foo'.isupper())

    def test_split(self):

        s = 'hello world'

        self.assertEqual(s.split(), ['hello', 'world'])

        # check that s.split fails when the separator is not a string

        with self.assertRaises(TypeError):

            s.split(2)

if __name__ == '__main__':

    unittest.main()

2. unittest2

unittest2 可以说是一个针对 unittest 测试框架新特性的补丁。它很大程度上和 unittest 都类似。然后还添加了一些 unittest 没有的方法。

3. pytest

参考文档:http://pytest.org/latest/

看了一下,pytest文档还是蛮详细的。比较关注的一点是,pytest 直接可以通过 @pytest.mark.parametrize 进行参数化,而unittest 则需要借助DDT。

示例:

def inc(x):

    return x + 1

def test_answer():

    assert inc(3) == 5

执行如下:

$ pytest
======= test session starts ========
platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y
rootdir: $REGENDOC_TMPDIR, inifile:
collected 1 item
test_sample.py F
======= FAILURES ========
_______ test_answer ________
    def test_answer():
>       assert inc(3) == 5
E       assert 4 == 5
E        +  where 4 = inc(3)
test_sample.py:5: AssertionError
======= 1 failed in 0.12 seconds ========

4. nose

nose 扩展了 unittest,从而使得测试更容易。

一般可以用 unittest 方式写用例,写完之后用 nose 来执行。nose 的测试收集方式还是很方便的。

 还有一个特定就是,nose 可以采用  @with_setup() 来定义方法的 setup 和 teardown。

示例:

def setup_func():

    "set up test fixtures"

def teardown_func():

    "tear down test fixtures"

@with_setup(setup_func, teardown_func)

def test():

    "test ..."

5. doctest

doctest 模块会搜索那些看起来像交互式会话的 Python 代码片段,然后尝试执行并验证结果。

doctest 中,如果要写测试用例,只需要在写在以 ''' '''包围的文档注释即可,也就是可以被__doc__这个属性引用到的地方。这点比较特别,跟其他单元测试框架都不一样。但是我觉得这样的话就注定了doctest不适合大型测试,因为做不到代码和测试的分离。

import doctest

"""

This is the "example" module.

The example module supplies one function, factorial().  For example,

>>> factorial(5)

120

"""

def factorial(n):

    """Return the factorial of n, an exact integer >= 0.

    >>> [factorial(n) for n in range(6)]

    [1, 1, 2, 6, 24, 120]

    >>> factorial(30)

    265252859812191058636308480000000

    >>> factorial(-1)

    Traceback (most recent call last):

        ...

    ValueError: n must be >= 0

    Factorials of floats are OK, but the float must be an exact integer:

    >>> factorial(30.1)

    Traceback (most recent call last):

        ...

    ValueError: n must be exact integer

    >>> factorial(30.0)

    265252859812191058636308480000000

    It must also not be ridiculously large:

    >>> factorial(1e100)

    Traceback (most recent call last):

        ...

    OverflowError: n too large

    """

    import math

    if not n >= 0:

        raise ValueError("n must be >= 0")

    if math.floor(n) != n:

        raise ValueError("n must be exact integer")

    if n+1 == n:  # catch a value like 1e300

        raise OverflowError("n too large")

    result = 1

    factor = 2

    while factor <= n:

        result *= factor

        factor += 1

    return result

if __name__ == "__main__":

    doctest.testmod(verbose=True)

verbose 参数用于控制是否输出详细信息,默认为 False ,如果不写,那么运行时不会输出任何东西,除非测试 fail。

输出如下:

Trying:
    [factorial(n) for n in range(6)]
Expecting:
    [1, 1, 2, 6, 24, 120]
ok
Trying:
    factorial(30)
Expecting:
    265252859812191058636308480000000
ok
Trying:
    factorial(-1)
Expecting:
    Traceback (most recent call last):
        ...
    ValueError: n must be >= 0
ok
Trying:
    factorial(30.1)
Expecting:
    Traceback (most recent call last):
        ...
    ValueError: n must be exact integer
ok
Trying:
    factorial(30.0)
Expecting:
    265252859812191058636308480000000
ok
Trying:
    factorial(1e100)
Expecting:
    Traceback (most recent call last):
        ...
    OverflowError: n too large
ok
1 items had no tests:
    __main__
1 items passed all tests:
   6 tests in __main__.factorial
6 tests in 2 items.
6 passed and 0 failed.
Test passed.


1 人点赞