Although Make has traditionally been used to build C and C++ programs, its uses are far wider - here's a new example in which I've used it to test a whole series of Python programs, and if they all test correctly to build a distribution (tar) file.
Scenario - three Python programs / classes for distribution. Each has some test code - first.py tests from first principles, second.py tests using doctest and third.py tests using unittest. Of course, I would normally be consistent in using one test harness or another, but this
is a demonstration.
The makefile (full source
[here]):
version=1.2
pyproject_$(version).tgz: first.tmp second.tmp third.tmp
tar czf pyproject_$(version).tgz project
@echo "BUILD COMPLETED"
# Simple Python Program
first.tmp: project/first.py
python project/first.py
@touch first.tmp
# Next example uses Python's doctest
second.tmp: project/second.py
python project/second.py
@touch second.tmp
# Next example uses Python's unittest
third.tmp: project/third.py
python project/third.py
@touch third.tmp
clean:
@rm -f *.tmp
@rm -f *.tgz
@echo "cleaned up"
Each of the Python test classes is written to return a successful status (0, because we're at shell level) if the test passes, and a failed status (1) if the test fails, so that the build will only complete through to distribution if all tests pass.
In first.py (full source
[here]), the test I have added onto the end of the test harness is as follows:
if tpc != 495: exit(1)
exit(0)
where tpc is my test variable that should end up with a result of "495" if the code runs right.
Doctest return a status line that we can analyse similarly:
if status.find("failed=0") != -1: return 0
return 1
(my doctest code is written within a function, thus "return" rather than "exit").
See full source
[here]
Unittest automatically exits with a success / failure status, so all I need to run my test is:
if __name__ == '__main__':
unittest.main()
See full source
[here]
Let's run that - initially with a bug (for testing) in the doctest example:
wizard:pyproject graham$ make
python project/first.py
First Great Western cl 150 160 2
First Avon and Somerset 81 1
Faresaver 29 1
South West Trains cl 159 225 3
--- TOTAL --- 495 7
python project/second.py
**********************************************************************
File "project/second.py", line 4, in __main__.factorial
Failed example:
[factorial(n) for n in range(6)]
Expected:
[1, 1, 2, 7, 24, 120]
Got:
[1, 1, 2, 6, 24, 120]
**********************************************************************
1 items had failures:
1 of 1 in __main__.factorial
***Test Failed*** 1 failures.
make: *** [second.tmp] Error 1
wizard:pyproject graham$
Fixing the bug and trying again - you'll note the first test is NOT repeated:
wizard:pyproject graham$ make
python project/second.py
python project/third.py
...
----------------------------------------------------------------------
Ran 3 tests in 0.000s
OK
tar czf pyproject_1.2.tgz project
BUILD COMPLETED
wizard:pyproject graham$
and running again:
wizard:pyproject graham$ make
make: `pyproject_1.2.tgz' is up to date.
wizard:pyproject graham$
I'm adding a section on make onto the end of next week's private
Python course - the example above will be used during that course. Also happy to spend up to day going through Make on other private courses ...
(written 2012-03-17)
Associated topics are indexed as below, or enter http://melksh.am/nnnn for individual articles
Y212 - Python - Code testing, patterns, profiles and optimisation. [235] Preparation for a day's work - (2005-03-04)
[1140] Python GTK - Widget, Packing, Event and Feedback example - (2007-04-09)
[1146] __new__ v __init__ - python constructor alternatives? - (2007-04-14)
[1148] Python decorators - wrapping a method call in extra code - (2007-04-15)
[1555] Advanced Python, Perl, PHP and Tcl training courses / classes - (2008-02-25)
[2123] Using Python with OpenOffice - (2009-04-09)
[2616] Defining a static method - Java, Python and Ruby - (2010-02-01)
[3441] Pressing ^C in a Python program. Also Progress Bar. - (2011-09-15)
[3442] A demonstration of how many Python facilities work together - (2011-09-16)
[3464] Passing optional and named parameters to python methods - (2011-10-04)
[3478] Testing your Python classes with the unittest package - how to - (2011-10-14)
[4090] Test Driven Development in Python - Customer Comes First - (2013-05-16)
[4326] Learning to program - comments, documentation and test code - (2014-11-22)
[4344] Python base and inherited classes, test harness and unit testing - new examples - (2014-12-07)
[4446] Combining tests into suites, and suites into bigger suites - Python and unittest - (2015-03-01)
[4470] Testing in Python 3 - unittest, doctest and __name__ == __main__ too. - (2015-04-21)
[4538] Flask and unittest - hello web app test world - (2015-10-15)
[4540] Unittest of a Flask application including forms - (2015-10-15)
[4542] The principle of mocking - and the Python Mock package - (2015-10-17)
[4617] Pytest - starting example - (2016-01-07)
[4618] Pytest - second example beyond hello world - (2016-01-08)
[4716] Profiling your Python program - (2016-11-01)
A168 - Web Application Deployment - Compiler and development tools [694] Ant and Make - (2006-04-22)
[1671] Compiling C programs with gcc - an overview - (2008-06-10)
[2674] Make and makefiles - a commented example to help you learn - (2010-03-12)
[3053] Make - automating the commands for building and installing - (2010-11-16)
[3632] What is Make? - (2012-03-02)
[3651] Makefile - some basics, and a demonstration - (2012-03-13)
[3652] A Complete makefile example - (2012-03-14)
[3666] Makefile variables - defined internally, from the command line and from the environment - (2012-03-22)
[4013] Web Frameworks - nested templates - (2013-02-22)
[4585] What is make? What is gcc? - (2015-11-28)
Some other Articles
Finding all the unique lines in a file, using Python or PerlKeeping forum and blog comments cleanA Pivotal Incident - learning how to welcome your guestsWelcome to Melksham - our new communitiesUsing Make for a distributionBasham Festival, Melksham, early August 2012 - a welcomeTrainWest 2012 - 14th and 15th April, Melksham, WiltshireSights and scenes - more London trip picturesOn a sunny afternoon in LondonWhat is happening in 59 days time in Melksham?