8000 Re-enable CI tests (#1760) · pyscript/pyscript@c6aaacd · GitHub
[go: up one dir, main page]

Skip to content

Commit c6aaacd

Browse files
authored
Re-enable CI tests (#1760)
This re-enables CI tests on every PR 🎉. This uses make test-integration, which runs tests sequentially. In theory, we also have test-integration-parallel but it seems to be very flaky: many tests randomly timeout. I didn't spend too much time investigating this, it's probably worth its own investigation in a separate PR, but for now it's important to re-enable CI tests, even if they are a bit slower.
1 parent abfc687 commit c6aaacd

File tree

8 files changed

+141
-52
lines changed

8 files changed

+141
-52
lines changed

.github/workflows/test.yml

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
name: "[CI] Test"
2+
3+
on:
4+
push: # Only run on merges into main that modify certain files
5+
branches:
6+
- main
7+
paths 8000 :
8+
- pyscript.core/**
9+
- .github/workflows/test.yml
10+
11+
pull_request: # Only run on merges into main that modify certain files
12+
branches:
13+
- main
14+
paths:
15+
- pyscript.core/**
16+
- .github/workflows/test.yml
17+
workflow_dispatch:
18+
19+
jobs:
20+
BuildAndTest:
21+
runs-on: ubuntu-latest-8core
22+
env:
23+
MINICONDA_PYTHON_VERSION: py38
24+
MINICONDA_VERSION: 4.11.0
25+
steps:
26+
- name: Checkout
27+
uses: actions/checkout@v4
28+
with:
29+
fetch-depth: 3
30+
31+
# display a git log: when you run CI on PRs, github automatically
32+
# merges the PR into main and run the CI on that commit. The idea
33+
# here is to show enough of git log to understand what is the
34+
# actual commit (in the PR) that we are using. See also
35+
# 'fetch-depth: 3' above.
36+
- name: git log
37+
run: git log --graph -3
38+
39+
- name: Install node
40+
uses: actions/setup-node@v3
41+
with:
42+
node-version: 20.x
43+
44+
- name: Cache node modules
45+
uses: actions/cache@v3
46+
env:
47+
cache-name: cache-node-modules
48+
with:
49+
# npm cache files are stored in `~/.npm` on Linux/macOS
50+
path: ~/.npm
51+
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/package-lock.json') }}
52+
restore-keys: |
53+
${{ runner.os }}-build-${{ env.cache-name }}-
54+
${{ runner.os }}-build-
55+
${{ runner.os }}-
56+
57+
- name: setup Miniconda
58+
uses: conda-incubator/setup-miniconda@v2
59+
60+
- name: Setup Environment
61+
run: make setup
62+
63+
- name: Build
64+
run: make build
65+
66+
- name: Integration Tests
67+
#run: make test-integration-parallel
68+
run: make test-integration
69+
70+
- uses: actions/upload-artifact@v3
71+
with:
72+
name: pyscript
73+
path: |
74+
pyscript.core/dist/
75+
if-no-files-found: error
76+
retention-days: 7
77+
78+
- uses: actions/upload-artifact@v3
79+
if: success() || failure()
80+
with:
81+
name: test_results
82+
path: test_results/
83+
if-no-files-found: error

.github/workflows/test_report.yml

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
name: Test Report
2+
on:
3+
workflow_run:
4+
workflows: ['\[CI\] Test']
5+
types:
6+
- completed
7+
jobs:
8+
report:
9+
runs-on: ubuntu-latest-8core
10+
steps:
11+
- uses: dorny/test-reporter@v1.6.0
12+
with:
13+
artifact: test_results
14+
name: Test reports
15+
path: "*.xml"
16+
reporter: java-junit

Makefile

Lines changed: 18 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,13 @@ examples ?= ../$(base_dir)/examples
77
app_dir ?= $(shell git rev-parse --show-prefix)
88

99
CONDA_EXE := conda
10-
CONDA_ENV ?= $(base_dir)/pyscriptjs/env
10+
CONDA_ENV ?= $(base_dir)/env
1111
env := $(CONDA_ENV)
1212
conda_run := $(CONDA_EXE) run -p $(env)
1313
PYTEST_EXE := $(CONDA_ENV)/bin/pytest
14-
GOOD_NODE_VER := 14
15-
GOOD_NPM_VER := 6
14+
15+
MIN_NODE_VER := 14
16+
MIN_NPM_VER := 6
1617
NODE_VER := $(shell node -v | cut -d. -f1 | sed 's/^v\(.*\)/\1/')
1718
NPM_VER := $(shell npm -v | cut -d. -f1)
1819

@@ -22,20 +23,21 @@ else
2223
SED_I_ARG := -i
2324
endif
2425

25-
GOOD_NODE := $(shell if [ $(NODE_VER) -ge $(GOOD_NODE_VER) ]; then echo true; else echo false; fi)
26-
GOOD_NPM := $(shell if [ $(NPM_VER) -ge $(GOOD_NPM_VER) ]; then echo true; else echo false; fi)
27-
2826
.PHONY: check-node
2927
check-node:
30-
@echo Build requires Node $(GOOD_NODE_VER).x or higher: $(NODE_VER) detected && $(GOOD_NODE)
28+
@if [ $(NODE_VER) -lt $(MIN_NODE_VER) ]; then \
29+
echo "Build requires Node $(MIN_NODE_VER).x or higher: $(NODE_VER) detected"; \
30+
false; \
31+
fi
3132

3233
.PHONY: check-npm
3334
check-npm:
34-
@echo Build requires npm $(GOOD_NPM_VER).x or higher: $(NPM_VER) detected && $(GOOD_NPM)
35+
@if [ $(NPM_VER) -lt $(MIN_NPM_VER) ]; then \
36+
echo "Build requires Node $(MIN_NPM_VER).x or higher: $(NPM_VER) detected"; \
37+
false; \
38+
fi
3539

36-
setup:
37-
make check-node
38-
make check-npm
40+
setup: check-node check-npm
3941
cd pyscript.core && npm install && cd ..
4042
$(CONDA_EXE) env $(shell [ -d $(env) ] && echo update || echo create) -p $(env) --file environment.yml
4143
$(conda_run) playwright install
@@ -53,13 +55,10 @@ shell:
5355
@echo 'conda activate $(env)'
5456

5557
dev:
56-
npm run dev
58+
cd pyscript.core && npm run dev
5759

5860
build:
59-
npm run build
60-
61-
build-fast:
62-
node esbuild.mjs
61+
cd pyscript.core && npm run build
6362

6463
# use the following rule to do all the checks done by precommit: in
6564
# particular, use this if you want to run eslint.
@@ -85,27 +84,22 @@ run-examples: setup build examples
8584
npm install
8685
make dev
8786

88-
test:
89-
cd pyscript.core && npm run build && cp -R dist ../pyscriptjs/build/
90-
make test-integration
91-
make test-examples
92-
9387
# run all integration tests *including examples* sequentially
9488
# TODO: (fpliger) The cd pyscript.core before running the tests shouldn't be needed but for
9589
# but for some reason it seems to bother pytest tmppaths (or test cache?). Unclear.
9690
test-integration:
9791
mkdir -p test_results
98-
cd pyscript.core && $(PYTEST_EXE) -vv $(ARGS) tests/integration/ --log-cli-level=warning --junitxml=../integration.xml
92+
$(PYTEST_EXE) -vv $(ARGS) pyscript.core/tests/integration/ --log-cli-level=warning --junitxml=test_results/integration.xml
9993

10094
# run all integration tests *except examples* in parallel (examples use too much memory)
10195
test-integration-parallel:
10296
mkdir -p test_results
103-
$(PYTEST_EXE) --numprocesses auto -vv $(ARGS) pyscript/tests/integration/ --log-cli-level=warning --junitxml=test_results/integration.xml -k 'not zz_examples'
97+
$(PYTEST_EXE) --numprocesses auto -vv $(ARGS) pyscript.core/tests/integration/ --log-cli-level=warning --junitxml=test_results/integration.xml
10498

10599
# run integration tests on only examples sequentially (to avoid running out of memory)
106100
test-examples:
107101
mkdir -p test_results
108-
$(PYTEST_EXE) -vv $(ARGS) pyscript/tests/integration/ --log-cli-level=warning --junitxml=test_results/integration.xml -k 'zz_examples'
102+
$(PYTEST_EXE) -vv $(ARGS) pyscript.core/tests/integration/ --log-cli-level=warning --junitxml=test_results/integration.xml -k 'zz_examples'
109103

110104
test-py:
111105
@echo "Tests from $(src_dir)"
File renamed without changes.

pyscript.core/tests/integration/support.py

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,7 @@ class PyScriptTest:
169169
creates an HTML page to run the specified snippet.
170170
"""
171171

172-
DEFAULT_TIMEOUT = 20000
172+
DEFAULT_TIMEOUT = 30 * 1000
173173

174174
@pytest.fixture()
175175
def init(self, request, tmpdir, logger, page, execution_thread):
@@ -240,10 +240,7 @@ def init(self, request, tmpdir, logger, page, execution_thread):
240240

241241
def init_page(self, page):
242242
self.page = page
243-
244-
# set default timeout to 60000 millliseconds from 30000
245243
page.set_default_timeout(self.DEFAULT_TIMEOUT)
246-
247244
self.console = ConsoleMessageCollection(self.logger)
248245
self._js_errors = []
249246
self._py_errors = []
@@ -424,7 +421,7 @@ def find_text():
424421
return text in self.console.all.lines
425422

426423
if timeout is None:
427-
timeout = 10 * 1000
424+
timeout = self.DEFAULT_TIMEOUT
428425
# NOTE: we cannot use playwright's own page.expect_console_message(),
429426
# because if you call it AFTER the text has already been emitted, it
430427
# waits forever. Instead, we have to use our own custom logic.

pyscript.core/tests/integration/test_01_basic.py

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -11,26 +11,22 @@ def test_script_py_hello(self):
1111
"""
1212
<script type="py">
1313
import js
14-
js.console.log('1. hello from script py')
14+
js.console.log('hello from script py')
1515
</script>
16+
"""
17+
)
18+
assert self.console.log.lines == ["hello from script py"]
1619

20+
def test_py_script_hello(self):
21+
self.pyscript_run(
22+
"""
1723
<py-script>
1824
import js
19-
js.console.log('2. hello from py-script')
25+
js.console.log('hello from py-script')
2026
</py-script>
2127
"""
2228
)
23-
if self.execution_thread == "main":
24-
# in main, the order of execution is guaranteed
25-
assert self.console.log.lines == [
26-
"1. hello from script py",
27-
"2. hello from py-script",
28-
]
29-
else:
30-
# in workers, each tag is executed by its own worker, so they can
31-
# come out of order
32-
lines = sorted(self.console.log.lines)
33-
assert lines == ["1. hello from script py", "2. hello from py-script"]
29+
assert self.console.log.lines == ["hello from py-script"]
3430

3531
def test_execution_thread(self):
3632
self.pyscript_run(
@@ -47,20 +43,25 @@ def test_execution_thread(self):
4743
in_worker = str(in_worker).lower()
4844
assert self.console.log.lines[-1] == f"worker? {in_worker}"
4945

50-
# TODO: if there's no py-script there are surely no plugins neither
51-
# this test must be discussed or rewritten to make sense now
52-
@pytest.mark.skip(reason="NEXT: No banner and should also add a WARNING about CORS")
46+
@skip_worker('NEXT: it should show a nice error on the page')
5347
def test_no_cors_headers(self):
5448
self.disable_cors_headers()
5549
self.pyscript_run(
5650
"""
57-
<!-- we don't really need anything here, we just want to check that
58-
pyscript starts -->
51+
<script type="py">
52+
import js
53+
js.console.log("hello")
54+
</script>
5955
""",
6056
wait_for_pyscript=False,
6157
)
6258
assert self.headers == {}
63-
if self.execution_thread == "worker":
59+
if self.execution_thread == "main":
60+
self.wait_for_pyscript()
61+
assert self.console.log.lines == ['hello']
62+
self.assert_no_banners()
63+
else:
64+
# XXX adapt and fix the test
6465
expected_alert_banner_msg = (
6566
'(PY1000): When execution_thread is "worker", the site must be cross origin '
6667
"isolated, but crossOriginIsolated is false. To be cross origin isolated, "
@@ -71,8 +72,7 @@ def test_no_cors_headers(self):
7172
)
7273
alert_banner = self.page.wait_for_selector(".alert-banner")
7374
assert expected_alert_banner_msg in alert_banner.inner_text()
74-
else:
75-
self.assert_no_banners()
75+
7676

7777
def test_print(self):
7878
self.pyscript_run(

pyscript.core/tests/integration/test_02_display.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -457,7 +457,7 @@ def test_image_renders_correctly(self):
457457
img = Image.new("RGB", (4, 4), color=(0, 0, 0))
458458
display(img, target='img-target', append=False)
459459
</script>
460-
"""
460+
""",
461461
)
462462

463463
img_src = self.page.locator("img").get_attribute("src")

pyscript.core/tests/integration/test_py_config.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,6 @@ def test_py_config_external(self):
6767
)
6868
assert self.console.log.lines[-1] == "config name: app with external config"
6969

70-
@pytest.mark.skip("NEXT: We need to restore the banner.")
7170
def test_invalid_json_config(self):
7271
# we need wait_for_pyscript=False because we bail out very soon,
7372
# before being able to write 'PyScript page fully initialized'

0 commit comments

Comments
 (0)
0