Skip to content

test(api-core): Adds integration tests using a local grpc server - #18118

Draft
chalmerlowe wants to merge 27 commits into
feat/otel-tracing-core-infrafrom
feat/otel-tracing-robust-tests
Draft

test(api-core): Adds integration tests using a local grpc server #18118
chalmerlowe wants to merge 27 commits into
feat/otel-tracing-core-infrafrom
feat/otel-tracing-robust-tests

Conversation

@chalmerlowe

Copy link
Copy Markdown
Contributor

Warning

This description is AI generated and is no longer accurate. NEEDS REVISION.

Problem

  1. The previous implementation used standard grpc.intercept_channel which caused a TypeError with modern OpenTelemetry interceptors because they do not satisfy standard grpc interceptor type checks.
  2. Older OpenTelemetry versions relied on pkg_resources, which was removed in setuptools v82+, causing ModuleNotFoundError in modern test environments.
  3. There was a lack of robust tests verifying that spans are actually recorded during a real gRPC call (without relying heavily on mocks).

Solution

  1. Modernized Interception: Switched from grpc.intercept_channel to otel_grpc.intercept_channel helper provided by the OpenTelemetry instrumentation package, which cleanly handles its own interceptor types.
  2. Raised Lower Bounds: Bumped minimum OpenTelemetry versions to modern releases (opentelemetry-api >= 1.44.0, opentelemetry-instrumentation-grpc >= 0.65b0) to eliminate reliance on the deprecated pkg_resources.
  3. New Testing Extra: Added a [testing] extra containing opentelemetry-sdk to facilitate test automation.
  4. Robust Integration Test: Added test_otel_integration_with_fake_endpoint which spins up a local, generic gRPC server (GenericEchoHandler) to verify that spans are recorded during a real request without needing compiled protobuf stubs.

Notes to Reviewers

  • This PR ensures compatibility with modern setuptools and modern OpenTelemetry practices.
  • The generic gRPC server approach allows us to test the full plumbing without bloating the PR with compiled _pb2.py files.
  • We have decoupled the testing SDK from core dependencies while ensuring standard test runners (like Nox) have all they need to run the suite.

Expands upon #18069 (Adds additional integration testing to supplement the unit testing)

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces OpenTelemetry tracing support for gRPC channels in google-api-core. It adds a tracer_provider option to ClientOptions, integrates OpenTelemetry gRPC client interceptors in grpc_helpers.create_channel when tracing is enabled, and safely discards the tracing configuration in async channels to prevent runtime errors. Additionally, dependencies and tests are updated to support this new functionality. The review feedback suggests improving mock hygiene in the newly added tests by patching the local module import path for grpc.secure_channel instead of patching the global module directly, adhering to the repository's style guide.

Comment on lines +110 to +112
mock.patch(
"grpc.secure_channel", return_value=mock_channel
) as mock_secure_channel,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

According to the Repository Style Guide (Section 4: Unit Testing and Mock Hygiene), we should mock the local module import path instead of patching third-party or global modules directly. This ensures that mocks are isolated and do not leak or cause side effects in other tests.

Suggested change
mock.patch(
"grpc.secure_channel", return_value=mock_channel
) as mock_secure_channel,
mock.patch(
"google.api_core.grpc_helpers.grpc.secure_channel", return_value=mock_channel
) as mock_secure_channel,
References
  1. Localized Mocking: When mocking standard functions or filesystem checks, mock the local module import path instead of patching builtins globally, ensuring mocks are isolated. (link)


mock_channel = "raw_channel"
with (
mock.patch("grpc.secure_channel", return_value=mock_channel),

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

According to the Repository Style Guide (Section 4: Unit Testing and Mock Hygiene), we should mock the local module import path instead of patching third-party or global modules directly to ensure proper mock isolation.

Suggested change
mock.patch("grpc.secure_channel", return_value=mock_channel),
mock.patch("google.api_core.grpc_helpers.grpc.secure_channel", return_value=mock_channel),
References
  1. Localized Mocking: When mocking standard functions or filesystem checks, mock the local module import path instead of patching builtins globally, ensuring mocks are isolated. (link)

def mock_secure(*args, **kwargs):
return grpc.insecure_channel(args[0])

monkeypatch.setattr(grpc, "secure_channel", mock_secure)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

According to the Repository Style Guide (Section 4: Unit Testing and Mock Hygiene), we should mock the local module import path instead of patching third-party or global modules directly to ensure proper mock isolation.

Suggested change
monkeypatch.setattr(grpc, "secure_channel", mock_secure)
monkeypatch.setattr("google.api_core.grpc_helpers.grpc.secure_channel", mock_secure)
References
  1. Localized Mocking: When mocking standard functions or filesystem checks, mock the local module import path instead of patching builtins globally, ensuring mocks are isolated. (link)

@chalmerlowe
chalmerlowe changed the base branch from main to feat/otel-tracing-core-infra August 14, 2026 16:02
@chalmerlowe
chalmerlowe force-pushed the feat/otel-tracing-core-infra branch from 0309a90 to c908003 Compare August 14, 2026 16:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant