Skip to content

Commit 02a8367

Browse files
committed
spanner
1 parent 773dac4 commit 02a8367

File tree

3 files changed

+53
-170
lines changed

3 files changed

+53
-170
lines changed

src/pytest_databases/docker/docker-compose.spanner.yml

Lines changed: 0 additions & 23 deletions
This file was deleted.
Lines changed: 35 additions & 118 deletions
Original file line numberDiff line numberDiff line change
@@ -1,142 +1,59 @@
11
from __future__ import annotations
22

3-
import contextlib
4-
import os
5-
import sys
6-
from pathlib import Path
3+
from dataclasses import dataclass
74
from typing import TYPE_CHECKING
85

96
import pytest
7+
from google.api_core.client_options import ClientOptions
108
from google.auth.credentials import AnonymousCredentials, Credentials
119
from google.cloud import spanner
1210

13-
from pytest_databases.docker import DockerServiceRegistry
14-
from pytest_databases.helpers import simple_string_hash
11+
from pytest_databases.types import ServiceContainer
1512

1613
if TYPE_CHECKING:
1714
from collections.abc import Generator
1815

16+
from pytest_databases._service import DockerService
1917

20-
COMPOSE_PROJECT_NAME: str = f"pytest-databases-spanner-{simple_string_hash(__file__)}"
2118

19+
@dataclass
20+
class SpannerService(ServiceContainer):
21+
credentials: Credentials
2222

23-
def spanner_responsive(
24-
host: str,
25-
spanner_port: int,
26-
spanner_instance: str,
27-
spanner_database: str,
28-
spanner_project: str,
29-
spanner_credentials: Credentials,
30-
) -> bool:
31-
try:
32-
spanner_client = spanner.Client(project=spanner_project, credentials=spanner_credentials)
33-
instance = spanner_client.instance(spanner_instance)
34-
with contextlib.suppress(Exception):
35-
instance.create()
36-
37-
database = instance.database(spanner_database)
38-
with contextlib.suppress(Exception):
39-
database.create()
40-
41-
with database.snapshot() as snapshot:
42-
resp = next(iter(snapshot.execute_sql("SELECT 1")))
43-
return resp[0] == 1
44-
except Exception: # noqa: BLE001
45-
return False
46-
23+
@property
24+
def endpoint(self) -> str:
25+
return f"{self.host}:{self.port}"
4726

48-
@pytest.fixture(scope="session")
49-
def spanner_compose_project_name() -> str:
50-
return os.environ.get("COMPOSE_PROJECT_NAME", COMPOSE_PROJECT_NAME)
27+
@property
28+
def client_options(self) -> ClientOptions:
29+
return ClientOptions(api_endpoint=self.endpoint)
5130

5231

5332
@pytest.fixture(autouse=False, scope="session")
54-
def spanner_docker_services(
55-
spanner_compose_project_name: str, worker_id: str = "main"
56-
) -> Generator[DockerServiceRegistry, None, None]:
57-
if os.getenv("GITHUB_ACTIONS") == "true" and sys.platform != "linux":
58-
pytest.skip("Docker not available on this platform")
59-
60-
with DockerServiceRegistry(worker_id, compose_project_name=spanner_compose_project_name) as registry:
61-
yield registry
62-
63-
64-
@pytest.fixture(scope="session")
65-
def spanner_port() -> int:
66-
return 9010
67-
68-
69-
@pytest.fixture(scope="session")
70-
def spanner_instance() -> str:
71-
return "test-instance"
72-
73-
74-
@pytest.fixture(scope="session")
75-
def spanner_database() -> str:
76-
return "test-database"
77-
78-
79-
@pytest.fixture(scope="session")
80-
def spanner_project() -> str:
81-
return "emulator-test-project"
82-
83-
84-
@pytest.fixture(scope="session")
85-
def spanner_credentials() -> Credentials:
86-
return AnonymousCredentials()
87-
88-
89-
@pytest.fixture(scope="session")
90-
def spanner_docker_compose_files() -> list[Path]:
91-
return [Path(Path(__file__).parent / "docker-compose.spanner.yml")]
92-
93-
94-
@pytest.fixture(scope="session")
95-
def default_spanner_service_name() -> str:
96-
return "spanner"
97-
98-
99-
@pytest.fixture(scope="session")
100-
def spanner_docker_ip(spanner_docker_services: DockerServiceRegistry) -> str:
101-
return spanner_docker_services.docker_ip
102-
103-
104-
@pytest.fixture(autouse=False, scope="session")
105-
def spanner_service(
106-
spanner_docker_services: DockerServiceRegistry,
107-
default_spanner_service_name: str,
108-
spanner_docker_compose_files: list[Path],
109-
spanner_docker_ip: str,
110-
spanner_port: int,
111-
spanner_instance: str,
112-
spanner_database: str,
113-
spanner_project: str,
114-
spanner_credentials: Credentials,
115-
) -> Generator[None, None, None]:
116-
os.environ["SPANNER_EMULATOR_HOST"] = f"{spanner_docker_ip}:{spanner_port}"
117-
os.environ["SPANNER_DATABASE"] = spanner_database
118-
os.environ["SPANNER_INSTANCE"] = spanner_instance
119-
os.environ["SPANNER_PORT"] = str(spanner_port)
120-
os.environ["GOOGLE_CLOUD_PROJECT"] = spanner_project
121-
spanner_docker_services.start(
122-
name=default_spanner_service_name,
123-
docker_compose_files=spanner_docker_compose_files,
124-
timeout=60,
125-
check=spanner_responsive,
126-
spanner_port=spanner_port,
127-
spanner_instance=spanner_instance,
128-
spanner_database=spanner_database,
129-
spanner_project=spanner_project,
130-
spanner_credentials=spanner_credentials,
131-
)
132-
yield
33+
def spanner_service(docker_service: DockerService) -> Generator[SpannerService, None, None]:
34+
with docker_service.run(
35+
image="gcr.io/cloud-spanner-emulator/emulator:latest",
36+
name="spanner",
37+
container_port=9010,
38+
wait_for_log="gRPC server listening at",
39+
) as service:
40+
yield SpannerService(
41+
host=service.host,
42+
port=service.port,
43+
credentials=AnonymousCredentials(),
44+
)
13345

