Skip to content

Commit 2cd71e5

Browse files
committed
Add server and HTTP API tests for ArcadeDB Python bindings
- Implemented tests for server creation, database operations, and custom configurations in `test_server.py`. - Added comprehensive access pattern tests, including embedded and HTTP API usage in `test_server_patterns.py`. - Created a script to write version information to `_version.py` during the build process.
1 parent 011c1ea commit 2cd71e5

80 files changed

Lines changed: 28721 additions & 1 deletion

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 179 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,179 @@
1+
name: Test Python Bindings
2+
3+
on:
4+
# Run on any push to any branch
5+
push:
6+
7+
# Run on any pull request
8+
pull_request:
9+
10+
# Allow being called by other workflows (e.g., release workflow)
11+
workflow_call:
12+
13+
# Allow manual trigger
14+
workflow_dispatch:
15+
inputs:
16+
distribution:
17+
description: 'Distribution to test (all, headless, minimal, or full)'
18+
required: false
19+
default: 'all'
20+
type: choice
21+
options:
22+
- all
23+
- headless
24+
- minimal
25+
- full
26+
27+
jobs:
28+
test:
29+
name: Test ${{ matrix.distribution }} distribution
30+
runs-on: ubuntu-latest
31+
strategy:
32+
# Don't cancel other matrix jobs if one fails
33+
fail-fast: false
34+
matrix:
35+
distribution: [headless, minimal, full]
36+
# Filter based on workflow_dispatch input if present
37+
exclude:
38+
- distribution: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.distribution != 'all' && github.event.inputs.distribution != 'headless' && 'headless' || '' }}
39+
- distribution: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.distribution != 'all' && github.event.inputs.distribution != 'minimal' && 'minimal' || '' }}
40+
- distribution: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.distribution != 'all' && github.event.inputs.distribution != 'full' && 'full' || '' }}
41+
42+
steps:
43+
- name: Checkout code
44+
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
45+
46+
- name: Set up Docker Buildx
47+
uses: docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435 # v3.11.1
48+
49+
- name: Build and test ${{ matrix.distribution }} distribution
50+
run: |
51+
cd bindings/python
52+
echo "🔨 Building ${{ matrix.distribution }} distribution..."
53+
./build-all.sh ${{ matrix.distribution }}
54+
env:
55+
DISTRIBUTION: ${{ matrix.distribution }}
56+
57+
- name: Extract wheel for additional testing
58+
run: |
59+
cd bindings/python
60+
mkdir -p test-install
61+
cp dist/*${{ matrix.distribution }}*.whl test-install/ || cp dist/*.whl test-install/
62+
63+
- name: Set up Python for host testing
64+
uses: actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c # v6.0.0
65+
with:
66+
python-version: '3.11'
67+
68+
- name: Install Java (required for JPype)
69+
uses: actions/setup-java@dded0888837ed1f317902acf8a20df0ad188d165 # v5.0.0
70+
with:
71+
distribution: 'temurin'
72+
java-version: '21'
73+
74+
- name: Install wheel and test dependencies
75+
run: |
76+
cd bindings/python
77+
pip install test-install/*.whl pytest pytest-cov requests
78+
79+
- name: Run pytest on host
80+
id: pytest
81+
run: |
82+
cd bindings/python
83+
echo "🧪 Testing ${{ matrix.distribution }} distribution..."
84+
85+
# Run pytest with verbose output
86+
pytest tests/ -v --tb=short --color=yes 2>&1 | tee pytest-output.txt
87+
88+
# Check results
89+
if grep -q "failed" pytest-output.txt; then
90+
echo "❌ Tests FAILED"
91+
exit 1
92+
elif grep -q "passed" pytest-output.txt || grep -q "skipped" pytest-output.txt; then
93+
echo "✅ Tests PASSED (may include skipped tests based on distribution)"
94+
95+
# Count results
96+
PASSED=$(grep -oP '\d+(?= passed)' pytest-output.txt || echo "0")
97+
SKIPPED=$(grep -oP '\d+(?= skipped)' pytest-output.txt || echo "0")
98+
FAILED=$(grep -oP '\d+(?= failed)' pytest-output.txt || echo "0")
99+
100+
echo "passed=$PASSED" >> $GITHUB_OUTPUT
101+
echo "skipped=$SKIPPED" >> $GITHUB_OUTPUT
102+
echo "failed=$FAILED" >> $GITHUB_OUTPUT
103+
104+
# Exit with error if any failures
105+
if [ "$FAILED" != "0" ]; then
106+
exit 1
107+
fi
108+
else
109+
echo "⚠️ Unexpected test output"
110+
exit 1
111+
fi
112+
113+
- name: Generate test summary
114+
if: always()
115+
run: |
116+
cd bindings/python
117+
118+
echo "## 🧪 Test Results: ${{ matrix.distribution }}" >> $GITHUB_STEP_SUMMARY
119+
echo "" >> $GITHUB_STEP_SUMMARY
120+
121+
if [ "${{ steps.pytest.outcome }}" = "success" ]; then
122+
echo "✅ **Status**: PASSED" >> $GITHUB_STEP_SUMMARY
123+
else
124+
echo "❌ **Status**: FAILED" >> $GITHUB_STEP_SUMMARY
125+
fi
126+
127+
echo "" >> $GITHUB_STEP_SUMMARY
128+
echo "| Metric | Count |" >> $GITHUB_STEP_SUMMARY
129+
echo "|--------|-------|" >> $GITHUB_STEP_SUMMARY
130+
echo "| ✅ Passed | ${{ steps.pytest.outputs.passed || 'N/A' }} |" >> $GITHUB_STEP_SUMMARY
131+
echo "| ⏭️ Skipped | ${{ steps.pytest.outputs.skipped || 'N/A' }} |" >> $GITHUB_STEP_SUMMARY
132+
echo "| ❌ Failed | ${{ steps.pytest.outputs.failed || 'N/A' }} |" >> $GITHUB_STEP_SUMMARY
133+
echo "" >> $GITHUB_STEP_SUMMARY
134+
135+
echo "### Expected Behavior by Distribution:" >> $GITHUB_STEP_SUMMARY
136+
echo "" >> $GITHUB_STEP_SUMMARY
137+
echo "- **Headless**: Some tests skipped (no server/Gremlin features)" >> $GITHUB_STEP_SUMMARY
138+
echo "- **Minimal**: Few tests skipped (no Gremlin, has server/Studio)" >> $GITHUB_STEP_SUMMARY
139+
echo "- **Full**: Minimal skipped tests (all features available)" >> $GITHUB_STEP_SUMMARY
140+
141+
- name: Upload test results
142+
if: always()
143+
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
144+
with:
145+
name: test-results-${{ matrix.distribution }}
146+
path: |
147+
bindings/python/pytest-output.txt
148+
bindings/python/.coverage
149+
retention-days: 7
150+
151+
- name: Upload wheel artifact
152+
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
153+
with:
154+
name: wheel-${{ matrix.distribution }}-test
155+
path: bindings/python/dist/*.whl
156+
retention-days: 7
157+
158+
# Summary job that checks all distributions
159+
test-summary:
160+
name: Test Summary
161+
needs: test
162+
runs-on: ubuntu-latest
163+
if: always()
164+
steps:
165+
- name: Check test results
166+
run: |
167+
echo "## 🎯 Overall Test Summary" >> $GITHUB_STEP_SUMMARY
168+
echo "" >> $GITHUB_STEP_SUMMARY
169+
170+
if [ "${{ needs.test.result }}" = "success" ]; then
171+
echo "✅ **All distributions passed testing!**" >> $GITHUB_STEP_SUMMARY
172+
echo "" >> $GITHUB_STEP_SUMMARY
173+
echo "All three Python distributions (headless, minimal, full) have been successfully built and tested." >> $GITHUB_STEP_SUMMARY
174+
else
175+
echo "❌ **Some distributions failed testing**" >> $GITHUB_STEP_SUMMARY
176+
echo "" >> $GITHUB_STEP_SUMMARY
177+
echo "Please check the individual test jobs for details." >> $GITHUB_STEP_SUMMARY
178+
exit 1
179+
fi
Lines changed: 211 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,211 @@
1+
name: Test Python Examples
2+
3+
on:
4+
# Run on any push to any branch
5+
push:
6+
7+
# Run on any pull request
8+
pull_request:
9+
10+
# Allow being called by other workflows (e.g., release workflow)
11+
workflow_call:
12+
13+
# Allow manual trigger
14+
workflow_dispatch:
15+
16+
jobs:
17+
test-examples:
18+
name: Test Python Examples
19+
runs-on: ubuntu-latest
20+
21+
steps:
22+
- name: Checkout code
23+
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
24+
25+
- name: Set up Docker Buildx
26+
uses: docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435 # v3.11.1
27+
28+
- name: Build minimal distribution
29+
run: |
30+
cd bindings/python
31+
echo "🔨 Building minimal distribution for examples..."
32+
./build-all.sh minimal
33+
34+
- name: Set up Python
35+
uses: actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c # v6.0.0
36+
with:
37+
python-version: '3.11'
38+
39+
- name: Install Java (required for JPype)
40+
uses: actions/setup-java@dded0888837ed1f317902acf8a20df0ad188d165 # v5.0.0
41+
with:
42+
distribution: 'temurin'
43+
java-version: '21'
44+
45+
- name: Install ArcadeDB Python bindings
46+
run: |
47+
cd bindings/python
48+
pip install dist/*minimal*.whl
49+
50+
- name: Install example dependencies
51+
run: |
52+
# Install dependencies needed by examples
53+
pip install numpy requests
54+
55+
- name: Download sample data
56+
run: |
57+
cd bindings/python/examples
58+
echo "📥 Downloading sample data for examples..."
59+
# Download large dataset for comprehensive testing
60+
python download_sample_data.py
61+
62+
- name: Run all examples
63+
id: run_examples
64+
env:
65+
# Increase JVM heap for large CSV imports (example 04)
66+
ARCADEDB_JVM_MAX_HEAP: "8g"
67+
run: |
68+
cd bindings/python/examples
69+
70+
echo "🚀 Running Python Examples..."
71+
echo ""
72+
73+
# Initialize counters
74+
total=0
75+
passed=0
76+
failed=0
77+
skipped=0
78+
79+
# Create results file
80+
results_file="example-results.txt"
81+
> $results_file
82+
83+
# Find all Python example files (exclude download_sample_data.py as it's a utility)
84+
examples=$(ls [0-9]*.py 2>/dev/null | sort)
85+
86+
if [ -z "$examples" ]; then
87+
echo "❌ No example files found!"
88+
exit 1
89+
fi
90+
91+
# Run each example
92+
for example in $examples; do
93+
total=$((total + 1))
94+
echo "----------------------------------------"
95+
echo "📝 Running: $example"
96+
echo "----------------------------------------"
97+
98+
# Create a timeout wrapper to prevent hanging
99+
if timeout 1800 python "$example" > "${example}.log" 2>&1; then
100+
echo "✅ PASSED: $example" | tee -a $results_file
101+
passed=$((passed + 1))
102+
else
103+
exit_code=$?
104+
if [ $exit_code -eq 124 ]; then
105+
echo "⏱️ TIMEOUT: $example (exceeded 30 minutes)" | tee -a $results_file
106+
failed=$((failed + 1))
107+
else
108+
echo "❌ FAILED: $example (exit code: $exit_code)" | tee -a $results_file
109+
failed=$((failed + 1))
110+
fi
111+
# Show last 20 lines of error log
112+
echo "Last 20 lines of output:"
113+
tail -n 20 "${example}.log"
114+
fi
115+
echo ""
116+
done
117+
118+
# Print summary
119+
echo "========================================"
120+
echo "📊 EXAMPLE TEST SUMMARY"
121+
echo "========================================"
122+
echo "Total: $total"
123+
echo "Passed: $passed ✅"
124+
echo "Failed: $failed ❌"
125+
echo "Skipped: $skipped ⏭️"
126+
echo "========================================"
127+
echo ""
128+
129+
# Output to GitHub Actions
130+
echo "total=$total" >> $GITHUB_OUTPUT
131+
echo "passed=$passed" >> $GITHUB_OUTPUT
132+
echo "failed=$failed" >> $GITHUB_OUTPUT
133+
echo "skipped=$skipped" >> $GITHUB_OUTPUT
134+
135+
# Show detailed results
136+
echo "Detailed Results:"
137+
cat $results_file
138+
139+
# Exit with error if any failed
140+
if [ $failed -gt 0 ]; then
141+
echo "❌ Some examples failed!"
142+
exit 1
143+
else
144+
echo "✅ All examples passed!"
145+
fi
146+
147+
- name: Generate test summary
148+
if: always()
149+
run: |
150+
cd bindings/python/examples
151+
152+
echo "## 🎮 Python Examples Test Results" >> $GITHUB_STEP_SUMMARY
153+
echo "" >> $GITHUB_STEP_SUMMARY
154+
155+
total="${{ steps.run_examples.outputs.total || '0' }}"
156+
passed="${{ steps.run_examples.outputs.passed || '0' }}"
157+
failed="${{ steps.run_examples.outputs.failed || '0' }}"
158+
159+
if [ "${{ steps.run_examples.outcome }}" = "success" ]; then
160+
echo "✅ **Status**: ALL EXAMPLES PASSED ($passed/$total)" >> $GITHUB_STEP_SUMMARY
161+
else
162+
echo "❌ **Status**: SOME EXAMPLES FAILED ($passed/$total passed)" >> $GITHUB_STEP_SUMMARY
163+
fi
164+
165+
echo "" >> $GITHUB_STEP_SUMMARY
166+
echo "### Summary" >> $GITHUB_STEP_SUMMARY
167+
echo "" >> $GITHUB_STEP_SUMMARY
168+
echo "| Metric | Count |" >> $GITHUB_STEP_SUMMARY
169+
echo "|--------|------:|" >> $GITHUB_STEP_SUMMARY
170+
echo "| 📝 Total | $total |" >> $GITHUB_STEP_SUMMARY
171+
echo "| ✅ Passed | $passed |" >> $GITHUB_STEP_SUMMARY
172+
echo "| ❌ Failed | $failed |" >> $GITHUB_STEP_SUMMARY
173+
echo "| ⏭️ Skipped | ${{ steps.run_examples.outputs.skipped || '0' }} |" >> $GITHUB_STEP_SUMMARY
174+
echo "" >> $GITHUB_STEP_SUMMARY
175+
176+
# Add detailed results if available
177+
if [ -f example-results.txt ]; then
178+
echo "### Detailed Results" >> $GITHUB_STEP_SUMMARY
179+
echo "" >> $GITHUB_STEP_SUMMARY
180+
echo "\`\`\`" >> $GITHUB_STEP_SUMMARY
181+
cat example-results.txt >> $GITHUB_STEP_SUMMARY
182+
echo "\`\`\`" >> $GITHUB_STEP_SUMMARY
183+
fi
184+
185+
echo "" >> $GITHUB_STEP_SUMMARY
186+
echo "### Examples Tested" >> $GITHUB_STEP_SUMMARY
187+
echo "" >> $GITHUB_STEP_SUMMARY
188+
echo "- 01_simple_document_store.py - Document CRUD operations" >> $GITHUB_STEP_SUMMARY
189+
echo "- 02_social_network_graph.py - Graph modeling and traversal" >> $GITHUB_STEP_SUMMARY
190+
echo "- 03_vector_search.py - Vector embeddings and similarity search" >> $GITHUB_STEP_SUMMARY
191+
echo "- 04_csv_import_documents.py - CSV data import with type inference" >> $GITHUB_STEP_SUMMARY
192+
echo "" >> $GITHUB_STEP_SUMMARY
193+
echo "_Note: Example 04 requires the MovieLens dataset. If it fails, the dataset may need to be downloaded._" >> $GITHUB_STEP_SUMMARY
194+
195+
- name: Upload example logs
196+
if: always()
197+
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
198+
with:
199+
name: example-logs
200+
path: |
201+
bindings/python/examples/*.log
202+
bindings/python/examples/example-results.txt
203+
retention-days: 7
204+
205+
- name: Upload example databases
206+
if: failure()
207+
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
208+
with:
209+
name: example-databases
210+
path: bindings/python/examples/my_test_databases/
211+
retention-days: 3

0 commit comments

Comments
 (0)