[Edu-sig] dual use __main__: work or test

Wes Turner wes.turner at gmail.com
Tue Feb 14 17:45:33 EST 2017


On Saturday, February 11, 2017, kirby urner <kirby.urner at gmail.com> wrote:

> Does anyone use this pattern?:
>
> (a) accept command line parameters if __name__ == "__main__" or
> (b) run unittests if no parameters passed
>
> Something like:
>
> if __name__ == "__main__":
>     if len(sys.argv)==7:
>         command_line()
>     else:
>         unittest.main()
>
> I'm using this pattern with my classes, as a way of touching on both
> passing arguments from the command line (with nod to argparse for POSIX
> compliance), and self-contained testing.
>

https://en.wikipedia.org/wiki/POSIX

- https://en.wikipedia.org/wiki/Exit_status
- https://en.wikipedia.org/wiki/Exit_(system_call)
- https://docs.python.org/3/library/signal.html#example
- https://docs.python.org/3/library/atexit.html#atexit-example *
- https://docs.python.org/3/library/sys.html#sys.exit

returncode = range(0,128)[0]
sys.exit(returncode)

# https://docs.python.org/3.5/library/unittest.html#unittest.main
sys.exit(unittest.main(exit=False))


# Running tests from the CLI

    def _main(argv=None)

argv = list(argv)
idx = argv.index('-t')
if idx != -1:
    test_args = argv[idx+1:]
    argv.pop('-t')


- https://docs.python.org/2.7/library/optparse.html
- https://docs.python.org/3/library/argparse.html
- http://click.pocoo.org/5/

In order to make main() testable, I like the following signature:

def main(argv=None, stdin=None, stdout=None):
    argv = list(argv)
    # optparse/argparse
    output = func()
    return 0

def _main():
    sys.exit(main(sys.argv))

if __name__ == "__main__":
    _main()

def test_main_help():
    retcode = _main(['-h',])
    assert retcode == 0
    retcode = _main(['--help',])
    assert retcode == 0


... in order to get test coverage for the main() entrypoint.

Additional advantages of defining _main() and main():

- python -m modulename  # should sys.exit
  - __main__.py
  - __init__.py:__main__

- setup.py console_script entry_points # should sys.exit
  - setup.py: 'scriptname = modulename:main'
  -
https://setuptools.readthedocs.io/en/latest/setuptools.html#automatic-script-creation


>
> Maybe this would be better with doctest instead. I could do another
> version....
>

Pytest

| homepage: http://pytest.org
| pypi: https://pypi.python.org/pypi/pytest
| src: https://github.com/pytest-dev/pytest
| docs: http://doc.pytest.org/en/latest/contents.html

http://doc.pytest.org/en/latest/talks.html

- Fixtures:
  - @pytest.fixture(scope=)
  - http://docs.pytest.org/en/latest/fixture.html
  - http://doc.pytest.org/en/latest/fixture.html#fixture-parametrize

- Parametrizations:
  - @pytest.mark.parametrized
  - http://doc.pytest.org/en/latest/parametrize.html

- Assertions
  - assert (with regular 'assert')
    - note that asserts are compiled out with 'python -O'
  - with pytest.raises
  - http://doc.pytest.org/en/latest/assert.html

- Plugins
  -
http://docs.pytest.org/en/latest/plugins.html#installing-external-plugins-searching
  - https://plugincompat.herokuapp.com/
    - https://pivotfinland.com/pytest-sugar/
    - https://github.com/zonca/pytest-ipynb (include 'assert' in Jupyter
Notebook cells)
    - https://github.com/matplotlib/pytest-mpl
    - https://github.com/kevin1024/pytest-httpbin (great for learning HTTP
w/ e.g. requests)
    - https://github.com/getsentry/pytest-responses (mock requests w/
responses)
    - https://github.com/manahl/pytest-plugins (shutil.Workspace.__exit__,
.__del__)
    - https://github.com/pytest-dev/pytest-runner  ($ python setup.py
pytest )
    - https://github.com/westurner?tab=stars&q=pytest

>
>
> Example:
> https://github.com/4dsolutions/Python5/blob/master/tetravolume.py
>

- unitest.main(exit=True) is the default
- @pytest.mark.parametrized
- sage
   - https://github.com/sagemath/sage/tree/master/src/sage/geometry
   - http://doc.sagemath.org/html/en/reference/geometry/
  -
http://doc.sagemath.org/html/en/reference/geometry/sage/geometry/polyhedron/constructor.html
  - http://doc.sagemath.org/html/en/reference/plot3d/#backends {Tachyon,
Three.js}
   -
http://doc.sagemath.org/html/en/reference/plot3d/sage/plot/plot3d/base.html
   -
http://doc.sagemath.org/html/en/reference/plot3d/sage/plot/plot3d/platonic.html
   - https://github.com/sagemath/sage/blob/master/src/sage/plot/polygon.py
Polygon




>
>
>
Kirby
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/edu-sig/attachments/20170214/f90f2d13/attachment.html>


More information about the Edu-sig mailing list