<div dir="ltr"><br><br>On Saturday, February 11, 2017, kirby urner <<a href="mailto:kirby.urner@gmail.com" target="_blank">kirby.urner@gmail.com</a>> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div><div><div><div><div>Does anyone use this pattern?:  <br></div><br>(a) accept command line parameters if __name__ == "__main__" or<br></div>(b) run unittests if no parameters passed<br><br></div>Something like:<br><br>if __name__ == "__main__":<br>    if len(sys.argv)==7:<br>        command_line()  <br>    else:<br>        unittest.main()<br><br></div>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. </div></div></blockquote><div><br></div><div><a href="https://en.wikipedia.org/wiki/POSIX">https://en.wikipedia.org/wiki/POSIX</a><br></div><div><br></div><div>- <a href="https://en.wikipedia.org/wiki/Exit_status">https://en.wikipedia.org/wiki/Exit_status</a><br></div><div>- <a href="https://en.wikipedia.org/wiki/Exit_(system_call)">https://en.wikipedia.org/wiki/Exit_(system_call)</a></div><div>- <a href="https://docs.python.org/3/library/signal.html#example">https://docs.python.org/3/library/signal.html#example</a></div><div>- <a href="https://docs.python.org/3/library/atexit.html#atexit-example">https://docs.python.org/3/library/atexit.html#atexit-example</a> *</div><div>- <a href="https://docs.python.org/3/library/sys.html#sys.exit">https://docs.python.org/3/library/sys.html#sys.exit</a><br></div><div><br></div><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><div>returncode = range(0,128)[0]</div><div>sys.exit(returncode)</div><div><br></div><div># <a href="https://docs.python.org/3.5/library/unittest.html#unittest.main">https://docs.python.org/3.5/library/unittest.html#unittest.main</a></div><div>sys.exit(unittest.main(exit=False))</div></blockquote><div><br></div><div># Running tests from the CLI</div><div><br></div><div>    def _main(argv=None)</div><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><div>argv = list(argv)</div><div>idx = argv.index('-t')</div><div>if idx != -1:</div><div>    test_args = argv[idx+1:]</div><div>    argv.pop('-t')</div></blockquote><div><br></div><div>- <a href="https://docs.python.org/2.7/library/optparse.html">https://docs.python.org/2.7/library/optparse.html</a><br></div><div>- <a href="https://docs.python.org/3/library/argparse.html">https://docs.python.org/3/library/argparse.html</a><br></div><div>- <a href="http://click.pocoo.org/5/">http://click.pocoo.org/5/</a><br></div><div> </div><div>In order to make main() testable, I like the following signature:</div><div><br></div><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><div>def main(argv=None, stdin=None, stdout=None):</div><div>    argv = list(argv)</div><div>    # optparse/argparse</div><div>    output = func()</div><div>    return 0</div><div><br></div><div>def _main():</div><div>    sys.exit(main(sys.argv))</div><div><br></div><div>if __name__ == "__main__":</div><div>    _main()</div><div><br></div><div>def test_main_help():</div><div>    retcode = _main(['-h',])</div><div>    assert retcode == 0</div><div>    retcode = _main(['--help',])</div><div>    assert retcode == 0</div></blockquote><div><br></div><div>... in order to get test coverage for the main() entrypoint.</div><div><br></div><div>Additional advantages of defining _main() and main():</div><div><br></div><div>- python -m modulename  # should sys.exit</div><div>  - __main__.py</div><div>  - __init__.py:__main__<br></div><div><br></div><div>- setup.py console_script entry_points # should sys.exit</div><div>  - setup.py: 'scriptname = modulename:main'</div><div>  - <a href="https://setuptools.readthedocs.io/en/latest/setuptools.html#automatic-script-creation">https://setuptools.readthedocs.io/en/latest/setuptools.html#automatic-script-creation</a></div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div><br><br>Maybe this would be better with doctest instead. I could do another version....</div></div></blockquote><div><br></div><div>Pytest</div><div><br></div><div>| homepage: <a href="http://pytest.org">http://pytest.org</a><br></div><div>| pypi: <a href="https://pypi.python.org/pypi/pytest">https://pypi.python.org/pypi/pytest</a></div><div>| src: <a href="https://github.com/pytest-dev/pytest">https://github.com/pytest-dev/pytest</a></div><div>| docs: <a href="http://doc.pytest.org/en/latest/contents.html">http://doc.pytest.org/en/latest/contents.html</a></div><div><br></div><div><a href="http://doc.pytest.org/en/latest/talks.html">http://doc.pytest.org/en/latest/talks.html</a><br></div><div><br></div><div>- Fixtures:</div><div>  - @pytest.fixture(scope=)</div><div>  - <a href="http://docs.pytest.org/en/latest/fixture.html">http://docs.pytest.org/en/latest/fixture.html</a></div><div>  - <a href="http://doc.pytest.org/en/latest/fixture.html#fixture-parametrize">http://doc.pytest.org/en/latest/fixture.html#fixture-parametrize</a></div><div><br></div><div>- Parametrizations:</div><div>  - @pytest.mark.parametrized</div><div>  - <a href="http://doc.pytest.org/en/latest/parametrize.html">http://doc.pytest.org/en/latest/parametrize.html</a></div><div><br></div><div>- Assertions </div><div>  - assert (with regular 'assert')</div><div>    - note that asserts are compiled out with 'python -O'</div><div>  - with pytest.raises</div><div>  - <a href="http://doc.pytest.org/en/latest/assert.html">http://doc.pytest.org/en/latest/assert.html</a></div><div><br></div><div>- Plugins</div><div>  - <a href="http://docs.pytest.org/en/latest/plugins.html#installing-external-plugins-searching">http://docs.pytest.org/en/latest/plugins.html#installing-external-plugins-searching</a><br></div><div>  - <a href="https://plugincompat.herokuapp.com/">https://plugincompat.herokuapp.com/</a><br></div><div>    - <a href="https://pivotfinland.com/pytest-sugar/">https://pivotfinland.com/pytest-sugar/</a></div><div>    - <a href="https://github.com/zonca/pytest-ipynb">https://github.com/zonca/pytest-ipynb</a> (include 'assert' in Jupyter Notebook cells)</div><div>    - <a href="https://github.com/matplotlib/pytest-mpl">https://github.com/matplotlib/pytest-mpl</a></div><div>    - <a href="https://github.com/kevin1024/pytest-httpbin">https://github.com/kevin1024/pytest-httpbin</a> (great for learning HTTP w/ e.g. requests)</div><div>    - <a href="https://github.com/getsentry/pytest-responses">https://github.com/getsentry/pytest-responses</a> (mock requests w/ responses)</div><div>    - <a href="https://github.com/manahl/pytest-plugins">https://github.com/manahl/pytest-plugins</a> (shutil.Workspace.__exit__, .__del__)</div><div>    - <a href="https://github.com/pytest-dev/pytest-runner">https://github.com/pytest-dev/pytest-runner</a>  ($ python setup.py pytest )</div><div>    - <a href="https://github.com/westurner?tab=stars&q=pytest">https://github.com/westurner?tab=stars&q=pytest</a></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div><br><br>Example:<br><a href="https://github.com/4dsolutions/Python5/blob/master/tetravolume.py" target="_blank">https://github.com/4dsolutions<wbr>/Python5/blob/master/<wbr>tetravolume.py</a></div></div></blockquote><div><br></div><div>- unitest.main(exit=True) is the default</div><div>- @pytest.mark.parametrized</div><div>- sage</div><div>   - <a href="https://github.com/sagemath/sage/tree/master/src/sage/geometry">https://github.com/sagemath/sage/tree/master/src/sage/geometry</a></div><div>   - <a href="http://doc.sagemath.org/html/en/reference/geometry/">http://doc.sagemath.org/html/en/reference/geometry/</a></div><div>  - <a href="http://doc.sagemath.org/html/en/reference/geometry/sage/geometry/polyhedron/constructor.html">http://doc.sagemath.org/html/en/reference/geometry/sage/geometry/polyhedron/constructor.html</a><br></div><div>  - <a href="http://doc.sagemath.org/html/en/reference/plot3d/#backends">http://doc.sagemath.org/html/en/reference/plot3d/#backends</a> {Tachyon, Three.js}</div><div>   - <a href="http://doc.sagemath.org/html/en/reference/plot3d/sage/plot/plot3d/base.html">http://doc.sagemath.org/html/en/reference/plot3d/sage/plot/plot3d/base.html</a></div><div>   - <a href="http://doc.sagemath.org/html/en/reference/plot3d/sage/plot/plot3d/platonic.html">http://doc.sagemath.org/html/en/reference/plot3d/sage/plot/plot3d/platonic.html</a></div><div>   - <a href="https://github.com/sagemath/sage/blob/master/src/sage/plot/polygon.py">https://github.com/sagemath/sage/blob/master/src/sage/plot/polygon.py</a> Polygon</div><div><br></div><div><br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div><br>  </div></div></blockquote><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr">Kirby<br><br></div>
</blockquote>
</div>