Installable Single Package
00:00 In the previous lesson, I talked about a simple package revolving around a single-file program. In this lesson, I’m going to make it more complicated and add more code and see how that changes the approach. First off, if you’ve got more than one coding file, you’re probably going to want to group it together into a module.
00:18 I’m going to take the example that I had before with a single file that had a Hello World in it and add a utilities file to go with it. When you have multiple files, typically that means you also want multiple test files.
00:30 You’ll also want to start doing things like checking your test coverage and running a linter to help you catch problematic code. The package itself doesn’t change by all that much. Here’s an example.
helloworld.py is now inside of a directory called
helloworld—that’s the module. Because it’s a module, it has to have a
__init__ file and the promised
utils.py file that I talked about before, splitting up
helloworld into multiple units.
tests now also becomes a directory. It’s a module as well so that it can be run. It also contains a
__init__. There’s a specific file for testing the
helloworld file, and a specific file for testing
runtests isn’t necessary, but it’s something I tend to do because I get tired of typing out the long
python -m unittest command, and particularly if you start doing things like running coverage tests—which I’ll show you how to do—there’s a little more logic to it, so I create a little Bash file to help with that. The rest of the files here that I’ve grayed out are the same files that were there in the previous package.
This is my new version of Hello World. It’s very, very similar to the previous one. All that’s changed is I’m now importing code from the
utils library inside of
helloworld. So, I’m now using a module
helloworld with a
utils file inside of it and grabbing the function
Then, I’m replacing what was a
print() function on line 14 with the
show_message() is just a wrapper for
utils is a really simple file—but you can see how the two files interact inside of the module together.
This changes how things are imported, so line 8 has changed: importing the
URL from the file that’s been moved. The other thing that has changed in this file is there’s some stuff missing.
Because I’m going to be using the
coverage—which I’ll show you in a minute—I no longer need the
'__main__' section at the bottom of the file for execution. The last thing I changed was—you may recall—
helloworld used to have a
__version__ variable inside of it.
02:56 This entire lesson is on writing more code with a larger module, which means you really should be writing more tests to go with it. Once you’re writing a lot of tests, it’s a good idea to figure out whether or not your tests are actually doing their job.
One measure of this is the coverage. Coverage tells you what percentage of your code has actually been executed by the tests. There’s some great libraries out there to help you with this; one of the most popular ones is simply enough called
coverage, and it can be found by installing
pip install coverage.
03:37 The first line here is the output from the program. I’ve actually commented out the line that does something, which is why this is empty. The second section is Python telling me that the tests have run.
One of my tests is empty, but of course, it passes when it’s empty. And the final section here is the simple report from
coverage. You can see
helloworld.py was executed, two of the lines inside of it were missed and not run, and it only has 75% coverage.
It’s very hard to test the
__main__ execution of a script inside of your tests files, so instead of measuring it, I test the
do_hello() function specifically and then do a
# pragma: no cover so that
coverage doesn’t actually examine this line.
This stops anything from being cached and causing strange behaviors. This is overkill, but it’s saved my bacon on a couple occasions. The actual
coverage command is very similar to doing the
-m unittest with Python directly, except that you also pass in information on what modules to look for source code in. This line itself is sufficient to get the coverage information, but then as you’ve seen inside of the results, I create the simple coverage report and then
echo some of this information out in an easier-to-read fashion.
If you’re using a linter like
pep8, this is a good place to put it so that it runs after you’ve run your tests every single time. The last thing that I want to show you in this lesson is just some simplification inside of
setup.py. In the previous version, there were four or five lines that read in the
helloworld.py file and grepped out the
05:58 This lesson talked about the file structure changes in going from a single-file program to a multi-file module. In the next lesson, I’m going to make things even more complicated and add multiple modules.
Become a Member to join the conversation.