Test packaging in python projects - python

Project structure:
project
some_api
__init__.py
api1.py
api2.py
some-folder
some-helper-module.py
lib
some-libs
docs
some-docs
Dockerfile
README.md
What should be the position for various tests
unit tests
function tests for the API
performance tests using API like Locust
Possible Solution
In the parallel of project, I can have something like
test
unit_tests
test1.py
test2.py
functional_tests
f_test1.py
f_test2.py
perf_tests
locust-files
load_test1.py
load_test2.py
test-data
something.csv

Generally, this structure is usually followed, Hope it helps. All types of test should be inside the test module with seperate submodule. For more details you can visit here
├── app_name
│
├── app_name
│ ├── __init__.py
│ ├── folder_name
│ └── etc...
├── tests
│ ├── unit
│ └── integration
├── README.md
├── setup.py
└── requirements.txt

In our team we used to put the unit tests alongside the python files they refer to, and the integration and performance tests outside the project as they will test it almost as blackbox :
project
some_api
__init__.py
api1.py
api1_unit_testing.py
api2.py
api2_unit_testing.py
some-folder
some-helper-module.py
lib
some-libs
docs
some-docs
tests
profiling_performance.py
integration_testing.py
Dockerfile
README.md

Related

Python packaging - Proper usage of the tests folder with unittest

I'm experimenting with packaging some Pythons projects and have followed this guide. The anonymized file tree can be seen below. The toml file is a barebones one from the tutorial modified appropriately. Building and uploading works well. So far so good.
.
├── LICENSE
├── pyproject.toml
├── README.md
├── src
│   └── mymodule
│      ├── __init__.py
│      └── main.py
└── tests
My next intended step is to package an older smaller well behaving project which includes a test suite written with unittest. Simplified structure below.
.
├── mymodule
│   ├── submoduleA
│   │   ├── __init__.py
│   │ └ foo.py
│   ├── submoduleB
│   │   ├── __init__.py
│   │ └ bar.py
│ ├── baz.py
│   └── __init__.py
└── tests
├── test_submoduleA.py
└── test_submoduleB.py
This is where my progress grinds to a halt.
There are many different ways to skin a cat but none directly involves unittest as far as I can tell. I have opted to go ahead by using tox to call the former.
Similarly when I have a look at different Python project repos the structure under tests seem to differ a bit.
End intent/wish: Convert said older project to a packagable one, editing the tests as little as possible, and using the tests for testing while developing and to do basic tests on the target device later.
Questions:
What is the purpose of the tests folder? Eg to run tests while developing files in src, to test the built package and/or to verify a package works once installed?
Is it possible to use the pyproject.toml file with unittest?

Python package-namespace: common test/docs/setup.py or one per namespace - which is the better pattern?

