- Get link
- X
- Other Apps
Have you ever wondered how to quickly start a python project?
For me, I usually write python as scripts to automate some of my daily tasks: like renaming folders, calculate something for me. In this case, we can just write a <name>.py file, and run python <name>.py to run the script.
What if you want to start a big python project? For example, if you want to write a machine learning package, what is the best way to share your work?
Package
It turns out that python has its own packaging system. You could create a bunch of .py files in the same directory and then add a "__init__.py" in the folder to convert your directory as a python package. It sounds so simple, isn't it? Heh.
However, how do you test the usage of your package? you would need to run command like "python -m test.main" to run a file in another package if you have imported file from another package.
Now imagine if you want to write test cases for the whole package, doing all this stuffs would not be convenient, agree?
Best Practice
So, I searched a lot for python best practices to manage a big project and I found a "angular-cli" like python project, named "cookiecutter-pylibrary".
It has organized your project using the suggested folder structure by the author. See the blog by the author for more details. Basically all packages are located in a src folder and all tests are located in tests folder.
The folder structure is not the only reason I chose this package as a quick start project:
- It also provides some testing templates, licensing, readme
- It also provides some online free integration templates as well as code review templates (need to pay)
How
Ok. How to start using the template?
1. Run:
This is to install the tox (test automation library) and cookiecutter libraries to your machine.pip install tox cookiecutter
2. Then Run:
cookiecutter gh:ionelmc/cookiecutter-pylibraryNote that gh means github. It would be good if you change to your real github repository.
3. Answer the questions, but choose pytest as the testing framework.
4. Run "tox" to run the test cases
Fix Test Failed In The Template
If you ran "tox", you might notice that the test failed. Why? You might not have setup all the settings and good things provided in the template.
To let the tests simply pass, comment out "check" and "docs" in tox.ini first.
[tox]
envlist =
clean,
; check,
{py27,py34,py35,py36,py37,pypy,pypy3},
report,
; docs,
PyTest
PyTest is a Python Test Framework which is incredibly easy to use. However, do note that it would be best if you follow the following convention:
1. The test files should be "test_*.py"
2. The test methods should have "test_" prefix
The original template has already included a sample test case written using PyTest, but I am going to show you one more example test case:
Suppose you have a function "inc" defines like this:
def inc(x):
return x + 1
Then a sample test case would be something like this:
def test_inc():
assert inc(1) == 2
Do note that every test case has a "assert" keyword, follow by a boolean clause, which is inc(1) == 2 in this case.
See py.test for more info
Hypothesis
Let us continue with the function "inc" example. By right, we should have tested every integers of x to make sure that this function works correctly. However, it is impossible to do so, right? Due to this, a few famous testing methodologies have come out. For example, boundary test. (well we could say positive numbers, 0 and negative numbers are different regions, then -2, -1, 0, 1 are sufficient for the boundary test)
The testing methodologies are not a focus today, you can find other references to learn more about testing designs. (Example: https://simpleprogrammer.com/proper-test-case-design-for-testing-equivalence-partitioning/ )
What if I tell you, you could specify that the input is number, and check if the output must be number + 1? This is what "Hypothesis" is doing! It integrates well with PyTest and is extremely useful.
To get started,
1. Install Hypothesis
2. If you are using the template that I introduced just now, add "hypothesis" to tox.ini, like this:pip install hypothesis
[testenv]
basepython =
pypy: {env:TOXPYTHON:pypy}
pypy3: {env:TOXPYTHON:pypy3}
{py27,docs,spell}: {env:TOXPYTHON:python2.7}
py34: {env:TOXPYTHON:python3.4}
py35: {env:TOXPYTHON:python3.5}
py36: {env:TOXPYTHON:python3.6}
py37: {env:TOXPYTHON:python3.7}
{bootstrap,clean,check,report,codecov}: {env:TOXPYTHON:python3}
setenv =
PYTHONPATH={toxinidir}/tests
PYTHONUNBUFFERED=yes
passenv =
*
usedevelop = false
deps =
pytest
pytest-travis-fold
pytest-cov
hypothesis
3. Add a sample test case, for example this:
from hypothesis import given
import hypothesis.strategies as st
@given(st.integers())
def test_inc_withhypothesis(x):
assert inc(x) == x + 1
Note that now you have supplied integers to the test_inc_withhypothesis function. It can generate some possible inputs to test this function.
from hypothesis import given, example
import hypothesis.strategies as st
@given(st.integers())
@example(0)
def test_inc_withhypothesis(x):
assert inc(x) == x + 1
5. Run
toxTo see the result it generated. Is this fun? ;)
Travis CI
Now all tests passed in your machine, but how do you make sure all tests passed in other machines too? This is where Travis CI comes in. It is a website that can run all your tests online. If your project is open-source, it is free of charge as well. This is called continuous integration (CI). To learn the importance of CI, please see: https://about.gitlab.com/2015/02/03/7-reasons-why-you-should-be-using-ci/
Assume that you have pushed all your local changes to a github repo. Now, visit https://travis-ci.org/ and sign in using your github account. Enable the travis build in the github. Next time, when you push, the travis build will be automatically triggered, and will automatically send an email to you to inform you about the build status if it is failed.
Of course, the badge on your readme would also show the build status.
However, you would need to comment out check and docs to make sure that it is working too:
env:
global:
- LD_PRELOAD=/lib/x86_64-linux-gnu/libSegFault.so
- SEGFAULT_SIGNALS=all
matrix:
# - TOXENV=check
# - TOXENV=docs
AppVeyor
AppVeyor is another CI environment that you can try out. Go to AppVeyor and login using github too. Create a build project based on your project repository.
You would need to comment out check to make sure it can be run too:
environment:
global:
WITH_COMPILER: 'cmd /E:ON /V:ON /C .\ci\appveyor-with-compiler.cmd'
matrix:
#- TOXENV: check
# TOXPYTHON: C:\Python27\python.exe
# PYTHON_HOME: C:\Python27
# PYTHON_VERSION: '2.7'
# PYTHON_ARCH: '32'
- TOXENV: 'py27,report,codecov'
TOXPYTHON: C:\Python27\python.exe
PYTHON_HOME: C:\Python27
PYTHON_VERSION: '2.7'
PYTHON_ARCH: '32'
Requires.IO
This website checks for the package requirements of your project to make sure that your project is up to date. Visit Requires.IO and login using your github account. Activate the repository to make sure it is working.
Final Outcome
Let's say you have tried everything, the final outcome would be something like this:
You can take a look at me trial repo: python-python_start if you are interested. ^^
Summary
1. To organize python code, we use packages, which is split by directory.
2. I suggest using a python stat-up template (cookiecutter-pylibrary) to follow the best practices.
3. Use PyTest, Hypothesis for writing your tests and use Tox to run your tests.
4. Try out TravisCi, AppVeyor to feel to power of Continuous Integration.
5. Try out Requires.IO to make sure your packages are all up-to-date.
Yup. So, that's all for today. Thanks a lot for reading my blog.
To reward you for reading my blog, I am going to introduce you a Chinese Song, hopefully you like it:
Tank - 《我在呢》
To reward you for reading my blog, I am going to introduce you a Chinese Song, hopefully you like it:
Tank - 《我在呢》
If you like what I am doing, feel free to buy me a coffee.
pharaoh
14/10/18
5:13p.m.


Comments
Post a Comment