test_sync_template_gen.py 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. # -*- coding:utf-8 -*-
  2. """
  3. datax-sync-template-gen 模板渲染 + JDBC URL 解析单测。
  4. 不连真 PG(query_columns / query_primary_key 走 mock conn)。
  5. 脚本路径含连字符,用 importlib.util 动态加载为模块。
  6. """
  7. import importlib.util
  8. import os
  9. import sys
  10. from unittest.mock import MagicMock
  11. import pytest
  12. PROJECT_ROOT = os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))
  13. SCRIPT_PATH = os.path.join(PROJECT_ROOT, 'bin', 'datax-sync-template-gen.py')
  14. def _load_script():
  15. spec = importlib.util.spec_from_file_location('datax_sync_template_gen', SCRIPT_PATH)
  16. mod = importlib.util.module_from_spec(spec)
  17. sys.modules['datax_sync_template_gen'] = mod
  18. spec.loader.exec_module(mod)
  19. return mod
  20. GEN = _load_script()
  21. def test_parse_jdbc_url_with_port():
  22. host, port, db = GEN.parse_jdbc_url('jdbc:postgresql://10.0.0.1:5433/hobby_stocks')
  23. assert host == '10.0.0.1'
  24. assert port == 5433
  25. assert db == 'hobby_stocks'
  26. def test_parse_jdbc_url_default_port():
  27. host, port, db = GEN.parse_jdbc_url('jdbc:postgresql://pg.example.com/mydb')
  28. assert host == 'pg.example.com'
  29. assert port == 5432
  30. assert db == 'mydb'
  31. def test_parse_jdbc_url_invalid():
  32. with pytest.raises(ValueError, match='无法解析'):
  33. GEN.parse_jdbc_url('mysql://10.0.0.1:3306/foo')
  34. def test_query_columns_returns_name_and_comment():
  35. conn = MagicMock()
  36. cur = conn.cursor.return_value
  37. cur.fetchall.return_value = [
  38. ('id', 'id'),
  39. ('user_id', '用户id'),
  40. ('create_time', None), # 无注释
  41. ]
  42. cols = GEN.query_columns(conn, 'public', 'orders')
  43. assert cols == [('id', 'id'), ('user_id', '用户id'), ('create_time', '')]
  44. def test_query_columns_empty_raises():
  45. conn = MagicMock()
  46. cur = conn.cursor.return_value
  47. cur.fetchall.return_value = []
  48. with pytest.raises(ValueError, match='表不存在或无字段'):
  49. GEN.query_columns(conn, 'public', 'no_such_table')
  50. def test_query_primary_key_single():
  51. conn = MagicMock()
  52. cur = conn.cursor.return_value
  53. cur.fetchall.return_value = [('id',)]
  54. assert GEN.query_primary_key(conn, 'public', 'orders') == 'id'
  55. def test_query_primary_key_composite_returns_empty():
  56. conn = MagicMock()
  57. cur = conn.cursor.return_value
  58. cur.fetchall.return_value = [('id1',), ('id2',)]
  59. assert GEN.query_primary_key(conn, 'public', 'orders') == ''
  60. def test_query_primary_key_none_returns_empty():
  61. conn = MagicMock()
  62. cur = conn.cursor.return_value
  63. cur.fetchall.return_value = []
  64. assert GEN.query_primary_key(conn, 'public', 'orders') == ''
  65. def test_render_template_includes_required_fields():
  66. columns = [('id', 'id'), ('name', '姓名'), ('create_time', '创建时间')]
  67. out = GEN.render_template(
  68. ds_ref='postgresql/prod-hobby',
  69. database='hobby_stocks',
  70. schema='public',
  71. table='users',
  72. columns=columns,
  73. pk='id',
  74. )
  75. assert 'dataSource = postgresql/prod-hobby' in out
  76. assert 'database = hobby_stocks' in out
  77. assert 'table = public.users' in out
  78. assert 'column = id,name,create_time' in out
  79. assert 'splitPk = id' in out
  80. assert "where = update_time >= '${start_date}' AND update_time < '${stop_date}'" in out
  81. assert 'path = /user/hive/warehouse/raw.db/users_TODO_d/dt=${dt}/' in out
  82. assert 'fileName = users_TODO_d' in out
  83. def test_render_template_empty_pk():
  84. out = GEN.render_template(
  85. ds_ref='postgresql/prod-hobby', database='db', schema='public',
  86. table='t', columns=[('a', '')], pk='',
  87. )
  88. assert 'splitPk = \n' in out