python 幾種常見的測試框架

微微微笑發表於2016-02-01

1. unittest

參考文件: https://docs.python.org/3/library/unittest.html

unittest筆記

The unittest unit testing framework was originally inspired by JUnit and has a similar flavor as major unit testing frameworks in other languages. It supports test automation, sharing of setup and shutdown code for tests, aggregation of tests into collections, and independence of the tests from the reporting framework.

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

參考文件: https://pypi.python.org/pypi/unittest2

unittest2 is a backport of the new features added to the unittest testing framework in Python 2.7 and onwards.

unittest2 可以說是一個針對 unittest測試框架新特性的補丁。它很大程度上和unittest都類似。然後還新增了一些unittest沒有的方法。

3. pytest

參考文件:http://pytest.org/latest/

The pytest framework makes it easy to write small tests, yet scales to support complex functional testing for applications and libraries.

看了一下,pytest文件還是蠻詳細的。比較關注的一點是,pytest 直接可以通過 @pytest.mark.parametrize 進行引數化,而unittest 則需要藉助DDT。

官網示例:

# content of test_sample.py
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

參考文件: https://nose.readthedocs.org/en/latest/

基於Python的測試驅動開發實戰 也有nose的用法: http://python.jobbole.com/81305/

nose extends unittest to make testing easier.

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

參考文件:https://docs.python.org/3/library/doctest.html

Python 各種測試框架簡介(一):doctest  http://my.oschina.net/lionets/blog/268542

The doctest module searches for pieces of text that look like interactive Python sessions, and then executes those sessions to verify that they work exactly as shown.

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.

 

相關文章