Skip to content

Commit d5f688e

Browse files
authored
Merge pull request #916 from consideRatio/pr/refactor-tests
maint: refactor tests, fix upgrade tests (now correctly failing)
2 parents 7974981 + cb200d9 commit d5f688e

File tree

15 files changed

+479
-603
lines changed

15 files changed

+479
-603
lines changed

.github/integration-test.py

Lines changed: 136 additions & 157 deletions
Large diffs are not rendered by default.

.github/workflows/integration-test.yaml

Lines changed: 40 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -59,82 +59,66 @@ jobs:
5959
with:
6060
python-version: "3.10"
6161

62-
- name: Install pytest
63-
run: python3 -m pip install pytest
62+
# FIXME: The test_bootstrap.py script has duplicated logic to run build
63+
# and start images and run things in them. This makes tests slower,
64+
# and adds code to maintain. Let's try to remove it.
65+
#
66+
# - bootstrap.py's failure detections, put in unit tests?
67+
# - bootstrap.py's --show-progress-page test, include as integration test?
68+
#
69+
- name: Install integration-tests/requirements.txt for test_bootstrap.py
70+
run: pip install -r integration-tests/requirements.txt
6471

65-
# We abort pytest after two failures as a compromise between wanting to
66-
# avoid a flood of logs while still understanding if multiple tests would
67-
# fail.
6872
- name: Run bootstrap tests (Runs in/Builds ${{ matrix.distro_image }} derived image)
6973
run: |
70-
pytest --verbose --maxfail=2 --color=yes --durations=10 --capture=no \
71-
integration-tests/test_bootstrap.py
72-
timeout-minutes: 20
74+
pytest integration-tests/test_bootstrap.py
75+
timeout-minutes: 10
7376
env:
7477
# integration-tests/test_bootstrap.py will build and start containers
7578
# based on this environment variable. This is similar to how
7679
# .github/integration-test.py build-image can take a --build-arg
7780
# setting the base image via a Dockerfile ARG.
7881
BASE_IMAGE: ${{ matrix.distro_image }}
7982

80-
# We build a docker image from wherein we will work
81-
- name: Build systemd image (Builds ${{ matrix.distro_image }} derived image)
83+
- name: Build systemd image, derived from ${{ matrix.distro_image }}
8284
run: |
8385
.github/integration-test.py build-image \
8486
--build-arg "BASE_IMAGE=${{ matrix.distro_image }}"
8587
86-
# FIXME: Make the logic below easier to follow.
87-
# - In short, setting BOOTSTRAP_PIP_SPEC here, specifies from what
88-
# location the tljh python package should be installed from. In this
89-
# GitHub Workflow's test job, we provide a remote reference to itself as
90-
# found on GitHub - this could be the HEAD of a PR branch or the default
91-
# branch on merge.
92-
#
9388
# Overview of how this logic influences the end result.
9489
# - integration-test.yaml:
95-
# Runs integration-test.py by passing --bootstrap-pip-spec flag with a
96-
# reference to the pull request on GitHub.
97-
# - integration-test.py:
98-
# Starts a pre-build systemd container, setting the
99-
# TLJH_BOOTSTRAP_PIP_SPEC based on its passed --bootstrap-pip-spec value.
100-
# - systemd container:
101-
# Runs bootstrap.py
102-
# - bootstrap.py
103-
# Makes use of TLJH_BOOTSTRAP_PIP_SPEC environment variable to install
104-
# the tljh package from a given location, which could be a local git
105-
# clone of this repo where setup.py resides, or a reference to some
106-
# GitHub branch for example.
107-
- name: Set BOOTSTRAP_PIP_SPEC value
108-
run: |
109-
BOOTSTRAP_PIP_SPEC="git+https://github.com/$GITHUB_REPOSITORY.git@$GITHUB_REF"
110-
echo "BOOTSTRAP_PIP_SPEC=$BOOTSTRAP_PIP_SPEC" >> $GITHUB_ENV
111-
echo $BOOTSTRAP_PIP_SPEC
112-
113-
- name: Run basic tests (Runs in ${{ matrix.distro_image }} derived image)
90+
#
91+
# - Runs integration-test.py build-image, to build a systemd based image
92+
# to use later.
93+
#
94+
# - Runs integration-test.py run-tests, to start a systemd based
95+
# container, run the bootstrap.py script inside it, and then run
96+
# pytest from the hub python environment setup by the bootstrap
97+
# script.
98+
#
99+
# About passed --installer-args:
100+
#
101+
# - --admin admin:admin
102+
# Required for test_admin_installer.py
103+
#
104+
# - --plugin /srv/src/integration-tests/plugins/simplest
105+
# Required for test_simplest_plugin.py
106+
#
107+
- name: pytest integration-tests/
108+
id: integration-tests
114109
run: |
115-
.github/integration-test.py run-test basic-tests \
116-
--bootstrap-pip-spec "$BOOTSTRAP_PIP_SPEC" \
110+
.github/integration-test.py run-test integration-tests \
111+
--installer-args "--admin test-admin-username:test-admin-password" \
112+
--installer-args "--plugin /srv/src/integration-tests/plugins/simplest" \
117113
${{ matrix.extra_flags }} \
118114
test_hub.py \
119115
test_proxy.py \
120116
test_install.py \
121-
test_extensions.py
122-
timeout-minutes: 15
123-
124-
- name: Run admin tests (Runs in ${{ matrix.distro_image }} derived image)
125-
run: |
126-
.github/integration-test.py run-test admin-tests \
127-
--installer-args "--admin admin:admin" \
128-
--bootstrap-pip-spec "$BOOTSTRAP_PIP_SPEC" \
129-
${{ matrix.extra_flags }} \
130-
test_admin_installer.py
131-
timeout-minutes: 15
132-
133-
- name: Run plugin tests (Runs in ${{ matrix.distro_image }} derived image)
134-
run: |
135-
.github/integration-test.py run-test plugin-tests \
136-
--bootstrap-pip-spec "$BOOTSTRAP_PIP_SPEC" \
137-
--installer-args "--plugin /srv/src/integration-tests/plugins/simplest" \
138-
${{ matrix.extra_flags }} \
117+
test_extensions.py \
118+
test_admin_installer.py \
139119
test_simplest_plugin.py
140120
timeout-minutes: 15
121+
- name: show logs
122+
if: always() && steps.integration-tests.outcome != 'skipped'
123+
run: |
124+
.github/integration-test.py show-logs integration-tests

