This is an automated email from the ASF dual-hosted git repository.

Amar3tto pushed a commit to branch debezium-io-yaml
in repository https://gitbox.apache.org/repos/asf/beam.git


The following commit(s) were added to refs/heads/debezium-io-yaml by this push:
     new 01c668b1455 Add Debezium YAML integration test
01c668b1455 is described below

commit 01c668b1455c203688e29a4d8017a2e3181a1ef1
Author: Vitaly Terentyev <[email protected]>
AuthorDate: Thu Jul 23 16:02:55 2026 +0400

    Add Debezium YAML integration test
---
 .../yaml/extended_tests/databases/debezium.yaml    | 48 +++++++++++++++
 sdks/python/apache_beam/yaml/integration_tests.py  | 70 +++++++++++++++++++++-
 sdks/python/build.gradle                           |  4 +-
 3 files changed, 120 insertions(+), 2 deletions(-)

diff --git 
a/sdks/python/apache_beam/yaml/extended_tests/databases/debezium.yaml 
b/sdks/python/apache_beam/yaml/extended_tests/databases/debezium.yaml
new file mode 100644
index 00000000000..c4f7e3dbdee
--- /dev/null
+++ b/sdks/python/apache_beam/yaml/extended_tests/databases/debezium.yaml
@@ -0,0 +1,48 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+fixtures:
+  - name: DEBEZIUM_DB
+    type: "apache_beam.yaml.integration_tests.temp_debezium_postgres_database"
+
+pipelines:
+  - pipeline:
+      type: chain
+      transforms:
+        - type: ReadFromDebezium
+          config:
+            connector: POSTGRES
+            username: "{DEBEZIUM_DB[USERNAME]}"
+            password: "{DEBEZIUM_DB[PASSWORD]}"
+            host: "{DEBEZIUM_DB[HOST]}"
+            port: "{DEBEZIUM_DB[PORT]}"
+            table: "{DEBEZIUM_DB[TABLE]}"
+            connection_properties:
+              - "database.dbname={DEBEZIUM_DB[DATABASE]}"
+              - "plugin.name=pgoutput"
+              - "snapshot.mode=initial_only"
+        - type: MapToFields
+          config:
+            language: python
+            fields:
+              id: "after.id"
+              name: "after.name"
+        - type: AssertEqual
+          config:
+            elements:
+              - {id: 1, name: Alice}
+              - {id: 2, name: Bob}
diff --git a/sdks/python/apache_beam/yaml/integration_tests.py 
b/sdks/python/apache_beam/yaml/integration_tests.py
index 4fca20ade96..979bcda44b7 100644
--- a/sdks/python/apache_beam/yaml/integration_tests.py
+++ b/sdks/python/apache_beam/yaml/integration_tests.py
@@ -48,7 +48,7 @@ from apache_beam.yaml.test_utils.datadog_test_utils import 
temp_fake_datadog_ser
 
 class BigEndianIntegerCoderImpl(CoderImpl):
   """Coder implementation for big-endian integers used in cross-language tests.
-  
+
   This is needed because Java's BigEndianIntegerCoder falls back to the generic
   'beam:coders:javasdk:0.1' URN when used in cross-language pipelines, and
   Python's FnApiRunner needs to know how to decode it.
@@ -394,6 +394,74 @@ def temp_mysql_database():
     yield jdbc_url
 
 
[email protected]
+def temp_debezium_postgres_database():
+  """Provides a temporary PostgreSQL database configured for Debezium CDC."""
+
+  container = (
+    DockerContainer('quay.io/debezium/example-postgres:latest')
+    .with_env('POSTGRES_USER', 'debezium')
+    .with_env('POSTGRES_PASSWORD', 'dbz')
+    .with_env('POSTGRES_DB', 'inventory')
+    .with_exposed_ports(5432))
+
+  try:
+    container.start()
+    wait_for_logs(container, 'database system is ready to accept connections')
+
+    host = container.get_container_host_ip()
+    port = int(container.get_exposed_port(5432))
+
+    connection = None
+    for _ in range(30):
+      try:
+        connection = psycopg2.connect(
+          host=host,
+          port=port,
+          user='debezium',
+          password='dbz',
+          dbname='inventory')
+        break
+      except psycopg2.OperationalError:
+        time.sleep(1)
+
+    if connection is None:
+      raise RuntimeError('Debezium PostgreSQL container failed to become 
ready.')
+
+    try:
+      with connection.cursor() as cursor:
+        cursor.execute(
+          """
+          CREATE TABLE IF NOT EXISTS customers (
+            id INTEGER PRIMARY KEY,
+            name VARCHAR(255)
+          )
+          """)
+        cursor.execute(
+          """
+          INSERT INTO customers (id, name)
+          VALUES
+            (1, 'Alice'),
+            (2, 'Bob')
+          ON CONFLICT (id) DO NOTHING
+          """)
+      connection.commit()
+    finally:
+      connection.close()
+
+    yield {
+      'HOST': host,
+      'PORT': port,
+      'USERNAME': 'debezium',
+      'PASSWORD': 'dbz',
+      'DATABASE': 'inventory',
+      'TABLE': 'public.customers',
+    }
+
+  finally:
+    container.stop()
+
+
 @contextlib.contextmanager
 def temp_postgres_database():
   """Context manager to provide a temporary PostgreSQL database for testing.
diff --git a/sdks/python/build.gradle b/sdks/python/build.gradle
index 9e2fe232c42..b50660978b2 100644
--- a/sdks/python/build.gradle
+++ b/sdks/python/build.gradle
@@ -151,6 +151,7 @@ tasks.register("yamlIntegrationTests") {
   dependsOn ":sdks:java:extensions:sql:expansion-service:shadowJar"
   dependsOn ":sdks:java:io:expansion-service:build"
   dependsOn ":sdks:java:io:google-cloud-platform:expansion-service:build"
+  dependsOn ":sdks:java:io:debezium:expansion-service:shadowJar"
 
   doLast {
     exec {
@@ -170,6 +171,7 @@ tasks.register("postCommitYamlIntegrationTests") {
   dependsOn ":sdks:java:extensions:sql:expansion-service:shadowJar"
   dependsOn ":sdks:java:io:expansion-service:build"
   dependsOn ":sdks:java:io:google-cloud-platform:expansion-service:build"
+  dependsOn ":sdks:java:io:debezium:expansion-service:shadowJar"
 
   doLast {
     def testSetInput = project.findProperty('yamlTestSet') ?: 
'data,databases,messaging'
@@ -188,7 +190,7 @@ tasks.register("postCommitYamlIntegrationTests") {
           test_files_dir = 'extended_tests/messaging'
           break
         default:
-          throw StopExecutionException("Unknown yamlTestSet: ${testSet}. Must 
be one of 'data', 'databases', or 'messaging'.")
+          throw StopExecutionException("Unknown yamlTestSet: 
${currentTestSet}. Must be one of 'data', 'databases', or 'messaging'.")
       }
       exec {
         executable 'sh'

Reply via email to