Documentation and test modules for Python

This article is dedicated to discuss Python documentation and test modules.

Table of content

Code

Documentation

pydoc module

Write documentation

Generate documentation

NAME solution

FILE /Users/su/GitHub/tmpSolution/solution.py

DESCRIPTION Python script to solve the teaser puzzle from Zalando document for this script can be generate with $pydoc solution unit text for this script can be triggled with $python solutin.py -v

CLASSES unittest.case.TestCase(builtin.object) TestMethods

class TestMethods(unittest.case.TestCase)
 |  class to define a set of unit test with Python unittest module
 |  
 |  Method resolution order:
 |      TestMethods
 |      unittest.case.TestCase
 |      __builtin__.object
 |  
 |  Methods defined here:
 |  
 |  test_GPS2POS(self)
 |      test GPS2POS function
 |  
 |  test_dist(self)
 |      test the function dist()
 |  
 |  ----------------------------------------------------------------------
 |  Methods inherited from unittest.case.TestCase:
 |  
 |  __call__(self, *args, **kwds)

FUNCTIONS GPS2POS((lat, lng)) transform from GPS to coordinate system (POS) perform the following test:  »> GPS2POS((52.516288,13.377689)) (-6.48982764810209, 9.159322471000536)

POS2GPS((x, y))
    transform from coordinate system (POS) to GPS

compute_joint_probability(ss, gatePOS, satellitePOS, riverPOS)
    compute joint probability of all point in the search space

dist(x1, y1, x2, y2, x3, y3)
    compute distance from a point to line segment
    x3,y3 is the point
    perform the following test
    >>> dist(-7.83434151195,17.378188238,-17.5348765366,0.375603802,-0.0,0.0)
    15.416540040627943

find_her()
    the function is designed to output locations and probabilities

plot_res(res)

prob_gate(pointPOS, gatePOS)
    compute probability according to lognormal distribution base on gate

prob_river(pointPOS, riverPOS)
    compute probability according to Gaussian distribution base on river

prob_satellite(pointPOS, satellitePOS)
    compute probability according to Gaussian distribution for satellite

save_probability(res)
    save probability to file

show_result(res)
    show results on google map

transformation(riverGPS, satelliteGPS, gateGPS, startGPS, stopGPS)
    wrapper function to transform the distance from GPS to locations POS

DATA author = ‘Hongyu Su’ else = ‘other information can be documented here’ version = ‘1.0’ gateGPS = (52.516288, 13.377689) lognorm = norm = riverGPS = [(52.529198, 13.274099), (52.531835, 13.29234), (52.522116,... satelliteGPS = [(52.590117, 13.39915), (52.437385, 13.553989)] startGPS = (52.434011, 13.274099) stopGPS = (52.564011, 13.554099)

VERSION 1.0

AUTHOR Hongyu Su


# Unit test

This brings an old topic of test-driven development (TDD) which is to design a software/function/programme starting with writing test case. After that write the expected outcome of the test case. Finally, implement the functionalities to pass the test case.

## `doctest` module

### Build test case

- `doctest` module is a Python builtin which allows building test case into the source code, in particular documentation, of the function. 
- Import the `doctest` module into your script with the following code `import doctest`.
- Each line in documentation part of the source code starting with `>>>` will run as if under the interactive Python shell, which is counted as a test case.
- The return from the test case should match exactly the following line written in the documentation part of the Python code.
- For example, the following code will compute the shortest distance of a point to a line segment, and a test case is written into the documentation part of the code.

  ```python
  def dist(x1,y1, x2,y2, x3,y3):
  '''
  compute distance from a point to line segment
  x3,y3 is the point
  perform the following test
  >>> dist(-7.83434151195,17.378188238,-17.5348765366,0.375603802,-0.0,0.0)
  15.416540040627943
  '''
  px = x2-x1
  py = y2-y1
  something = px*px + py*py
  u =  ((x3 - x1) * px + (y3 - y1) * py) / float(something)
  if u > 1:
    u = 1
  elif u < 0:
    u = 0
  x = x1 + u * px
  y = y1 + u * py
  dx = x - x3
  dy = y - y3
  dist = math.sqrt(dx*dx + dy*dy)
  return dist 

Run test case

unittest module

Python unit test module unittest is sometimes referred as PyUnit. There are a few concept closely related to the unittest module, including

The work flow of performing a unit test with unittest is

Build test cases

Run test


Ran 1 test in 0.000s

OK guest37:tmpSolution su$ python -m unittest -v solution.TestMethods.test_GPS2POS test_GPS2POS (solution.TestMethods) … ok


Ran 1 test in 0.000s

OK guest37:tmpSolution su$ python -m unittest -v solution.TestMethods test_GPS2POS (solution.TestMethods) … ok test_dist (solution.TestMethods) … ok


Ran 2 tests in 0.000s

OK


### Other functionalities

- Run unit test with `unittest` for files with suffix `.py` in the directory with the following command.

  ```bash
  $ python -m unittest discover -v -p *py

nose module

nose is a third party module which does not come by default with Python. An installation is required. However, I don’t think I manage to install the package. But nose is at least working well for some basic test cases.

Write test case

The test case for nose is quite similar as unittest but is much simpler. I don’t need to define classes. Just go straight forwards to write a test function. The function that implemented the same test case as described above can be coded simply as the following.

def test_dist():
  '''unit test with nose'''
  assert dist(-7.83434151195,17.378188238,-17.5348765366,0.375603802,-0.0,0.0) == 15.416540040627943
  pass

def test_GPS2POS():
  '''unit test with nose'''
  assert GPS2POS((52.516288,13.377689)) == (-6.48982764810209, 9.159322471000536)
  pass

Run test

nosetests -v solution.py

The command line argument -v is same as before which is to print detailed test information on screen. The result is shown as the follows.

test GPS2POS function ... ok
test the function dist() ... ok
unit test with nose ... ok
unit test with nose ... ok

----------------------------------------------------------------------
Ran 4 tests in 0.002s

OK

There are 4 tests in total in which the first two tests are built with unittest and the last two tests are built with nose.

setup and teardown functions in nose

def setup_test_GPS2POS(): _globals[‘tmpPoint’] = (52.516288,13.377689) pass

def teardown_test_GPS2POS(): _globals[‘tmpPoint’] = None pass

@with_setup(setup_test_GPS2POS,teardown_test_GPS2POS) def test(): tmpPoint = _globals[‘tmpPoint’] assert GPS2POS(tmpPoint) == (-6.48982764810209, 9.159322471000536) ```

Other functionalities with nose

External references

Hongyu Su 02 November 2015