Skip to content

test(e2e_appium): add e2e_appium #2

test(e2e_appium): add e2e_appium

test(e2e_appium): add e2e_appium #2

name: E2E Appium Android
permissions:
actions: read
contents: read
checks: write
pull-requests: write
on:
push:
branches:
- test/e2e_appium/add-e2e_appium-framework
workflow_dispatch:
inputs:
apk_source:
description: 'APK source (lt://APP..., artifact run id, or direct URL)'
type: string
default: 'lt://APP...'
required: true
target:
description: 'Test target (marker name, test file, or custom pytest args)'
type: string
default: 'onboarding'
required: true
device_config:
description: 'Device configuration'
type: choice
default: 'default'
options:
- 'default' # Galaxy Tab S8
- 'pixel_tablet' # Google Pixel Tablet
- 'galaxy_tab_a' # Samsung Galaxy Tab A
parallel_execution:
description: 'Enable parallel test execution'
type: boolean
default: false
concurrency:
group: e2e-${{ github.ref }}-${{ inputs.target || 'onboarding' }}
cancel-in-progress: true
jobs:
e2e-test:
runs-on: ubuntu-latest
timeout-minutes: 60
steps:
- name: Normalize inputs
id: vars
run: |
# Normalize all inputs to handle both push and workflow_dispatch triggers
echo "target=${{ inputs.target || 'onboarding' }}" >> $GITHUB_OUTPUT
echo "parallel_execution=${{ inputs.parallel_execution || 'false' }}" >> $GITHUB_OUTPUT
echo "device_config=${{ inputs.device_config || 'default' }}" >> $GITHUB_OUTPUT
echo "apk_source=${{ inputs.apk_source || 'lt://APP10160232441755188546651464' }}" >> $GITHUB_OUTPUT
echo "πŸ“‹ Normalized inputs:"
echo " Target: ${{ steps.vars.outputs.target }}"
echo " Parallel: ${{ steps.vars.outputs.parallel_execution }}"
echo " Device: ${{ steps.vars.outputs.device_config }}"
echo " APK: ${{ steps.vars.outputs.apk_source }}"
- name: Checkout repository
uses: actions/checkout@v4
- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: '3.11.9'
cache: 'pip'
- name: Install dependencies
working-directory: test/e2e_appium
run: |
pip install -r requirements.txt
if [ "${{ steps.vars.outputs.parallel_execution }}" = "true" ]; then
pip install pytest-xdist
fi
- name: Detect APK source type
id: detect_source
run: |
SOURCE="${{ steps.vars.outputs.apk_source }}"
if [[ "$SOURCE" == lt://* ]]; then
echo "source_type=lambdatest_url" >> $GITHUB_OUTPUT
echo "app_url=$SOURCE" >> $GITHUB_OUTPUT
echo "πŸ“± Using existing LambdaTest app: $SOURCE"
elif [[ "$SOURCE" == http* ]]; then
echo "source_type=direct_url" >> $GITHUB_OUTPUT
echo "download_url=$SOURCE" >> $GITHUB_OUTPUT
echo "🌐 Will download APK from URL: $SOURCE"
else
# Assume SOURCE is a GitHub Actions run id
echo "source_type=github_artifact" >> $GITHUB_OUTPUT
echo "artifact_run_id=$SOURCE" >> $GITHUB_OUTPUT
echo "πŸ“¦ Will download GitHub artifact from run: $SOURCE"
fi
- name: Download APK from GitHub artifact
if: steps.detect_source.outputs.source_type == 'github_artifact'
uses: actions/download-artifact@v4
with:
# Your build workflow uploads "Status-tablet-${{ inputs.architecture }}-${{ github.run_number }}"
pattern: Status-tablet-*
merge-multiple: true
run-id: ${{ steps.detect_source.outputs.artifact_run_id }}
path: ./apk/
github-token: ${{ secrets.GITHUB_TOKEN }}
repository: ${{ github.repository }}
- name: Download APK from URL
if: steps.detect_source.outputs.source_type == 'direct_url'
run: |
echo "Downloading APK from: ${{ steps.detect_source.outputs.download_url }}"
mkdir -p ./apk
curl -L -o ./apk/downloaded.apk "${{ steps.detect_source.outputs.download_url }}"
ls -la ./apk/
- name: Upload APK to LambdaTest
if: steps.detect_source.outputs.source_type != 'lambdatest_url'
id: upload-lt
working-directory: test/e2e_appium
env:
LT_USERNAME: ${{ secrets.LT_USERNAME }}
LT_ACCESS_KEY: ${{ secrets.LT_ACCESS_KEY }}
run: |
if [ "${{ steps.detect_source.outputs.source_type }}" = "github_artifact" ]; then
APK_PATH="$(find ../../apk -type f -name '*.apk' | head -n 1)"
else
APK_PATH="../../apk/downloaded.apk"
fi
if [ -z "$APK_PATH" ] || [ ! -f "$APK_PATH" ]; then
echo "No APK found in ./apk" >&2
ls -la ../../apk || true
exit 1
fi
echo "πŸš€ Uploading APK to LambdaTest: $APK_PATH"
python scripts/upload_apk_to_lambdatest.py \
--apk-path "$APK_PATH" \
--app-name "E2E-${{ steps.vars.outputs.target }}-${{ github.run_number }}"
- name: Setup test environment
run: |
# Set app URL based on source type
if [ "${{ steps.detect_source.outputs.source_type }}" = "lambdatest_url" ]; then
echo "STATUS_APP_URL=${{ steps.detect_source.outputs.app_url }}" >> $GITHUB_ENV
else
echo "STATUS_APP_URL=${{ steps.upload-lt.outputs.app_url }}" >> $GITHUB_ENV
fi
# Set device name
case "${{ steps.vars.outputs.device_config }}" in
"pixel_tablet") echo "DEVICE_NAME=Google Pixel Tablet" >> $GITHUB_ENV ;;
"galaxy_tab_a") echo "DEVICE_NAME=Samsung Galaxy Tab A8" >> $GITHUB_ENV ;;
*) echo "DEVICE_NAME=Samsung Galaxy Tab S8" >> $GITHUB_ENV ;;
esac
echo "🎯 Test configuration:"
echo " Target: ${{ steps.vars.outputs.target }}"
echo " Device: $DEVICE_NAME"
echo " App: $STATUS_APP_URL"
echo " Parallel: ${{ steps.vars.outputs.parallel_execution }}"
- name: Build pytest command
id: pytest
run: |
TARGET="${{ steps.vars.outputs.target }}"
# Auto-detect target type and build pytest args
if [[ "$TARGET" == *.py ]]; then
# Test file
PYTEST_ARGS="tests/$TARGET"
elif [[ "$TARGET" == *::* ]] || [[ "$TARGET" == *test_* ]]; then
# Specific test or custom args
PYTEST_ARGS="$TARGET"
else
# Marker
PYTEST_ARGS="-m $TARGET"
fi
echo "pytest_args=$PYTEST_ARGS" >> $GITHUB_OUTPUT
echo "πŸ“‹ Will run: pytest $PYTEST_ARGS"
- name: Run E2E tests
working-directory: test/e2e_appium
env:
LT_USERNAME: ${{ secrets.LT_USERNAME }}
LT_ACCESS_KEY: ${{ secrets.LT_ACCESS_KEY }}
STATUS_APP_URL: ${{ env.STATUS_APP_URL }}
DEVICE_NAME: ${{ env.DEVICE_NAME }}
run: |
mkdir -p reports screenshots logs
PYTEST_CMD="python -m pytest ${{ steps.pytest.outputs.pytest_args }}"
PYTEST_CMD="$PYTEST_CMD --env=lambdatest -v"
PYTEST_CMD="$PYTEST_CMD --html=reports/e2e-results.html --self-contained-html"
PYTEST_CMD="$PYTEST_CMD --junitxml=reports/junit-e2e.xml"
if [ "${{ steps.vars.outputs.parallel_execution }}" = "true" ]; then
PYTEST_CMD="$PYTEST_CMD -n auto"
fi
echo "πŸ§ͺ Running: $PYTEST_CMD"
$PYTEST_CMD
- name: Generate test summary
if: always()
run: |
echo "## πŸ§ͺ E2E Test Results" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "| Setting | Value |" >> $GITHUB_STEP_SUMMARY
echo "|---------|--------|" >> $GITHUB_STEP_SUMMARY
echo "| **Target** | \`${{ steps.vars.outputs.target }}\` |" >> $GITHUB_STEP_SUMMARY
echo "| **Device** | ${{ env.DEVICE_NAME }} |" >> $GITHUB_STEP_SUMMARY
echo "| **App** | \`${{ env.STATUS_APP_URL }}\` |" >> $GITHUB_STEP_SUMMARY
echo "| **Parallel** | ${{ steps.vars.outputs.parallel_execution }} |" >> $GITHUB_STEP_SUMMARY
echo "| **Source Type** | ${{ steps.detect_source.outputs.source_type }} |" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
# Add test results if available
if [ -f "test/e2e_appium/reports/junit-e2e.xml" ]; then
echo "βœ… **Test execution completed** - Check artifacts for detailed results" >> $GITHUB_STEP_SUMMARY
else
echo "❌ **Test execution failed** - No results generated" >> $GITHUB_STEP_SUMMARY
fi
- name: Upload test artifacts
if: always()
uses: actions/upload-artifact@v4
with:
name: e2e-results-${{ github.run_number }}-${{ steps.vars.outputs.target }}
path: |
test/e2e_appium/reports/**/*
test/e2e_appium/screenshots/**/*
test/e2e_appium/logs/**/*
retention-days: 14
if-no-files-found: warn
- name: Test results summary
if: always()
run: |
echo "πŸ“Š E2E Results (${{ steps.vars.outputs.target }} on ${{ env.DEVICE_NAME }})"
if [ -f "test/e2e_appium/reports/junit-e2e.xml" ]; then
echo "βœ… Test report generated: test/e2e_appium/reports/junit-e2e.xml"
else
echo "⚠️ No test report found"
fi