Skip to content

Commit aff21c8

Browse files
Merge pull request #58 from shruthis4/AWSTest
Add test to execute notebooks
2 parents 6e2a08f + 3467502 commit aff21c8

File tree

3 files changed

+135
-2
lines changed

3 files changed

+135
-2
lines changed

.github/workflows/execute-all-notebooks.yml

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,12 @@ on:
1111
description: "Pull request number or branch name"
1212
required: true
1313
default: "main"
14-
14+
pull_request:
15+
types: [opened, synchronize, reopened]
16+
paths:
17+
- "notebooks/**/*.ipynb"
18+
- ".github/workflows/execute-all-notebooks.yml"
19+
push:
1520
env:
1621
INSTANCE_TYPE: "g6e.xlarge"
1722

@@ -70,6 +75,26 @@ jobs:
7075
run: |
7176
echo "hello. i'm running from inside of EC2 instance ${{ needs.launch-ec2-runner.outputs.ec2-instance-id }}"
7277
78+
- uses: actions/checkout@v5
79+
80+
- name: Set up Python
81+
uses: actions/setup-python@v6
82+
with:
83+
python-version: "3.12"
84+
cache: pip
85+
86+
- name: Install Dependencies
87+
run: |
88+
pip install -r requirements-dev.txt
89+
pip install papermill ipykernel jupyter
90+
ipython kernel install --name "python3" --user
91+
92+
- name: Execute All Notebooks via Pytest
93+
run: |
94+
cd tests
95+
python -m pytest test_notebook_execution.py -v --tb=short
96+
97+
7398
stop-ec2-runner:
7499
permissions:
75100
id-token: write # This is required for OIDC (AWS auth)

Makefile

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
.PHONY: format-python format-notebook format-python-check format-notebooks-check test-notebook-parameters
1+
.PHONY: format-python format-notebook format-python-check format-notebooks-check test-notebook-parameters test-notebook-execution test-kfp-components test-notebooks test-all
22

33
USE_CASES := $(wildcard notebooks/use-cases/*.ipynb)
44
TUTORIALS := $(wildcard notebooks/tutorials/*.ipynb)
@@ -29,3 +29,16 @@ test-notebook-parameters:
2929
@echo "Running notebook parameters validation..."
3030
pytest tests/test_notebook_parameters.py -v
3131
@echo "Notebook parameters test passed :)"
32+
33+
test-notebook-execution:
34+
@echo "Running notebook execution tests..."
35+
pytest tests/test_notebook_execution.py -v
36+
@echo "Notebook execution tests passed :)"
37+
38+
test-notebooks: format-notebooks-check test-notebook-parameters test-notebook-execution
39+
@echo "All notebook validations completed successfully (formatting, parameters, execution) :)"
40+
41+
test-all:
42+
@echo "Running all tests..."
43+
pytest tests/ -v
44+
@echo "All tests passed :)"

tests/test_notebook_execution.py

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
"""
2+
Simple notebook execution tests for CI/CD integration.
3+
4+
This module provides basic notebook execution testing using papermill,
5+
designed to be lightweight and integrate easily with GitHub Actions.
6+
"""
7+
8+
import os
9+
import tempfile
10+
from pathlib import Path
11+
12+
import papermill as pm
13+
import pytest
14+
15+
from conftest import get_notebook_files
16+
17+
18+
def get_test_parameters():
19+
"""Get default test parameters for notebook execution."""
20+
return {
21+
"files": [], # Empty files list for basic testing
22+
"test_mode": True,
23+
"quick_run": True,
24+
}
25+
26+
27+
def execute_single_notebook(notebook_path: Path, timeout: int = 300) -> bool:
28+
"""
29+
Execute a single notebook with papermill.
30+
31+
Args:
32+
notebook_path: Path to notebook to execute
33+
timeout: Execution timeout in seconds
34+
35+
Returns:
36+
True if successful, raises exception if failed
37+
"""
38+
with tempfile.NamedTemporaryFile(suffix='.ipynb', delete=False) as tmp_file:
39+
output_path = Path(tmp_file.name)
40+
41+
try:
42+
pm.execute_notebook(
43+
input_path=str(notebook_path),
44+
output_path=str(output_path),
45+
parameters=get_test_parameters(),
46+
timeout=timeout,
47+
kernel_name="python3"
48+
)
49+
return True
50+
except Exception as e:
51+
raise Exception(f"Notebook execution failed: {str(e)}") from e
52+
finally:
53+
if output_path.exists():
54+
output_path.unlink()
55+
56+
57+
@pytest.mark.parametrize("notebook_path", get_notebook_files())
58+
def test_notebook_executes_without_error(notebook_path):
59+
"""Test that each notebook executes without errors."""
60+
61+
# Skip backup/duplicate files
62+
if any(skip in str(notebook_path) for skip in ["copy.ipynb", ".checkpoint"]):
63+
pytest.skip(f"Skipping backup/checkpoint file: {notebook_path}")
64+
65+
# Execute the notebook
66+
success = execute_single_notebook(notebook_path, timeout=300)
67+
assert success, f"Failed to execute notebook: {notebook_path}"
68+
69+
70+
def test_notebooks_directory_exists():
71+
"""Verify the notebooks directory exists and contains files."""
72+
notebooks = get_notebook_files()
73+
assert len(notebooks) > 0, "No notebook files found in notebooks directory"
74+
75+
for notebook in notebooks:
76+
assert notebook.exists(), f"Notebook file does not exist: {notebook}"
77+
assert notebook.suffix == '.ipynb', f"File is not a notebook: {notebook}"
78+
79+
80+
if __name__ == "__main__":
81+
# Allow running directly for testing
82+
import sys
83+
84+
if len(sys.argv) > 1:
85+
notebook_file = Path(sys.argv[1])
86+
if notebook_file.exists():
87+
print(f"Testing {notebook_file}...")
88+
try:
89+
execute_single_notebook(notebook_file)
90+
print("✅ Success!")
91+
except Exception as e:
92+
print(f"❌ Failed: {e}")
93+
sys.exit(1)
94+
else:
95+
print("Usage: python test_notebook_execution.py <notebook_path>")

0 commit comments

Comments
 (0)