Coding With Fun
Home Docker Django Node.js Articles Python pip guide FAQ Policy

Python five common test frameworks


May 30, 2021 Article blog



I. Unittest

Unittest, like JUnit, can be said to be python's standard unit test framework, so it is sometimes referred to as PyUnit. I t works like other members of the xUnit family. T here are also more people using it. Compatible with python2 and python3.

Personally prefer to use this, mainly before using JUnit, with this quickly. And belongs to python automatic integration, do not use the additional installation package, feel that there should be, easy to use.

Example of an official website:

Copy the code by pressing Ctrl-C

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()

Ii. Unittest2

Unittest2 can be said to be a patch for the new features of the unittest test framework. I t's largely similar to unittest. Then you add some methods that unittest doesn't have.

III. pytest

At a glance, the pytest documentation is quite detailed. A closer concern is that pytest can be parameterized directly through @pytest.mark.parametrize, whereas unittest requires DDT.

Example of an official website:

# content of test_sample.py
def inc(x):
  return x + 1

def test_answer():
  assert inc(3) == 5

The execution is as follows:

$ 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 ========

Four. nose

nose extends unittest to make testing easier.

Use cases can generally be written as unittest and executed with nose after writing. Nose's test collection is still convenient.

Another particular is that nose can use @with_setup() to define setup and teardown for methods.

Official example:

def setup_func():
  "set up test fixtures"

def teardown_func():
  "tear down test fixtures"

@with_setup(setup_func, teardown_func)
def test():
  "test ..."

V. Doctest

The doctest module searches for Python snippets that look like interactive sessions, and then tries to execute and validate the results.

In doctest, if you want to write a test case, you only need to write in a document comment surrounded by ', which is where you can be referenced by the doc property. T his is special, unlike other unit test frameworks. But I think that's what makes doctest unsuitable for large-scale testing, because it doesn't separate code from testing.

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)

The verbose parameter is used to control whether to output details, defaulting to False, and if not written, the runtime does not output anything unless fail is tested.

The output is as follows:

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.

Recommended good lessons: python3 getting started, python3 advanced