.github/workflows/unit-test.yaml

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -82,15 +82,15 @@ jobs:
8282
8383
- name: Install Python dependencies
8484
run: |
85-
python3 -m pip install -r dev-requirements.txt
86-
python3 -m pip install -e .
85+
pip install -r dev-requirements.txt
86+
pip install -e .
87+
88+
- name: List Python dependencies
89+
run: |
8790
pip freeze
8891
89-
# We abort pytest after two failures as a compromise between wanting to
90-
# avoid a flood of logs while still understanding if multiple tests would
91-
# fail.
9292
- name: Run unit tests
93-
run: pytest --verbose --maxfail=2 --color=yes --durations=10 --cov=tljh tests/
93+
run: pytest tests
9494
timeout-minutes: 15
9595

9696
- uses: codecov/codecov-action@v3

bootstrap/bootstrap.py

Lines changed: 36 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@
3636
logs can be accessed during installation. If this is
3737
passed, it will pass --progress-page-server-pid=<pid>
3838
to the tljh installer for later termination.
39-
--version TLJH version or Git reference. Default 'latest' is
39+
--version VERSION TLJH version or Git reference. Default 'latest' is
4040
the most recent release. Partial versions can be
4141
specified, for example '1', '1.0' or '1.0.0'. You
4242
can also pass a branch name such as 'main' or a
@@ -183,32 +183,32 @@ def run_subprocess(cmd, *args, **kwargs):
183183
return output
184184

185185

