Skip to content

Commit 4f0b90c

Browse files
committed
Add tox generation script, but don't use it yet
1 parent 4ae94a5 commit 4f0b90c

File tree

6 files changed

+1956
-0
lines changed

6 files changed

+1956
-0
lines changed

scripts/generate-test-files.sh

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
#!/bin/sh
2+
3+
# This script generates tox.ini and CI YAML files in one go.
4+
5+
set -xe
6+
7+
cd "$(dirname "$0")"
8+
9+
python -m venv .venv
10+
. .venv/bin/activate
11+
12+
pip install -e ..
13+
pip install -r populate_tox/requirements.txt
14+
pip install -r split_tox_gh_actions/requirements.txt
15+
16+
python populate_tox/populate_tox.py
17+
python split_tox_gh_actions/split_tox_gh_actions.py

scripts/populate_tox/README.md

Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
# Populate Tox
2+
3+
We integrate with a number of frameworks and libraries and have a test suite for
4+
each. The tests run against different versions of the framework/library to make
5+
sure we support everything we claim to.
6+
7+
This `populate_tox.py` script is responsible for picking reasonable versions to
8+
test automatically and generating parts of `tox.ini` to capture this.
9+
10+
## How it works
11+
12+
There is a template in this directory called `tox.jinja` which contains a
13+
combination of hardcoded and generated entries.
14+
15+
The `populate_tox.py` script fills out the auto-generated part of that template.
16+
It does this by querying PYPI for each framework's package and its metadata and
17+
then determining which versions make sense to test to get good coverage.
18+
19+
The lowest supported and latest version of a framework are always tested, with
20+
a number of releases in between:
21+
- If the package has majors, we pick the highest version of each major. For the
22+
latest major, we also pick the lowest version in that major.
23+
- If the package doesn't have multiple majors, we pick two versions in between
24+
lowest and highest.
25+
26+
#### Caveats
27+
28+
- Make sure the integration name is the same everywhere. If it consists of
29+
multiple words, use an underscore instead of a hyphen.
30+
31+
## Defining constraints
32+
33+
The `TEST_SUITE_CONFIG` dictionary defines, for each integration test suite,
34+
the main package (framework, library) to test with; any additional test
35+
dependencies, optionally gated behind specific conditions; and optionally
36+
the Python versions to test on.
37+
38+
The format is:
39+
40+
```
41+
integration_name: {
42+
"package": name_of_main_package_on_pypi,
43+
"deps": {
44+
rule1: [package1, package2, ...],
45+
rule2: [package3, package4, ...],
46+
},
47+
"python": python_version_specifier,
48+
}
49+
```
50+
51+
The following can be set as a rule:
52+
- `*`: packages will be always installed
53+
- a version specifier on the main package (e.g. `<=0.32`): packages will only
54+
be installed if the main package falls into the version bounds specified
55+
- specific Python version(s) in the form `py3.8,py3.9`: packages will only be
56+
installed if the Python version matches one from the list
57+
58+
Rules can be used to specify version bounds on older versions of the main
59+
package's dependencies, for example. If e.g. Flask tests generally need
60+
Werkzeug and don't care about its version, but Flask older than 3.0 needs
61+
a specific Werkzeug version to work, you can say:
62+
63+
```
64+
"flask": {
65+
"deps": {
66+
"*": ["Werkzeug"],
67+
"<3.0": ["Werkzeug<2.1.0"],
68+
}
69+
}
70+
```
71+
72+
Sometimes, things depend on the Python version installed. If the integration
73+
test should only run on specific Python version, e.g. if you want AIOHTTP
74+
tests to only run on Python 3.7+, you can say:
75+
76+
```
77+
"aiohttp": {
78+
...
79+
"python": ">=3.7",
80+
}
81+
```
82+
83+
If, on the other hand, you need to install a specific version of a secondary
84+
dependency on specific Python versions (so the test suite should still run on
85+
said Python versions, just with different dependency-of-a-dependency bounds),
86+
you can say:
87+
88+
```
89+
"celery": {
90+
...
91+
"deps": {
92+
"*": ["newrelic", "redis"],
93+
"py3.7": ["importlib-metadata<5.0"],
94+
},
95+
},
96+
```
97+
98+
## How-Tos
99+
100+
### Add a new test suite
101+
102+
1. Add the minimum supported version of the framework/library to `_MIN_VERSIONS`
103+
in `integrations/__init__.py`. This should be the lowest version of the
104+
framework that we can guarantee works with the SDK. If you've just added the
105+
integration, it's fine to set this to the latest version of the framework
106+
at the time.
107+
2. Add the integration and any constraints to `TEST_SUITE_CONFIG`. See the
108+
"Defining constraints" section for the format (or copy-paste one
109+
of the existing entries).
110+
3. Add the integration to one of the groups in the `GROUPS` dictionary in
111+
`scripts/split_tox_gh_actions/split_tox_gh_actions.py`.
112+
4. Add the `TESTPATH` for the test suite in `tox.jinja`'s `setenv` section.
113+
5. Run `scripts/generate-test-files.sh` and commit the changes.
114+
115+
### Migrate a test suite to populate_tox.py
116+
117+
A handful of integration test suites are still hardcoded. The goal is to migrate
118+
them all to `populate_tox.py` over time.
119+
120+
1. Remove the integration from the `IGNORE` list in `populate_tox.py`.
121+
2. Remove the hardcoded entries for the integration from the `envlist` and `deps` sections of `tox.jinja`.
122+
2. Run `scripts/generate-test-files.sh`.
123+
3. Run the test suite, either locally or by creating a PR.
124+
4. Address any test failures that happen.
125+
126+
You might have to introduce additional version bounds on the dependencies of the
127+
package. Try to determine the source of the failure and address it.
128+
129+
Common scenarios:
130+
- An old version of the tested package installs a dependency without defining
131+
an upper version bound on it. A new version of the dependency is installed that
132+
is incompatible with the package. In this case you need to determine which
133+
versions of the dependency don't contain the breaking change and restrict this
134+
in `TEST_SUITE_CONFIG`.
135+
- Tests are failing on an old Python version. In this case first double-check
136+
whether we were even testing them on that version in the original `tox.ini`.

0 commit comments

Comments
 (0)