Spaces:
Runtime error
Runtime error
| # Apps Script MCP Testing Guide | |
| This document provides instructions for running unit tests and end-to-end (E2E) tests for the Apps Script MCP feature. | |
| ## Test Structure | |
| ``` | |
| tests/gappsscript/ | |
| __init__.py | |
| test_apps_script_tools.py # Unit tests with mocked API | |
| manual_test.py # E2E tests against real API | |
| ``` | |
| ## Unit Tests | |
| Unit tests use mocked API responses and do not require Google credentials. | |
| ### Running Unit Tests | |
| ```bash | |
| # Run all Apps Script unit tests | |
| uv run pytest tests/gappsscript/test_apps_script_tools.py -v | |
| # Run specific test | |
| uv run pytest tests/gappsscript/test_apps_script_tools.py::test_list_script_projects -v | |
| # Run with coverage | |
| uv run pytest tests/gappsscript/test_apps_script_tools.py --cov=gappsscript | |
| ``` | |
| ### Test Coverage | |
| Unit tests cover: | |
| - list_script_projects (uses Drive API) | |
| - get_script_project | |
| - get_script_content | |
| - create_script_project | |
| - update_script_content | |
| - run_script_function | |
| - create_deployment | |
| - list_deployments | |
| - update_deployment | |
| - delete_deployment | |
| - list_script_processes | |
| ## E2E Tests | |
| E2E tests interact with the real Google Apps Script API. They require valid OAuth credentials and will create real resources in your Google account. | |
| ### Prerequisites | |
| 1. **Google Cloud Project** with Apps Script API and Drive API enabled | |
| 2. **OAuth credentials** (Desktop application type) | |
| 3. **Test user** added to OAuth consent screen | |
| ### Setup | |
| **Option 1: Default paths (recommended for CI)** | |
| Place credentials in the project root: | |
| ```bash | |
| # Place your OAuth client credentials here | |
| cp /path/to/your/client_secret.json ./client_secret.json | |
| ``` | |
| **Option 2: Custom paths via environment variables** | |
| ```bash | |
| export GOOGLE_CLIENT_SECRET_PATH=/path/to/client_secret.json | |
| export GOOGLE_TOKEN_PATH=/path/to/token.pickle | |
| ``` | |
| ### Running E2E Tests | |
| ```bash | |
| # Interactive mode (prompts for confirmation) | |
| uv run python tests/gappsscript/manual_test.py | |
| # Non-interactive mode (for CI) | |
| uv run python tests/gappsscript/manual_test.py --yes | |
| ``` | |
| ### E2E Test Flow | |
| The test script performs the following operations: | |
| 1. **List Projects** - Lists existing Apps Script projects via Drive API | |
| 2. **Create Project** - Creates a new test project | |
| 3. **Get Project** - Retrieves project details | |
| 4. **Update Content** - Adds code to the project | |
| 5. **Run Function** - Attempts to execute a function (see note below) | |
| 6. **Create Deployment** - Creates a versioned deployment | |
| 7. **List Deployments** - Lists all deployments | |
| 8. **List Processes** - Lists recent script executions | |
| ### Cleanup | |
| The test script does not automatically delete created projects. After running tests: | |
| 1. Go to [Google Apps Script](https://script.google.com/) | |
| 2. Find projects named "MCP Test Project" | |
| 3. Delete them manually via the menu (three dots) > Remove | |
| ## Headless Linux Testing | |
| For headless environments (servers, CI/CD, WSL without GUI): | |
| ### OAuth Authentication Flow | |
| The test script uses a headless-compatible OAuth flow: | |
| 1. Script prints an authorization URL | |
| 2. Open the URL in any browser (can be on a different machine) | |
| 3. Complete Google sign-in and authorization | |
| 4. Browser redirects to `http://localhost/?code=...` (page will not load) | |
| 5. Copy the full URL from the browser address bar | |
| 6. Paste it into the terminal when prompted | |
| ### Example Session | |
| ``` | |
| $ python tests/gappsscript/manual_test.py --yes | |
| ============================================================ | |
| HEADLESS AUTH | |
| ============================================================ | |
| 1. Open this URL in any browser: | |
| https://accounts.google.com/o/oauth2/auth?response_type=code&client_id=... | |
| 2. Sign in and authorize the app | |
| 3. You'll be redirected to http://localhost (won't load) | |
| 4. Copy the FULL URL from browser address bar | |
| (looks like: http://localhost/?code=4/0A...&scope=...) | |
| 5. Paste it below: | |
| Paste full redirect URL: http://localhost/?code=4/0AQSTgQ...&scope=... | |
| Building API services... | |
| === Test: List Projects === | |
| Found 3 Apps Script projects: | |
| ... | |
| ``` | |
| ### Credential Storage | |
| OAuth tokens are stored as pickle files: | |
| - Default: `./test_token.pickle` in project root | |
| - Custom: Set via `GOOGLE_TOKEN_PATH` environment variable | |
| Tokens are reused on subsequent runs until they expire or are revoked. | |
| ## Known Limitations and Caveats | |
| ### run_script_function Test Failure | |
| The "Run Function" test will fail with a 404 error unless you manually configure the script as an API Executable. This is a Google platform requirement, not a bug. | |
| To make run_script_function work: | |
| 1. Open the created test script in Apps Script editor | |
| 2. Go to Project Settings > Change GCP project | |
| 3. Enter your GCP project number | |
| 4. Deploy as "API Executable" | |
| For E2E testing purposes, it is acceptable for this test to fail. All other tests should pass. | |
| ### Drive API Requirement | |
| The `list_script_projects` function uses the Google Drive API (not the Apps Script API) because the Apps Script API does not provide a projects.list endpoint. Ensure the Drive API is enabled in your GCP project. | |
| ### Scope Requirements | |
| The E2E tests require these scopes: | |
| - `script.projects` and `script.projects.readonly` | |
| - `script.deployments` and `script.deployments.readonly` | |
| - `script.processes` | |
| - `drive.readonly` | |
| If you encounter "insufficient scopes" errors, delete the stored token file and re-authenticate. | |
| ### Rate Limits | |
| Google enforces rate limits on the Apps Script API. If running tests repeatedly, you may encounter quota errors. Wait a few minutes before retrying. | |
| ## CI/CD Integration | |
| For automated testing in CI/CD pipelines: | |
| ### Unit Tests Only (Recommended) | |
| ```yaml | |
| # GitHub Actions example | |
| - name: Run unit tests | |
| run: uv run pytest tests/gappsscript/test_apps_script_tools.py -v | |
| ``` | |
| ### E2E Tests in CI | |
| E2E tests require OAuth credentials. Options: | |
| 1. **Skip E2E in CI** - Run only unit tests in CI, run E2E locally | |
| 2. **Service Account** - Not supported (Apps Script API requires user OAuth) | |
| 3. **Pre-authenticated Token** - Store encrypted token in CI secrets | |
| To use a pre-authenticated token: | |
| ```bash | |
| # Generate token locally | |
| python tests/gappsscript/manual_test.py | |
| # Store test_token.pickle contents as base64 in CI secret | |
| base64 test_token.pickle > token.b64 | |
| # In CI, restore and set path | |
| echo $TOKEN_SECRET | base64 -d > test_token.pickle | |
| export GOOGLE_TOKEN_PATH=./test_token.pickle | |
| python tests/gappsscript/manual_test.py --yes | |
| ``` | |
| Note: Tokens expire and must be refreshed periodically. | |
| ## Troubleshooting | |
| ### "Apps Script API has not been used in project" | |
| Enable the Apps Script API in your GCP project: | |
| https://console.cloud.google.com/flows/enableapi?apiid=script.googleapis.com | |
| ### "Access Not Configured. Drive API has not been used" | |
| Enable the Drive API in your GCP project: | |
| https://console.cloud.google.com/flows/enableapi?apiid=drive.googleapis.com | |
| ### "Request had insufficient authentication scopes" | |
| Delete the token file and re-authenticate: | |
| ```bash | |
| rm test_token.pickle | |
| python tests/gappsscript/manual_test.py | |
| ``` | |
| ### "User is not authorized to access this resource" | |
| Ensure your email is added as a test user in the OAuth consent screen configuration. | |
| ### "Requested entity was not found" (404 on run) | |
| The script needs to be deployed as "API Executable". See the run_script_function section above. | |
| ### OAuth redirect fails on headless machine | |
| The redirect to `http://localhost` is expected to fail. Copy the URL from the browser address bar (including the error page URL) and paste it into the terminal. | |