Skip to content

Commit 7cbb682

Browse files
authored
Improve test speed (#445)
1 parent 7977e0e commit 7cbb682

File tree

8 files changed

+60
-43
lines changed

8 files changed

+60
-43
lines changed

.github/workflows/test.yml

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ defaults:
88
run:
99
shell: bash -eux {0}
1010

11+
env:
12+
PYTHONDONTWRITEBYTECODE: 1
13+
1114
jobs:
1215
# Run "pre-commit run --all-files --hook-stage=manual"
1316
pre-commit:
@@ -51,13 +54,13 @@ jobs:
5154
- name: Run the tests with coverage on Ubuntu
5255
if: ${{ matrix.os == 'ubuntu-latest' }}
5356
run: |
54-
hatch run cov:test
57+
hatch run cov:test -n auto || hatch run test:test --lf
5558
pip install codecov
5659
codecov
5760
5861
- name: Run the tests on Windows and MacOS
5962
if: ${{ matrix.os != 'ubuntu-latest' }}
60-
run: hatch run test:test -s
63+
run: hatch run test:test -s -n auto || hatch run test:test -s --lf
6164

6265
generate-changelog:
6366
runs-on: ubuntu-20.04

jupyter_releaser/lib.py

Lines changed: 14 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,8 @@ def populate_release(
248248

249249
def delete_release(auth, release_url, dry_run=False):
250250
"""Delete a draft GitHub release by url to the release page"""
251-
match = re.match(util.RELEASE_HTML_PATTERN, release_url)
251+
pattern = util.RELEASE_HTML_PATTERN % util.get_mock_github_url()
252+
match = re.match(pattern, release_url)
252253
match = match or re.match(util.RELEASE_API_PATTERN, release_url)
253254
if not match:
254255
raise ValueError(f"Release url is not valid: {release_url}")
@@ -409,21 +410,6 @@ def prep_git(ref, branch, repo, auth, username, url):
409410
"""Set up git"""
410411
repo = repo or util.get_repo()
411412

412-
try:
413-
util.run("git config --global user.email")
414-
has_git_config = True
415-
except Exception:
416-
has_git_config = False
417-
418-
if not has_git_config:
419-
# Default to the GitHub Actions bot
420-
# https://github.community/t/github-actions-bot-email-address/17204/6
421-
git_user_name = username or "41898282+github-actions[bot]"
422-
util.run(
423-
f'git config --global user.email "{git_user_name}@users.noreply.github.com"', echo=True
424-
)
425-
util.run(f'git config --global user.name "{git_user_name}"', echo=True)
426-
427413
# Set up the repository
428414
checkout_dir = os.environ.get("RH_CHECKOUT_DIR", util.CHECKOUT_NAME)
429415
checkout_exists = False
@@ -504,6 +490,18 @@ def prep_git(ref, branch, repo, auth, username, url):
504490
elif util.PACKAGE_JSON.exists():
505491
util.run("npm install")
506492

493+
try:
494+
has_git_config = util.run("git config user.email").strip()
495+
except Exception:
496+
has_git_config = False
497+
498+
if not has_git_config:
499+
# Default to the GitHub Actions bot
500+
# https://github.community/t/github-actions-bot-email-address/17204/6
501+
git_user_name = username or "41898282+github-actions[bot]"
502+
util.run(f'git config user.email "{git_user_name}@users.noreply.github.com"', echo=True)
503+
util.run(f'git config user.name "{git_user_name}"', echo=True)
504+
507505
os.chdir(orig_dir)
508506

509507
return branch

jupyter_releaser/mock_github.py

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
from fastapi.staticfiles import StaticFiles
1111
from pydantic import BaseModel
1212

13-
from jupyter_releaser.util import MOCK_GITHUB_URL
13+
from jupyter_releaser.util import get_mock_github_url
1414

1515
app = FastAPI()
1616

@@ -131,9 +131,10 @@ async def create_a_release(owner: str, repo: str, request: Request) -> Release:
131131
"""https://docs.github.com/en/rest/releases/releases#create-a-release"""
132132
release_id = uuid.uuid4().int
133133
data = await request.json()
134-
url = f"{MOCK_GITHUB_URL}/repos/{owner}/{repo}/releases/{release_id}"
135-
html_url = f"{MOCK_GITHUB_URL}/{owner}/{repo}/releases/tag/{data['tag_name']}"
136-
upload_url = f"{MOCK_GITHUB_URL}/repos/{owner}/{repo}/releases/{release_id}/assets"
134+
base_url = get_mock_github_url()
135+
url = f"{base_url}/repos/{owner}/{repo}/releases/{release_id}"
136+
html_url = f"{base_url}/{owner}/{repo}/releases/tag/{data['tag_name']}"
137+
upload_url = f"{base_url}/repos/{owner}/{repo}/releases/{release_id}/assets"
137138
fmt_str = r"%Y-%m-%dT%H:%M:%SZ"
138139
created_at = datetime.datetime.utcnow().strftime(fmt_str)
139140
model = Release(
@@ -164,14 +165,15 @@ async def update_a_release(owner: str, repo: str, release_id: int, request: Requ
164165
@app.post("/repos/{owner}/{repo}/releases/{release_id}/assets")
165166
async def upload_a_release_asset(owner: str, repo: str, release_id: int, request: Request) -> None:
166167
"""https://docs.github.com/en/rest/releases/assets#upload-a-release-asset"""
168+
base_url = get_mock_github_url()
167169
model = releases[str(release_id)]
168170
asset_id = uuid.uuid4().int
169171
name = request.query_params["name"]
170172
with open(f"{static_dir}/{asset_id}", "wb") as fid:
171173
async for chunk in request.stream():
172174
fid.write(chunk)
173175
headers = request.headers
174-
url = f"{MOCK_GITHUB_URL}/static/{asset_id}"
176+
url = f"{base_url}/static/{asset_id}"
175177
asset = Asset(
176178
id=asset_id,
177179
name=name,

jupyter_releaser/python.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ def get_pypi_token(release_url, python_package):
9999
pypi_token_map = os.environ.get("PYPI_TOKEN_MAP", "").replace(r"\n", "\n")
100100
if pypi_token_map and release_url:
101101
parts = (
102-
release_url.replace(util.MOCK_GITHUB_URL + "/", "")
102+
release_url.replace(util.get_mock_github_url() + "/", "")
103103
.replace("https://github.com/", "")
104104
.split("/")
105105
)

jupyter_releaser/tests/conftest.py

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,15 @@
1717
from jupyter_releaser.util import ensure_mock_github, run
1818

1919

20+
@fixture(autouse=True)
21+
def github_port(worker_id):
22+
# The worker id will be of the form "gw123" unless xdist is disabled,
23+
# in which case it will be "master".
24+
if worker_id == "master":
25+
return
26+
os.environ["MOCK_GITHUB_PORT"] = str(8000 + int(worker_id[2:]))
27+
28+
2029
@fixture(autouse=True)
2130
def mock_env(mocker):
2231
"""Clear unwanted environment variables"""
@@ -29,13 +38,6 @@ def mock_env(mocker):
2938
del env[key]
3039

3140
mocker.patch.dict(os.environ, env, clear=True)
32-
33-
try:
34-
run("git config --global user.name")
35-
except Exception:
36-
run("git config --global user.name snuffy")
37-
run("git config --global user.email [email protected]")
38-
3941
yield
4042

4143

jupyter_releaser/tests/test_cli.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -94,18 +94,19 @@ def test_prep_git_full(py_package, tmp_path, mocker, runner):
9494
os.mkdir(util.CHECKOUT_NAME)
9595

9696
runner(["prep-git"], env=env)
97-
9897
mock_run.assert_has_calls(
9998
[
10099
call("echo before-prep-git >> 'log.txt'"),
101-
call("git config --global user.email"),
102100
call("git init .jupyter_releaser_checkout"),
103101
call("git remote add origin https://snuffy:[email protected]/baz/bar.git"),
104102
call(f"{GIT_FETCH_CMD} --tags --force"),
105103
call(f"{GIT_FETCH_CMD} +refs/pull/42:refs/pull/42"),
106104
call(f"{GIT_FETCH_CMD} refs/pull/42"),
107105
call("git checkout -B foo refs/pull/42"),
108106
call("git symbolic-ref -q HEAD"),
107+
call("git config user.email"),
108+
call('git config user.email "[email protected]"', echo=True),
109+
call('git config user.name "snuffy"', echo=True),
109110
]
110111
)
111112

jupyter_releaser/util.py

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
from io import BytesIO
2121
from pathlib import Path
2222
from subprocess import PIPE, CalledProcessError, check_output
23+
from urllib.parse import urlparse
2324

2425
import requests
2526
import toml
@@ -45,14 +46,13 @@
4546
TBUMP_CMD = "pipx run tbump --non-interactive --only-patch"
4647

4748
CHECKOUT_NAME = ".jupyter_releaser_checkout"
48-
49-
MOCK_GITHUB_URL = "http://127.0.0.1:8000"
50-
RELEASE_HTML_PATTERN = f"(?:https://github.com|{MOCK_GITHUB_URL})/(?P<owner>[^/]+)/(?P<repo>[^/]+)/releases/tag/(?P<tag>.*)"
49+
RELEASE_HTML_PATTERN = (
50+
"(?:https://github.com|%s)/(?P<owner>[^/]+)/(?P<repo>[^/]+)/releases/tag/(?P<tag>.*)"
51+
)
5152
RELEASE_API_PATTERN = (
5253
"https://api.github.com/repos/(?P<owner>[^/]+)/(?P<repo>[^/]+)/releases/tags/(?P<tag>.*)"
5354
)
5455

55-
5656
SCHEMA = files("jupyter_releaser").joinpath("schema.json").read_text()
5757
SCHEMA = json.loads(SCHEMA)
5858

@@ -468,7 +468,8 @@ def read_config():
468468

469469
def parse_release_url(release_url):
470470
"""Parse a release url into a regex match"""
471-
match = re.match(RELEASE_HTML_PATTERN, release_url)
471+
pattern = RELEASE_HTML_PATTERN % get_mock_github_url()
472+
match = re.match(pattern, release_url)
472473
match = match or re.match(RELEASE_API_PATTERN, release_url)
473474
if not match:
474475
raise ValueError(f"Release url is not valid: {release_url}")
@@ -686,13 +687,20 @@ def get_remote_name(dry_run):
686687
return "test"
687688

688689

690+
def get_mock_github_url():
691+
port = os.environ.get("MOCK_GITHUB_PORT", "8000")
692+
return f"http://127.0.0.1:{port}"
693+
694+
689695
def ensure_mock_github():
690696
"""Check for or start a mock github server."""
691-
core.GH_HOST = MOCK_GITHUB_URL
697+
core.GH_HOST = host = get_mock_github_url()
698+
port = urlparse(host).port
699+
692700
log("Ensuring mock GitHub")
693701
# First see if it is already running.
694702
try:
695-
requests.get(MOCK_GITHUB_URL)
703+
requests.get(host)
696704
return
697705
except requests.ConnectionError:
698706
pass
@@ -705,7 +713,9 @@ def ensure_mock_github():
705713
except ImportError:
706714
run(f"'{python}' -m pip install fastapi uvicorn")
707715

708-
proc = subprocess.Popen([python, "-m", "uvicorn", "jupyter_releaser.mock_github:app"])
716+
proc = subprocess.Popen(
717+
[python, "-m", "uvicorn", "jupyter_releaser.mock_github:app", "--port", str(port)]
718+
)
709719

710720
try:
711721
ret = proc.wait(1)
@@ -718,7 +728,7 @@ def ensure_mock_github():
718728

719729
while 1:
720730
try:
721-
requests.get(MOCK_GITHUB_URL)
731+
requests.get(host)
722732
break
723733
except requests.ConnectionError:
724734
pass

pyproject.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ test = [
5858
"pytest>=7.0",
5959
"pytest-cov",
6060
"pytest-mock",
61+
"pytest-xdist[psutil]",
6162
"uvicorn"
6263
]
6364

@@ -94,7 +95,7 @@ after-populate-release = "bash ./.github/scripts/bump_tag.sh"
9495
post-version-spec = "dev"
9596

9697
[tool.pytest.ini_options]
97-
addopts = "-raXs --durations 10 --color=yes --doctest-modules"
98+
addopts = "-raXs --durations 10 --color=yes --doctest-modules -p no:pastebin -p no:nose"
9899
testpaths = [
99100
"jupyter_releaser/tests/"
100101
]

0 commit comments

Comments
 (0)