(In the interest of transparency, this is a follow up to a question asked here)
I'm dealing with related files in which a namespace package seems a good fit. I'm following the guide from the packaging authority, which places a setup.py in each namespace package;
mynamespace-subpackage-a/
setup.py
mynamespace/
subpackage_a/
__init__.py
mynamespace-subpackage-b/
setup.py
mynamespace/
subpackage_b/
__init__.py
module_b.py
In my tests, created a similar project. Apart from setup.py, I placed my unit tests, docs, and other stuff per namespace (I left out some of the directories for compactness.). I used pyscaffold to generate the namespaces.
├── namespace-package-test.package1
│ ├── LICENSE.txt
│ ├── README.md
│ ├── setup.cfg
│ ├── setup.py
│ ├── src
│ │ └── pkg1
│ │ ├── cli
│ │ │ ├── __init__.py
│ │ │ └── pkg1_cli.py
│ │ └── __init__.py
│ └── tests
├── namespace-package-test.package2
│ ├── AUTHORS.rst
However, I then noticed that pyscaffold has the option to create namespaces packages in the putup command.
(venv) steve#PRVL10SJACKSON:~/Temp$ putup --force my-package -p pkg1 --namespace namespace1
(venv) steve#PRVL10SJACKSON:~/Temp$ putup --force my-package -p pkg1 --namespace namespace2
This creates a folder structure like this;
├── AUTHORS.rst
├── CHANGELOG.rst
├── LICENSE.txt
├── README.rst
├── requirements.txt
├── setup.cfg
├── setup.py
├── src
│   ├── namespace1
│   │   ├── __init__.py
│   │   └── pkg1
│   │   ├── __init__.py
│   │   └── skeleton.py
│   └── namespace2
│   ├── __init__.py
│   └── pkg1
│   ├── __init__.py
│   └── skeleton.py
└── tests
├── conftest.py
└── test_skeleton.py
So I'm conflicted; I trust the team at pyscaffold, but it goes against the example from the packaging authority.
Are both approaches valid?
Is there a reason to choose one approach over the other?
The idea behind the namespace option in PyScaffold is to share/reuse namespaces across projects (in opposite of having more than one namespace inside a single project). Or in other words, to split a larger project in independently maintained/developed projects.
To my best understanding, having an structure like the one you showed in the 4th code block will not work. Using putup --force twice with 2 different namespaces for the same root folder is not the intended/supported usage.
The approach of PyScaffold is the same as the package authority, the only difference is that PyScaffold will assume you have only one package contained in a single project and git repository (PyScaffold also uses a src directory for the reasons explained in Ionel's blog post)
The reason behind adopting one setup.py per namespace+package is that it is required for building separated distribution files (i.e. you need one setup.py per *.whl).

What is the correct way to distribute "bin" and "tests" directories for a Python package?

I have created a python package.
At the advice of several internet sources (including https://github.com/pypa/sampleproject ), I have set up the directory structure like so:
root_dir
├── bin
│ └── do_stuff.py
├── MANIFEST.in
├── README.md
├── my_lib
│ ├── __init__.py
│ ├── __main__.py
│ └── my_lib.py
├── setup.cfg
├── setup.py
├── important_script.py
└── tests
├── __init__.py
└── test_lib.py
I have included tests, bin, and important_script.py in the manifest, and set include_package_data in setup.py to True.
However, after running pip install root_dir, I see that it correctly installed my_lib but bin and tests were just placed directly into Lib/site-packages as if they were separate packages.
I can't find important_script.py at all, and I don't think it was installed.
How do I correctly include these files/directories in my installation?
EDIT
So, it turns out that the bin and tests directories being placed directly into the site-packages directory was caused by something I was doing previously, but I can't discover what. At some point a build and a dist directory were generated in my root_dir (I assume by pip or setuptools?), and any changes I made to the project after that were not actually showing up in the installed package. After deleting these directories, I am no longer able to reproduce that issue.
The sample project distributes neither bin nor tests, it even explicitly excludes tests.
To include bin you should use scripts or entry_points (like in the sample project). Add this to your setup.py to setup() call:
scripts=['bin/do_stuff.py'],
To include tests you should restructure your tree to include the directory tests under the package directory:
root_dir
├── bin
│ └── do_stuff.py
├── MANIFEST.in
├── README.md
├── my_lib
│ ├── __init__.py
│ ├── __main__.py
│ └── my_lib.py
│ └── tests
│ ├── __init__.py
│ └── test_lib.py
├── setup.cfg
├── setup.py
├── important_script.py

Add non app tests to tests that run when executing python manage.py test

My Django project has a few app each with their respective tests. It also has a utils package that has its own tests.
The package utils is in a folder at the same level as manage.py and its tests are in a subfolder called tests in files called test_xxx.py
When I run python manage.py test Django runs all tests for all the apps in my project but it does not run the tests for the utils package. I can run the tests for the utils package by running python manage.py test utils.
What I would like to do is that tests for utils are also run when I run python manage.py test so that single command tests the whole suite for my project. I haven't been able to find anything in the documentation or searching google or here on how to do it. Any ideas?
Thanks for your help!!
--- Additional details ---
Directory structure
├── project
│ ├── __init__.py
│ ├── settings.py
│ ├── urls.py
│ └── wsgi.py
├── manage.py
├── ...
├── app1
│ ├── __init__.py
│ ├── urls.py
│ ├── views.py
│ ├── ...
│ └── tests
│ ├── test_views.py
│ └── test_models.py
├── app2
│ ├── __init__.py
│ ├── urls.py
│ ├── views.py
│ ├── ...
│ └── tests
│ ├── test_views.py
│ └── test_models.py
└── utils
├── __init__.py
├── code.py
└── tests
└── test_utils.py
Command to execute tests
python manage.py test
... that executes ...
nosetests --with-coverage --cover-package=app1,app2, utils --cover-html --cover-erase --logging-filter='selenium' --verbosity=1
And the coverage report shows that all the tests for app1 and app2 have been executed but not the tests for utils
Django uses the DiscoverRunner to run your tests harness. As you can see here: https://docs.djangoproject.com/en/2.1/topics/testing/advanced/#defining-a-test-runner
The first option is:
top_level can be used to specify the directory containing your
top-level Python modules. Usually Django can figure this out
automatically, so it’s not necessary to specify this option. If
specified, it should generally be the directory containing your
manage.py file.
Therefore your test should be run by the test harness because are in the same folder of your manage.py. Did you add the __init__.py in the tests folder?

Django-nose cannot find tests in folders

I know there are similar questions on StackOverflow, but I can't quite find one that matches my situation.
I'm working on an app built by someone else and have been adding tests.
The folder structure is like so:
my_project
├── apps
│ ├── app1
| ├── __init__.py
│ ├── tests.py
│ └── app2
│ └── app3
├── settings.py
├── urls.py
└── views.py
However, when I run python manage.py test, I get 0 tests run. Running the individual apps (python manage.py test app1) works when django-nose isn't installed, but works without django-nose.

Categories