13446

13547
@pytest.fixture(autouse=False, scope="session")
13648
def spanner_startup_connection(
137-
spanner_service: DockerServiceRegistry,
138-
spanner_project: str,
139-
spanner_credentials: Credentials,
49+
spanner_service: SpannerService,
14050
) -> Generator[spanner.Client, None, None]:
141-
c = spanner.Client(project=spanner_project, credentials=spanner_credentials)
142-
yield c
51+
client = spanner.Client(
52+
project=spanner_service.project,
53+
credentials=spanner_service.credentials,
54+
client_options=spanner_service.client_options,
55+
)
56+
try:
57+
yield client
58+
finally:
59+
client.close()

tests/docker/test_spanner.py

Lines changed: 18 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,48 +1,37 @@
11
from __future__ import annotations
22

3+
import contextlib
34
from typing import TYPE_CHECKING
45

56
from google.cloud import spanner
67

7-
from pytest_databases.docker.spanner import spanner_responsive
8-
98
if TYPE_CHECKING:
10-
from google.auth.credentials import Credentials
11-
12-
from pytest_databases.docker import DockerServiceRegistry
9+
from pytest_databases.docker.spanner import SpannerService
1310

1411
pytest_plugins = [
1512
"pytest_databases.docker.spanner",
1613
]
1714

1815

19-
def test_spanner_default_config(
20-
spanner_port: int, spanner_instance: str, spanner_database: str, spanner_project: str
21-
) -> None:
22-
assert spanner_port == 9010
23-
assert spanner_instance == "test-instance"
24-
assert spanner_database == "test-database"
25-
assert spanner_project == "emulator-test-project"
26-
27-
2816
def test_spanner_services(
29-
spanner_docker_ip: str,
30-
spanner_service: DockerServiceRegistry,
31-
spanner_port: int,
32-
spanner_instance: str,
33-
spanner_database: str,
34-
spanner_project: str,
35-
spanner_credentials: Credentials,
17+
spanner_service: SpannerService,
3618
) -> None:
37-
ping = spanner_responsive(
38-
spanner_docker_ip,
39-
spanner_port=spanner_port,
40-
spanner_instance=spanner_instance,
41-
spanner_database=spanner_database,
42-
spanner_project=spanner_project,
43-
spanner_credentials=spanner_credentials,
19+
spanner_client = spanner.Client(
20+
project=spanner_service.project,
21+
credentials=spanner_service.credentials,
22+
client_options=spanner_service.client_options,
4423
)
45-
assert ping
24+
instance = spanner_client.instance(spanner_service.instance_name)
25+
with contextlib.suppress(Exception):
26+
instance.create()
27+
28+
database = instance.database(spanner_service.database_name)
29+
with contextlib.suppress(Exception):
30+
database.create()
31+
32+
with database.snapshot() as snapshot:
33+
resp = next(iter(snapshot.execute_sql("SELECT 1")))
34+
assert resp[0] == 1
4635

4736

4837
def test_spanner_service_after_start(

0 commit comments

Comments
 (0)