Skip to content

Commit e510f43

Browse files
authored
test: add network mocking for example tests (#16)
* chore: update lockfile * ci: update actions * test: add network mocking for example tests - Add responses library for HTTP mocking - Mock StackOne API calls in tests instead of skipping - Import and execute examples directly to enable mocking - Skip only when optional dependencies are missing * fix: resolve linting issues - Remove unused imports (os, Any) - Remove trailing whitespace - Remove whitespace from blank lines
1 parent 3b213e6 commit e510f43

File tree

7 files changed

+1687
-1624
lines changed

7 files changed

+1687
-1624
lines changed

.github/workflows/docs.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,10 @@ jobs:
1212
deploy:
1313
runs-on: ubuntu-latest
1414
steps:
15-
- uses: actions/checkout@v4
15+
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
1616

1717
- name: Install uv
18-
uses: astral-sh/setup-uv@v4
18+
uses: astral-sh/setup-uv@e92bafb6253dcd438e0484186d7669ea7a8ca1cc # v6.4.3
1919
with:
2020
python-version: "3.11"
2121
enable-cache: true
@@ -30,7 +30,7 @@ jobs:
3030
3131
- name: Deploy to GitHub Pages
3232
if: github.ref == 'refs/heads/main'
33-
uses: peaceiris/actions-gh-pages@v3
33+
uses: peaceiris/actions-gh-pages@4f9cc6602d3f66b9c108549d475ec49e8ef4d45e # v4.0.0
3434
with:
3535
github_token: ${{ secrets.GITHUB_TOKEN }}
3636
publish_dir: ./site

.github/workflows/lint.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,10 @@ jobs:
99
lint:
1010
runs-on: ubuntu-latest
1111
steps:
12-
- uses: actions/checkout@v4
12+
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
1313

1414
- name: Install uv
15-
uses: astral-sh/setup-uv@v5
15+
uses: astral-sh/setup-uv@e92bafb6253dcd438e0484186d7669ea7a8ca1cc # v6.4.3
1616
with:
1717
python-version: "3.11"
1818
enable-cache: true
@@ -21,7 +21,7 @@ jobs:
2121
run: uv sync --all-extras
2222

2323
- name: Run Ruff
24-
uses: astral-sh/ruff-action@v3
24+
uses: astral-sh/ruff-action@0c50076f12c38c3d0115b7b519b54a91cb9cf0ad # v3.5.0
2525
with:
2626
args: check .
2727

.github/workflows/release.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,19 +13,19 @@ jobs:
1313
release-please:
1414
runs-on: ubuntu-latest
1515
steps:
16-
- uses: google-github-actions/release-please-action@v4
16+
- uses: google-github-actions/release-please-action@e4dc86ba9405554aeba3c6bb2d169500e7d3b4ee # v4.1.1
1717
id: release
1818
with:
1919
config-file: .release-please-config.json
2020
manifest-file: .release-please-manifest.json
2121

2222
# Only release to PyPI when a new release is created
23-
- uses: actions/checkout@v4
23+
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
2424
if: ${{ steps.release.outputs.release_created }}
2525

2626
- name: Install uv
2727
if: ${{ steps.release.outputs.release_created }}
28-
uses: astral-sh/setup-uv@v5
28+
uses: astral-sh/setup-uv@e92bafb6253dcd438e0484186d7669ea7a8ca1cc # v6.4.3
2929
with:
3030
python-version: "3.11"
3131
enable-cache: true

.github/workflows/test.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,10 @@ jobs:
1212
STACKONE_API_KEY: ${{ secrets.STACKONE_API_KEY }}
1313
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
1414
steps:
15-
- uses: actions/checkout@v4
15+
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
1616

1717
- name: Install uv
18-
uses: astral-sh/setup-uv@v5
18+
uses: astral-sh/setup-uv@e92bafb6253dcd438e0484186d7669ea7a8ca1cc # v6.4.3
1919
with:
2020
python-version: "3.11"
2121
enable-cache: true

examples/test_examples.py

Lines changed: 54 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
1-
import subprocess
1+
import importlib.util
22
import sys
33
from pathlib import Path
44

55
import pytest
6+
import responses
67

78

89
def get_example_files() -> list[str]:
@@ -21,19 +22,64 @@ def get_example_files() -> list[str]:
2122

2223
EXAMPLES = get_example_files()
2324

25+
# Map of example files to required optional packages
26+
OPTIONAL_DEPENDENCIES = {
27+
"openai_integration.py": ["openai"],
28+
"langchain_integration.py": ["langchain_openai"],
29+
"crewai_integration.py": ["crewai"],
30+
}
2431

25-
def test_example_files_exist():
32+
33+
def test_example_files_exist() -> None:
2634
"""Verify that we found example files to test"""
2735
assert len(EXAMPLES) > 0, "No example files found"
2836
print(f"Found {len(EXAMPLES)} examples")
2937

3038

3139
@pytest.mark.parametrize("example_file", EXAMPLES)
32-
def test_run_example(example_file):
40+
@responses.activate
41+
def test_run_example(example_file: str) -> None:
3342
"""Run each example file directly using python"""
43+
# Skip if optional dependencies are not available
44+
if example_file in OPTIONAL_DEPENDENCIES:
45+
for module in OPTIONAL_DEPENDENCIES[example_file]:
46+
try:
47+
__import__(module)
48+
except ImportError:
49+
pytest.skip(f"Skipping {example_file}: {module} not installed")
50+
51+
# Setup mock responses for examples that need them
52+
if example_file in ["index.py", "file_uploads.py"]:
53+
# Mock employee list endpoint
54+
responses.add(
55+
responses.GET,
56+
"https://api.stackone.com/unified/hris/employees",
57+
json={
58+
"data": [
59+
{
60+
"id": "test-employee-1",
61+
"first_name": "John",
62+
"last_name": "Doe",
63+
"email": "[email protected]"
64+
}
65+
]
66+
},
67+
status=200
68+
)
69+
70+
# Mock document upload endpoint
71+
responses.add(
72+
responses.POST,
73+
"https://api.stackone.com/unified/hris/employees/c28xIQaWQ6MzM5MzczMDA2NzMzMzkwNzIwNA/documents/upload",
74+
json={"success": True, "document_id": "test-doc-123"},
75+
status=200
76+
)
77+
3478
example_path = Path(__file__).parent / example_file
35-
result = subprocess.run([sys.executable, str(example_path)], capture_output=True, text=True)
36-
if result.returncode != 0:
37-
print(f"stdout: {result.stdout}")
38-
print(f"stderr: {result.stderr}")
39-
pytest.fail(f"Example {example_file} failed with return code {result.returncode}")
79+
80+
# Import and run the example module directly
81+
spec = importlib.util.spec_from_file_location("example", example_path)
82+
if spec and spec.loader:
83+
module = importlib.util.module_from_spec(spec)
84+
sys.modules["example"] = module
85+
spec.loader.exec_module(module)

pyproject.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ dev = [
5959
"pytest-asyncio>=0.25.3",
6060
"pytest-cov>=6.0.0",
6161
"pytest-snapshot>=0.9.0",
62+
"responses>=0.25.8",
6263
"ruff>=0.9.6",
6364
"stackone-ai",
6465
"types-requests>=2.31.0.20240311",

0 commit comments

Comments
 (0)