Files
firebase-ios-sdk/GeminiLanguageModel/Tests/GeminiTestUtilities
Andrew Heard bfb2eaac29 test(ai): GeminiLanguageModel integration testing foundation (#16617)
Establishes the integration testing foundation and parameterized test
suites for `GeminiLanguageModel`, enabling fast local execution via
`swift test` and automated CI verification on iOS Simulator.

Key Changes:
- `IntegrationTestingBackend`: Defines canonical backend configurations
  (`.developerAPI`, `.firebaseAILogicDeveloperAPI`, and
  `.firebaseAILogicAgentPlatform`), dynamically resolving endpoints,
  model resource paths, and auth headers from available credentials.
- `IntegrationTestEnvironment`: Centralizes credential discovery
  (`GEMINI_API_KEY`, `GOOGLE_API_KEY`, and `FIREBASE_PLIST_PATH`) into
  an immutable, thread-safe configuration struct with cached process
  access to avoid redundant disk I/O.
- `AppCheckDebugClient`: Implements a lightweight client to exchange
  debug tokens for App Check tokens without Keychain dependencies,
  deduplicating token requests across test runs with an in-memory cache.
- Parameterized Tests: Adds `BasicContentGenerationIntegrationTests`
  running against all available backends, tagged with `@Tag.integration`
  and gated by condition traits to cleanly skip when credentials are
  missing.
- CI Workflow: Adds `.github/workflows/sdk.geminilanguagemodel.yml` to
  run integration tests against Firebase AI Logic on iOS Simulator
  using decrypted repo secrets.
2026-09-07 18:28:37 -04:00
..

GeminiTestUtilities

Shared testing infrastructure, network mocking utilities, environment condition traits, and integration test backends for GeminiLanguageModel and GeminiAPIClient.

Overview

GeminiTestUtilities is an internal test support target consumed across all test suites in the package. It provides centralized utilities so tests avoid duplicating mock handlers, endpoint URLs, credential checks, or port probes.

Component Breakdown

Category Files Purpose
Network Mocking MockHTTPURLProtocol.swift, HTTPURLResponse+Mock.swift Offline URLSession request interception, response mocking, and SSE streaming simulation
Integration Backends IntegrationTestingBackend.swift, AppCheckDebugClient.swift Backend routing configurations, TCP socket probing, App Check debug token exchange and caching
Testing Traits & Tags ConditionTrait+Credentials.swift, ConditionTrait+FoundationModels.swift, Tag+Integration.swift Swift Testing conditional skip traits (.requireAPIKey, .requireFoundationModels) and .integration tag
Constants TestConstants.swift Centralized model resource IDs and canonical endpoint configurations

Common Recipes

1. Mocking HTTP URL Responses

Use MockHTTPURLProtocol and HTTPURLResponse.mock to simulate API responses without network access:

defer { MockHTTPURLProtocol.reset() }
let expectedURL = URL(string: "https://generativelanguage.googleapis.com/v1beta/models/gemini-3.5-flash-lite:generateContent")!
let response = try HTTPURLResponse.mock(url: expectedURL, statusCode: 200)

MockHTTPURLProtocol.setHandler(for: expectedURL) { request, proto in
  proto.client?.urlProtocol(proto, didReceive: response, cacheStoragePolicy: .notAllowed)
  proto.client?.urlProtocol(proto, didLoad: Data("{}".utf8))
  proto.client?.urlProtocolDidFinishLoading(proto)
}

2. Guarding Tests with Condition Traits

Swift Testing condition traits allow tests to cleanly skip when prerequisites (like API keys or specific OS versions) are absent:

// Skip if neither local test-server nor remote credentials are available
@Test(.requireIntegrationTestingBackend)
func myBackendTest() async throws { ... }

// Skip on platforms where FoundationModels is unavailable (< macOS 27)
@Suite("Model Tests", .requireFoundationModels)
struct ModelTests { ... }

3. App Check Token Caching

AppCheckTokenCache manages debug token exchange for Firebase AI Logic integration tests, caching active tokens in-memory and deduplicating in-flight network requests:

let token = try await AppCheckTokenCache.shared.token(
  projectID: projectID,
  appID: appID,
  apiKey: apiKey,
  debugToken: debugToken
)