# 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.