186+
def get_os_release_variable(key):
187+
"""
188+
Return value for key from /etc/os-release
189+
190+
/etc/os-release is a bash file, so should use bash to parse it.
191+
192+
Returns empty string if key is not found.
193+
"""
194+
return (
195+
subprocess.check_output(
196+
[
197+
"/bin/bash",
198+
"-c",
199+
"source /etc/os-release && echo ${{{key}}}".format(key=key),
200+
]
201+
)
202+
.decode()
203+
.strip()
204+
)
205+
206+
186207
def ensure_host_system_can_install_tljh():
187208
"""
188209
Check if TLJH is installable in current host system and exit with a clear
189210
error message otherwise.
190211
"""
191-
192-
def get_os_release_variable(key):
193-
"""
194-
Return value for key from /etc/os-release
195-
196-
/etc/os-release is a bash file, so should use bash to parse it.
197-
198-
Returns empty string if key is not found.
199-
"""
200-
return (
201-
subprocess.check_output(
202-
[
203-
"/bin/bash",
204-
"-c",
205-
"source /etc/os-release && echo ${{{key}}}".format(key=key),
206-
]
207-
)
208-
.decode()
209-
.strip()
210-
)
211-
212212
# Require Ubuntu 20.04+ or Debian 11+
213213
distro = get_os_release_variable("ID")
214214
version = get_os_release_variable("VERSION_ID")
@@ -364,7 +364,7 @@ def main():
364364
)
365365
parser.add_argument(
366366
"--version",
367-
default="latest",
367+
default="",
368368
help=(
369369
"TLJH version or Git reference. "
370370
"Default 'latest' is the most recent release. "
@@ -478,21 +478,26 @@ def serve_forever(server):
478478
logger.info("Upgrading pip...")
479479
run_subprocess([hub_env_pip, "install", "--upgrade", "pip"])
480480

481-
# Install/upgrade TLJH installer
481+
# pip install TLJH installer based on
482+
#
483+
# 1. --version, _resolve_git_version is used
484+
# 2. TLJH_BOOTSTRAP_PIP_SPEC (then also respect TLJH_BOOTSTRAP_DEV)
485+
# 3. latest, _resolve_git_version is used
486+
#
482487
tljh_install_cmd = [hub_env_pip, "install", "--upgrade"]
483-
if os.environ.get("TLJH_BOOTSTRAP_DEV", "no") == "yes":
484-
logger.info("Selected TLJH_BOOTSTRAP_DEV=yes...")
485-
tljh_install_cmd.append("--editable")
486-
487488
bootstrap_pip_spec = os.environ.get("TLJH_BOOTSTRAP_PIP_SPEC")
488-
if not bootstrap_pip_spec:
489+
if args.version or not bootstrap_pip_spec:
490+
version_to_resolve = args.version or "latest"
489491
bootstrap_pip_spec = (
490492
"git+https://github.com/jupyterhub/the-littlest-jupyterhub.git@{}".format(
491-
_resolve_git_version(args.version)
493+
_resolve_git_version(version_to_resolve)
492494
)
493495
)
494-
496+
elif os.environ.get("TLJH_BOOTSTRAP_DEV", "no") == "yes":
497+
logger.info("Selected TLJH_BOOTSTRAP_DEV=yes...")
498+
tljh_install_cmd.append("--editable")
495499
tljh_install_cmd.append(bootstrap_pip_spec)
500+
496501
if initial_setup:
497502
logger.info("Installing TLJH installer...")
498503
else:

dev-requirements.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
packaging
22
pytest
33
pytest-cov
4+
pytest-asyncio
45
pytest-mock

integration-tests/Dockerfile

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,6 @@ RUN find /etc/systemd/system \
2424
-not -name '*systemd-user-sessions*' \
2525
-exec rm \{} \;
2626

27-
RUN mkdir -p /etc/sudoers.d
28-
2927
RUN systemctl set-default multi-user.target
3028

3129
STOPSIGNAL SIGRTMIN+3
Lines changed: 12 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,55 +1,47 @@
11
"""
2-
Simplest plugin that exercises all the hooks
2+
Simplest plugin that exercises all the hooks defined in tljh/hooks.py.
33
"""
44
from tljh.hooks import hookimpl
55

66

77
@hookimpl
88
def tljh_extra_user_conda_packages():
9-
return [
10-
"hypothesis",
11-
]
9+
return ["tqdm"]
1210

1311

1412
@hookimpl
1513
def tljh_extra_user_pip_packages():
16-
return [
17-
"django",
18-
]
14+
return ["django"]
1915

2016

2117
@hookimpl
2218
def tljh_extra_hub_pip_packages():
23-
return [
24-
"there",
25-
]
19+
return ["there"]
2620

2721

2822
@hookimpl
2923
def tljh_extra_apt_packages():
30-
return [
31-
"sl",
32-
]
24+
return ["sl"]
3325

3426

3527
@hookimpl
36-
def tljh_config_post_install(config):
37-
# Put an arbitrary marker we can test for
38-
config["simplest_plugin"] = {"present": True}
28+
def tljh_custom_jupyterhub_config(c):
29+
c.Test.jupyterhub_config_set_by_simplest_plugin = True
3930

4031

4132
@hookimpl
42-
def tljh_custom_jupyterhub_config(c):
43-
c.JupyterHub.authenticator_class = "tmpauthenticator.TmpAuthenticator"
33+
def tljh_config_post_install(config):
34+
config["Test"] = {"tljh_config_set_by_simplest_plugin": True}
4435

4536

4637
@hookimpl
4738
def tljh_post_install():
48-
with open("test_post_install", "w") as f:
49-
f.write("123456789")
39+
with open("test_tljh_post_install", "w") as f:
40+
f.write("file_written_by_simplest_plugin")
5041

5142

5243
@hookimpl
5344
def tljh_new_user_create(username):
5445
with open("test_new_user_create", "w") as f:
46+
f.write("file_written_by_simplest_plugin")
5547
f.write(username)

integration-tests/requirements.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
pytest
2+
pytest-cov
23
pytest-asyncio
34
git+https://github.com/yuvipanda/hubtraf.git

0 commit comments

Comments
 (0)