pytest-dbt-macros 0.2.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (232) hide show
  1. pytest_dbt_macros-0.2.1/.gitignore +11 -0
  2. pytest_dbt_macros-0.2.1/CONTRIBUTING.md +8 -0
  3. pytest_dbt_macros-0.2.1/LICENSE +21 -0
  4. pytest_dbt_macros-0.2.1/NOTICE +28 -0
  5. pytest_dbt_macros-0.2.1/PKG-INFO +203 -0
  6. pytest_dbt_macros-0.2.1/README.md +176 -0
  7. pytest_dbt_macros-0.2.1/examples/README.md +22 -0
  8. pytest_dbt_macros-0.2.1/pyproject.toml +42 -0
  9. pytest_dbt_macros-0.2.1/scripts/baseline-requirements.txt +6 -0
  10. pytest_dbt_macros-0.2.1/scripts/make_baselines.py +126 -0
  11. pytest_dbt_macros-0.2.1/scripts/make_baselines.sh +8 -0
  12. pytest_dbt_macros-0.2.1/src/pytest_dbt_macros/__init__.py +3 -0
  13. pytest_dbt_macros-0.2.1/src/pytest_dbt_macros/core.py +318 -0
  14. pytest_dbt_macros-0.2.1/src/pytest_dbt_macros/plugin.py +15 -0
  15. pytest_dbt_macros-0.2.1/src/pytest_dbt_macros/vendored/SOURCES.json +7 -0
  16. pytest_dbt_macros-0.2.1/src/pytest_dbt_macros/vendored/bigquery/LICENSE +201 -0
  17. pytest_dbt_macros-0.2.1/src/pytest_dbt_macros/vendored/bigquery/array_append.sql +3 -0
  18. pytest_dbt_macros-0.2.1/src/pytest_dbt_macros/vendored/bigquery/array_concat.sql +3 -0
  19. pytest_dbt_macros-0.2.1/src/pytest_dbt_macros/vendored/bigquery/array_construct.sql +7 -0
  20. pytest_dbt_macros-0.2.1/src/pytest_dbt_macros/vendored/bigquery/bool_or.sql +5 -0
  21. pytest_dbt_macros-0.2.1/src/pytest_dbt_macros/vendored/bigquery/date.sql +3 -0
  22. pytest_dbt_macros-0.2.1/src/pytest_dbt_macros/vendored/bigquery/date_trunc.sql +7 -0
  23. pytest_dbt_macros-0.2.1/src/pytest_dbt_macros/vendored/bigquery/dateadd.sql +8 -0
  24. pytest_dbt_macros-0.2.1/src/pytest_dbt_macros/vendored/bigquery/datediff.sql +15 -0
  25. pytest_dbt_macros-0.2.1/src/pytest_dbt_macros/vendored/bigquery/equals.sql +7 -0
  26. pytest_dbt_macros-0.2.1/src/pytest_dbt_macros/vendored/bigquery/escape_single_quotes.sql +4 -0
  27. pytest_dbt_macros-0.2.1/src/pytest_dbt_macros/vendored/bigquery/except.sql +5 -0
  28. pytest_dbt_macros-0.2.1/src/pytest_dbt_macros/vendored/bigquery/get_columns_spec_ddl.sql +37 -0
  29. pytest_dbt_macros-0.2.1/src/pytest_dbt_macros/vendored/bigquery/hash.sql +3 -0
  30. pytest_dbt_macros-0.2.1/src/pytest_dbt_macros/vendored/bigquery/intersect.sql +5 -0
  31. pytest_dbt_macros-0.2.1/src/pytest_dbt_macros/vendored/bigquery/listagg.sql +14 -0
  32. pytest_dbt_macros-0.2.1/src/pytest_dbt_macros/vendored/bigquery/position.sql +9 -0
  33. pytest_dbt_macros-0.2.1/src/pytest_dbt_macros/vendored/bigquery/right.sql +12 -0
  34. pytest_dbt_macros-0.2.1/src/pytest_dbt_macros/vendored/bigquery/safe_cast.sql +27 -0
  35. pytest_dbt_macros-0.2.1/src/pytest_dbt_macros/vendored/bigquery/split_part.sql +20 -0
  36. pytest_dbt_macros-0.2.1/src/pytest_dbt_macros/vendored/bigquery/string_literal.sql +3 -0
  37. pytest_dbt_macros-0.2.1/src/pytest_dbt_macros/vendored/bigquery/timestamps.sql +12 -0
  38. pytest_dbt_macros-0.2.1/src/pytest_dbt_macros/vendored/duckdb/LICENSE +201 -0
  39. pytest_dbt_macros-0.2.1/src/pytest_dbt_macros/vendored/duckdb/any_value.sql +5 -0
  40. pytest_dbt_macros-0.2.1/src/pytest_dbt_macros/vendored/duckdb/date.sql +3 -0
  41. pytest_dbt_macros-0.2.1/src/pytest_dbt_macros/vendored/duckdb/dateadd.sql +22 -0
  42. pytest_dbt_macros-0.2.1/src/pytest_dbt_macros/vendored/duckdb/datediff.sql +12 -0
  43. pytest_dbt_macros-0.2.1/src/pytest_dbt_macros/vendored/duckdb/external_location.sql +8 -0
  44. pytest_dbt_macros-0.2.1/src/pytest_dbt_macros/vendored/duckdb/generate_series.sql +5 -0
  45. pytest_dbt_macros-0.2.1/src/pytest_dbt_macros/vendored/duckdb/lastday.sql +14 -0
  46. pytest_dbt_macros-0.2.1/src/pytest_dbt_macros/vendored/duckdb/listagg.sql +22 -0
  47. pytest_dbt_macros-0.2.1/src/pytest_dbt_macros/vendored/duckdb/normalize.sql +19 -0
  48. pytest_dbt_macros-0.2.1/src/pytest_dbt_macros/vendored/duckdb/splitpart.sql +3 -0
  49. pytest_dbt_macros-0.2.1/src/pytest_dbt_macros/vendored/duckdb/upstream.sql +42 -0
  50. pytest_dbt_macros-0.2.1/src/pytest_dbt_macros/vendored/global_project/LICENSE +201 -0
  51. pytest_dbt_macros-0.2.1/src/pytest_dbt_macros/vendored/global_project/_timestamps.sql +52 -0
  52. pytest_dbt_macros-0.2.1/src/pytest_dbt_macros/vendored/global_project/any_value.sql +9 -0
  53. pytest_dbt_macros-0.2.1/src/pytest_dbt_macros/vendored/global_project/array_append.sql +8 -0
  54. pytest_dbt_macros-0.2.1/src/pytest_dbt_macros/vendored/global_project/array_concat.sql +7 -0
  55. pytest_dbt_macros-0.2.1/src/pytest_dbt_macros/vendored/global_project/array_construct.sql +12 -0
  56. pytest_dbt_macros-0.2.1/src/pytest_dbt_macros/vendored/global_project/bool_or.sql +9 -0
  57. pytest_dbt_macros-0.2.1/src/pytest_dbt_macros/vendored/global_project/cast.sql +7 -0
  58. pytest_dbt_macros-0.2.1/src/pytest_dbt_macros/vendored/global_project/cast_bool_to_text.sql +7 -0
  59. pytest_dbt_macros-0.2.1/src/pytest_dbt_macros/vendored/global_project/concat.sql +7 -0
  60. pytest_dbt_macros-0.2.1/src/pytest_dbt_macros/vendored/global_project/data_types.sql +129 -0
  61. pytest_dbt_macros-0.2.1/src/pytest_dbt_macros/vendored/global_project/date.sql +10 -0
  62. pytest_dbt_macros-0.2.1/src/pytest_dbt_macros/vendored/global_project/date_spine.sql +75 -0
  63. pytest_dbt_macros-0.2.1/src/pytest_dbt_macros/vendored/global_project/date_trunc.sql +7 -0
  64. pytest_dbt_macros-0.2.1/src/pytest_dbt_macros/vendored/global_project/dateadd.sql +14 -0
  65. pytest_dbt_macros-0.2.1/src/pytest_dbt_macros/vendored/global_project/datediff.sql +14 -0
  66. pytest_dbt_macros-0.2.1/src/pytest_dbt_macros/vendored/global_project/equals.sql +14 -0
  67. pytest_dbt_macros-0.2.1/src/pytest_dbt_macros/vendored/global_project/escape_single_quotes.sql +8 -0
  68. pytest_dbt_macros-0.2.1/src/pytest_dbt_macros/vendored/global_project/except.sql +9 -0
  69. pytest_dbt_macros-0.2.1/src/pytest_dbt_macros/vendored/global_project/generate_series.sql +53 -0
  70. pytest_dbt_macros-0.2.1/src/pytest_dbt_macros/vendored/global_project/hash.sql +7 -0
  71. pytest_dbt_macros-0.2.1/src/pytest_dbt_macros/vendored/global_project/intersect.sql +9 -0
  72. pytest_dbt_macros-0.2.1/src/pytest_dbt_macros/vendored/global_project/last_day.sql +15 -0
  73. pytest_dbt_macros-0.2.1/src/pytest_dbt_macros/vendored/global_project/length.sql +11 -0
  74. pytest_dbt_macros-0.2.1/src/pytest_dbt_macros/vendored/global_project/listagg.sql +30 -0
  75. pytest_dbt_macros-0.2.1/src/pytest_dbt_macros/vendored/global_project/literal.sql +7 -0
  76. pytest_dbt_macros-0.2.1/src/pytest_dbt_macros/vendored/global_project/position.sql +11 -0
  77. pytest_dbt_macros-0.2.1/src/pytest_dbt_macros/vendored/global_project/replace.sql +14 -0
  78. pytest_dbt_macros-0.2.1/src/pytest_dbt_macros/vendored/global_project/right.sql +12 -0
  79. pytest_dbt_macros-0.2.1/src/pytest_dbt_macros/vendored/global_project/safe_cast.sql +9 -0
  80. pytest_dbt_macros-0.2.1/src/pytest_dbt_macros/vendored/global_project/split_part.sql +26 -0
  81. pytest_dbt_macros-0.2.1/src/pytest_dbt_macros/vendored/postgres/LICENSE +201 -0
  82. pytest_dbt_macros-0.2.1/src/pytest_dbt_macros/vendored/postgres/_timestamps.sql +20 -0
  83. pytest_dbt_macros-0.2.1/src/pytest_dbt_macros/vendored/postgres/any_value.sql +7 -0
  84. pytest_dbt_macros-0.2.1/src/pytest_dbt_macros/vendored/postgres/columns_spec_ddl.sql +0 -0
  85. pytest_dbt_macros-0.2.1/src/pytest_dbt_macros/vendored/postgres/dateadd.sql +5 -0
  86. pytest_dbt_macros-0.2.1/src/pytest_dbt_macros/vendored/postgres/datediff.sql +32 -0
  87. pytest_dbt_macros-0.2.1/src/pytest_dbt_macros/vendored/postgres/equals.sql +7 -0
  88. pytest_dbt_macros-0.2.1/src/pytest_dbt_macros/vendored/postgres/last_day.sql +14 -0
  89. pytest_dbt_macros-0.2.1/src/pytest_dbt_macros/vendored/postgres/listagg.sql +23 -0
  90. pytest_dbt_macros-0.2.1/src/pytest_dbt_macros/vendored/postgres/split_part.sql +9 -0
  91. pytest_dbt_macros-0.2.1/src/pytest_dbt_macros/vendored/snowflake/LICENSE +201 -0
  92. pytest_dbt_macros-0.2.1/src/pytest_dbt_macros/vendored/snowflake/array_construct.sql +3 -0
  93. pytest_dbt_macros-0.2.1/src/pytest_dbt_macros/vendored/snowflake/bool_or.sql +5 -0
  94. pytest_dbt_macros-0.2.1/src/pytest_dbt_macros/vendored/snowflake/cast.sql +9 -0
  95. pytest_dbt_macros-0.2.1/src/pytest_dbt_macros/vendored/snowflake/equals.sql +7 -0
  96. pytest_dbt_macros-0.2.1/src/pytest_dbt_macros/vendored/snowflake/escape_single_quotes.sql +4 -0
  97. pytest_dbt_macros-0.2.1/src/pytest_dbt_macros/vendored/snowflake/optional.sql +16 -0
  98. pytest_dbt_macros-0.2.1/src/pytest_dbt_macros/vendored/snowflake/right.sql +12 -0
  99. pytest_dbt_macros-0.2.1/src/pytest_dbt_macros/vendored/snowflake/safe_cast.sql +13 -0
  100. pytest_dbt_macros-0.2.1/src/pytest_dbt_macros/vendored/snowflake/timestamps.sql +20 -0
  101. pytest_dbt_macros-0.2.1/tests/baselines/VERSIONS.txt +7 -0
  102. pytest_dbt_macros-0.2.1/tests/baselines/bigquery/concat.sql +1 -0
  103. pytest_dbt_macros-0.2.1/tests/baselines/bigquery/dateadd.sql +7 -0
  104. pytest_dbt_macros-0.2.1/tests/baselines/bigquery/datediff.sql +9 -0
  105. pytest_dbt_macros-0.2.1/tests/baselines/bigquery/deduplicate.sql +11 -0
  106. pytest_dbt_macros-0.2.1/tests/baselines/bigquery/generate_series.sql +43 -0
  107. pytest_dbt_macros-0.2.1/tests/baselines/bigquery/generate_surrogate_key.sql +1 -0
  108. pytest_dbt_macros-0.2.1/tests/baselines/bigquery/get_url_host.sql +46 -0
  109. pytest_dbt_macros-0.2.1/tests/baselines/bigquery/get_url_parameter.sql +19 -0
  110. pytest_dbt_macros-0.2.1/tests/baselines/bigquery/haversine_distance.sql +9 -0
  111. pytest_dbt_macros-0.2.1/tests/baselines/bigquery/pivot.sql +32 -0
  112. pytest_dbt_macros-0.2.1/tests/baselines/bigquery/project_to_text.sql +1 -0
  113. pytest_dbt_macros-0.2.1/tests/baselines/bigquery/project_var.sql +1 -0
  114. pytest_dbt_macros-0.2.1/tests/baselines/bigquery/safe_add.sql +3 -0
  115. pytest_dbt_macros-0.2.1/tests/baselines/bigquery/safe_divide_overridden.sql +1 -0
  116. pytest_dbt_macros-0.2.1/tests/baselines/bigquery/safe_subtract.sql +2 -0
  117. pytest_dbt_macros-0.2.1/tests/baselines/bigquery/type_string.sql +1 -0
  118. pytest_dbt_macros-0.2.1/tests/baselines/bigquery/width_bucket.sql +20 -0
  119. pytest_dbt_macros-0.2.1/tests/baselines/cases.json +19 -0
  120. pytest_dbt_macros-0.2.1/tests/baselines/duckdb/concat.sql +1 -0
  121. pytest_dbt_macros-0.2.1/tests/baselines/duckdb/dateadd.sql +3 -0
  122. pytest_dbt_macros-0.2.1/tests/baselines/duckdb/datediff.sql +3 -0
  123. pytest_dbt_macros-0.2.1/tests/baselines/duckdb/deduplicate.sql +16 -0
  124. pytest_dbt_macros-0.2.1/tests/baselines/duckdb/generate_series.sql +43 -0
  125. pytest_dbt_macros-0.2.1/tests/baselines/duckdb/generate_surrogate_key.sql +1 -0
  126. pytest_dbt_macros-0.2.1/tests/baselines/duckdb/get_url_host.sql +34 -0
  127. pytest_dbt_macros-0.2.1/tests/baselines/duckdb/get_url_parameter.sql +5 -0
  128. pytest_dbt_macros-0.2.1/tests/baselines/duckdb/haversine_distance.sql +7 -0
  129. pytest_dbt_macros-0.2.1/tests/baselines/duckdb/pivot.sql +32 -0
  130. pytest_dbt_macros-0.2.1/tests/baselines/duckdb/project_to_text.sql +1 -0
  131. pytest_dbt_macros-0.2.1/tests/baselines/duckdb/project_var.sql +1 -0
  132. pytest_dbt_macros-0.2.1/tests/baselines/duckdb/safe_add.sql +3 -0
  133. pytest_dbt_macros-0.2.1/tests/baselines/duckdb/safe_divide_overridden.sql +1 -0
  134. pytest_dbt_macros-0.2.1/tests/baselines/duckdb/safe_subtract.sql +2 -0
  135. pytest_dbt_macros-0.2.1/tests/baselines/duckdb/type_string.sql +1 -0
  136. pytest_dbt_macros-0.2.1/tests/baselines/duckdb/width_bucket.sql +26 -0
  137. pytest_dbt_macros-0.2.1/tests/baselines/postgres/concat.sql +1 -0
  138. pytest_dbt_macros-0.2.1/tests/baselines/postgres/dateadd.sql +4 -0
  139. pytest_dbt_macros-0.2.1/tests/baselines/postgres/datediff.sql +5 -0
  140. pytest_dbt_macros-0.2.1/tests/baselines/postgres/deduplicate.sql +4 -0
  141. pytest_dbt_macros-0.2.1/tests/baselines/postgres/generate_series.sql +43 -0
  142. pytest_dbt_macros-0.2.1/tests/baselines/postgres/generate_surrogate_key.sql +1 -0
  143. pytest_dbt_macros-0.2.1/tests/baselines/postgres/get_url_host.sql +58 -0
  144. pytest_dbt_macros-0.2.1/tests/baselines/postgres/get_url_parameter.sql +29 -0
  145. pytest_dbt_macros-0.2.1/tests/baselines/postgres/haversine_distance.sql +7 -0
  146. pytest_dbt_macros-0.2.1/tests/baselines/postgres/pivot.sql +32 -0
  147. pytest_dbt_macros-0.2.1/tests/baselines/postgres/project_to_text.sql +1 -0
  148. pytest_dbt_macros-0.2.1/tests/baselines/postgres/project_var.sql +1 -0
  149. pytest_dbt_macros-0.2.1/tests/baselines/postgres/safe_add.sql +3 -0
  150. pytest_dbt_macros-0.2.1/tests/baselines/postgres/safe_divide_overridden.sql +1 -0
  151. pytest_dbt_macros-0.2.1/tests/baselines/postgres/safe_subtract.sql +2 -0
  152. pytest_dbt_macros-0.2.1/tests/baselines/postgres/type_string.sql +1 -0
  153. pytest_dbt_macros-0.2.1/tests/baselines/postgres/width_bucket.sql +26 -0
  154. pytest_dbt_macros-0.2.1/tests/baselines/snowflake/concat.sql +1 -0
  155. pytest_dbt_macros-0.2.1/tests/baselines/snowflake/dateadd.sql +8 -0
  156. pytest_dbt_macros-0.2.1/tests/baselines/snowflake/datediff.sql +5 -0
  157. pytest_dbt_macros-0.2.1/tests/baselines/snowflake/deduplicate.sql +7 -0
  158. pytest_dbt_macros-0.2.1/tests/baselines/snowflake/generate_series.sql +43 -0
  159. pytest_dbt_macros-0.2.1/tests/baselines/snowflake/generate_surrogate_key.sql +1 -0
  160. pytest_dbt_macros-0.2.1/tests/baselines/snowflake/get_url_host.sql +47 -0
  161. pytest_dbt_macros-0.2.1/tests/baselines/snowflake/get_url_parameter.sql +17 -0
  162. pytest_dbt_macros-0.2.1/tests/baselines/snowflake/haversine_distance.sql +7 -0
  163. pytest_dbt_macros-0.2.1/tests/baselines/snowflake/pivot.sql +32 -0
  164. pytest_dbt_macros-0.2.1/tests/baselines/snowflake/project_to_text.sql +1 -0
  165. pytest_dbt_macros-0.2.1/tests/baselines/snowflake/project_var.sql +1 -0
  166. pytest_dbt_macros-0.2.1/tests/baselines/snowflake/safe_add.sql +3 -0
  167. pytest_dbt_macros-0.2.1/tests/baselines/snowflake/safe_divide_overridden.sql +1 -0
  168. pytest_dbt_macros-0.2.1/tests/baselines/snowflake/safe_subtract.sql +2 -0
  169. pytest_dbt_macros-0.2.1/tests/baselines/snowflake/type_string.sql +1 -0
  170. pytest_dbt_macros-0.2.1/tests/baselines/snowflake/width_bucket.sql +2 -0
  171. pytest_dbt_macros-0.2.1/tests/baselines_star/star_all.sql +3 -0
  172. pytest_dbt_macros-0.2.1/tests/baselines_star/star_except_prefix.sql +2 -0
  173. pytest_dbt_macros-0.2.1/tests/conftest.py +10 -0
  174. pytest_dbt_macros-0.2.1/tests/fixtures/project/dbt_packages/dbt_utils/LICENSE +201 -0
  175. pytest_dbt_macros-0.2.1/tests/fixtures/project/dbt_packages/dbt_utils/dbt_project.yml +11 -0
  176. pytest_dbt_macros-0.2.1/tests/fixtures/project/dbt_packages/dbt_utils/macros/generic_tests/accepted_range.sql +33 -0
  177. pytest_dbt_macros-0.2.1/tests/fixtures/project/dbt_packages/dbt_utils/macros/generic_tests/at_least_one.sql +48 -0
  178. pytest_dbt_macros-0.2.1/tests/fixtures/project/dbt_packages/dbt_utils/macros/generic_tests/cardinality_equality.sql +53 -0
  179. pytest_dbt_macros-0.2.1/tests/fixtures/project/dbt_packages/dbt_utils/macros/generic_tests/equal_rowcount.sql +76 -0
  180. pytest_dbt_macros-0.2.1/tests/fixtures/project/dbt_packages/dbt_utils/macros/generic_tests/equality.sql +166 -0
  181. pytest_dbt_macros-0.2.1/tests/fixtures/project/dbt_packages/dbt_utils/macros/generic_tests/expression_is_true.sql +18 -0
  182. pytest_dbt_macros-0.2.1/tests/fixtures/project/dbt_packages/dbt_utils/macros/generic_tests/fewer_rows_than.sql +80 -0
  183. pytest_dbt_macros-0.2.1/tests/fixtures/project/dbt_packages/dbt_utils/macros/generic_tests/mutually_exclusive_ranges.sql +97 -0
  184. pytest_dbt_macros-0.2.1/tests/fixtures/project/dbt_packages/dbt_utils/macros/generic_tests/not_accepted_values.sql +37 -0
  185. pytest_dbt_macros-0.2.1/tests/fixtures/project/dbt_packages/dbt_utils/macros/generic_tests/not_constant.sql +27 -0
  186. pytest_dbt_macros-0.2.1/tests/fixtures/project/dbt_packages/dbt_utils/macros/generic_tests/not_empty_string.sql +39 -0
  187. pytest_dbt_macros-0.2.1/tests/fixtures/project/dbt_packages/dbt_utils/macros/generic_tests/not_null_proportion.sql +34 -0
  188. pytest_dbt_macros-0.2.1/tests/fixtures/project/dbt_packages/dbt_utils/macros/generic_tests/recency.sql +46 -0
  189. pytest_dbt_macros-0.2.1/tests/fixtures/project/dbt_packages/dbt_utils/macros/generic_tests/relationships_where.sql +51 -0
  190. pytest_dbt_macros-0.2.1/tests/fixtures/project/dbt_packages/dbt_utils/macros/generic_tests/sequential_values.sql +42 -0
  191. pytest_dbt_macros-0.2.1/tests/fixtures/project/dbt_packages/dbt_utils/macros/generic_tests/unique_combination_of_columns.sql +37 -0
  192. pytest_dbt_macros-0.2.1/tests/fixtures/project/dbt_packages/dbt_utils/macros/jinja_helpers/_is_ephemeral.sql +16 -0
  193. pytest_dbt_macros-0.2.1/tests/fixtures/project/dbt_packages/dbt_utils/macros/jinja_helpers/_is_relation.sql +5 -0
  194. pytest_dbt_macros-0.2.1/tests/fixtures/project/dbt_packages/dbt_utils/macros/jinja_helpers/log_info.sql +7 -0
  195. pytest_dbt_macros-0.2.1/tests/fixtures/project/dbt_packages/dbt_utils/macros/jinja_helpers/pretty_log_format.sql +7 -0
  196. pytest_dbt_macros-0.2.1/tests/fixtures/project/dbt_packages/dbt_utils/macros/jinja_helpers/pretty_time.sql +7 -0
  197. pytest_dbt_macros-0.2.1/tests/fixtures/project/dbt_packages/dbt_utils/macros/jinja_helpers/slugify.sql +18 -0
  198. pytest_dbt_macros-0.2.1/tests/fixtures/project/dbt_packages/dbt_utils/macros/sql/date_spine.sql +75 -0
  199. pytest_dbt_macros-0.2.1/tests/fixtures/project/dbt_packages/dbt_utils/macros/sql/deduplicate.sql +110 -0
  200. pytest_dbt_macros-0.2.1/tests/fixtures/project/dbt_packages/dbt_utils/macros/sql/generate_series.sql +53 -0
  201. pytest_dbt_macros-0.2.1/tests/fixtures/project/dbt_packages/dbt_utils/macros/sql/generate_surrogate_key.sql +29 -0
  202. pytest_dbt_macros-0.2.1/tests/fixtures/project/dbt_packages/dbt_utils/macros/sql/get_column_values.sql +65 -0
  203. pytest_dbt_macros-0.2.1/tests/fixtures/project/dbt_packages/dbt_utils/macros/sql/get_filtered_columns_in_relation.sql +25 -0
  204. pytest_dbt_macros-0.2.1/tests/fixtures/project/dbt_packages/dbt_utils/macros/sql/get_query_results_as_dict.sql +26 -0
  205. pytest_dbt_macros-0.2.1/tests/fixtures/project/dbt_packages/dbt_utils/macros/sql/get_relations_by_pattern.sql +32 -0
  206. pytest_dbt_macros-0.2.1/tests/fixtures/project/dbt_packages/dbt_utils/macros/sql/get_relations_by_prefix.sql +32 -0
  207. pytest_dbt_macros-0.2.1/tests/fixtures/project/dbt_packages/dbt_utils/macros/sql/get_single_value.sql +33 -0
  208. pytest_dbt_macros-0.2.1/tests/fixtures/project/dbt_packages/dbt_utils/macros/sql/get_table_types_sql.sql +32 -0
  209. pytest_dbt_macros-0.2.1/tests/fixtures/project/dbt_packages/dbt_utils/macros/sql/get_tables_by_pattern_sql.sql +96 -0
  210. pytest_dbt_macros-0.2.1/tests/fixtures/project/dbt_packages/dbt_utils/macros/sql/get_tables_by_prefix_sql.sql +14 -0
  211. pytest_dbt_macros-0.2.1/tests/fixtures/project/dbt_packages/dbt_utils/macros/sql/groupby.sql +11 -0
  212. pytest_dbt_macros-0.2.1/tests/fixtures/project/dbt_packages/dbt_utils/macros/sql/haversine_distance.sql +51 -0
  213. pytest_dbt_macros-0.2.1/tests/fixtures/project/dbt_packages/dbt_utils/macros/sql/nullcheck.sql +21 -0
  214. pytest_dbt_macros-0.2.1/tests/fixtures/project/dbt_packages/dbt_utils/macros/sql/nullcheck_table.sql +14 -0
  215. pytest_dbt_macros-0.2.1/tests/fixtures/project/dbt_packages/dbt_utils/macros/sql/pivot.sql +86 -0
  216. pytest_dbt_macros-0.2.1/tests/fixtures/project/dbt_packages/dbt_utils/macros/sql/safe_add.sql +28 -0
  217. pytest_dbt_macros-0.2.1/tests/fixtures/project/dbt_packages/dbt_utils/macros/sql/safe_divide.sql +7 -0
  218. pytest_dbt_macros-0.2.1/tests/fixtures/project/dbt_packages/dbt_utils/macros/sql/safe_subtract.sql +28 -0
  219. pytest_dbt_macros-0.2.1/tests/fixtures/project/dbt_packages/dbt_utils/macros/sql/star.sql +51 -0
  220. pytest_dbt_macros-0.2.1/tests/fixtures/project/dbt_packages/dbt_utils/macros/sql/surrogate_key.sql +20 -0
  221. pytest_dbt_macros-0.2.1/tests/fixtures/project/dbt_packages/dbt_utils/macros/sql/union.sql +134 -0
  222. pytest_dbt_macros-0.2.1/tests/fixtures/project/dbt_packages/dbt_utils/macros/sql/unpivot.sql +67 -0
  223. pytest_dbt_macros-0.2.1/tests/fixtures/project/dbt_packages/dbt_utils/macros/sql/width_bucket.sql +34 -0
  224. pytest_dbt_macros-0.2.1/tests/fixtures/project/dbt_packages/dbt_utils/macros/web/get_url_host.sql +27 -0
  225. pytest_dbt_macros-0.2.1/tests/fixtures/project/dbt_packages/dbt_utils/macros/web/get_url_parameter.sql +13 -0
  226. pytest_dbt_macros-0.2.1/tests/fixtures/project/dbt_packages/dbt_utils/macros/web/get_url_path.sql +34 -0
  227. pytest_dbt_macros-0.2.1/tests/fixtures/project/dbt_project.yml +10 -0
  228. pytest_dbt_macros-0.2.1/tests/fixtures/project/macros/project_macros.sql +30 -0
  229. pytest_dbt_macros-0.2.1/tests/fixtures/project/packages.yml +3 -0
  230. pytest_dbt_macros-0.2.1/tests/test_baselines.py +21 -0
  231. pytest_dbt_macros-0.2.1/tests/test_macros.py +81 -0
  232. pytest_dbt_macros-0.2.1/tests/test_star.py +24 -0
@@ -0,0 +1,11 @@
1
+ .baseline-venv/
2
+ .venv/
3
+ __pycache__/
4
+ *.egg-info/
5
+ dist/
6
+ build/
7
+ .pytest_cache/
8
+ target/
9
+ logs/
10
+ .env
11
+ bench/.work/
@@ -0,0 +1,8 @@
1
+ # Contributing
2
+
3
+ This project is an experiment by AI agents at start-up-team-k; humans are very welcome to file issues and PRs.
4
+
5
+ - Dev setup: `python -m venv .venv && . .venv/bin/activate && pip install -e . pytest && pytest`
6
+ - A bug where a rendered macro differs from `dbt compile` is the most valuable kind of report. Please include the macro, the `target.type`, and the dbt output. To add a regression case, put the Jinja in `tests/baselines/cases.json` and run `scripts/make_baselines.sh` (needs `uv`; no database needed), then commit the regenerated baselines.
7
+ - Keep the runtime free of dbt-core and keep the code small. Anything that needs a database connection is out of scope.
8
+ - `src/pytest_dbt_macros/vendored/` and `tests/fixtures/project/dbt_packages/` are third-party Apache-2.0 files; do not edit them by hand (see `NOTICE`).
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 start-up-team-k contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,28 @@
1
+ pytest-dbt-macros
2
+ Copyright (c) 2026 start-up-team-k contributors, MIT License (see LICENSE).
3
+
4
+ This product includes third-party files licensed under the Apache License 2.0.
5
+ Each directory below carries its upstream LICENSE file next to the files. The files are
6
+ unmodified copies of the `macros/utils/` directories (plus `timestamps.sql`) taken from the
7
+ published packages listed here (exact versions: src/pytest_dbt_macros/vendored/SOURCES.json).
8
+ They are used as dbt's built-in "dbt" macro namespace (dbt.concat, dbt.hash, dbt.dateadd, ...).
9
+ Regenerate with scripts/make_baselines.sh.
10
+
11
+ src/pytest_dbt_macros/vendored/global_project/ dbt-adapters 1.24.5 Copyright dbt Labs, Inc.
12
+ https://github.com/dbt-labs/dbt-adapters
13
+ src/pytest_dbt_macros/vendored/postgres/ dbt-postgres 1.11.0 Copyright dbt Labs, Inc.
14
+ https://github.com/dbt-labs/dbt-postgres
15
+ src/pytest_dbt_macros/vendored/snowflake/ dbt-snowflake 1.12.4 Copyright dbt Labs, Inc.
16
+ https://github.com/dbt-labs/dbt-adapters
17
+ src/pytest_dbt_macros/vendored/bigquery/ dbt-bigquery 1.12.1 Copyright dbt Labs, Inc.
18
+ https://github.com/dbt-labs/dbt-adapters
19
+ src/pytest_dbt_macros/vendored/duckdb/ dbt-duckdb 1.11.1 Apache-2.0, see its LICENSE
20
+ https://github.com/duckdb/dbt-duckdb
21
+
22
+ Test fixture (not part of the installed package):
23
+ tests/fixtures/project/dbt_packages/dbt_utils/ dbt-utils 1.4.1, Copyright dbt Labs, Inc., Apache-2.0
24
+ https://github.com/dbt-labs/dbt-utils (its LICENSE is in that directory)
25
+ tests/baselines/*/*.sql are outputs of `dbt compile` (dbt-core 1.12.6, Apache-2.0) over those macros.
26
+
27
+ The design of the Jinja stubs (ref/source/var/dispatch) follows dbt-core's documented behaviour;
28
+ no dbt-core source code is copied.
@@ -0,0 +1,203 @@
1
+ Metadata-Version: 2.5
2
+ Name: pytest-dbt-macros
3
+ Version: 0.2.1
4
+ Summary: Unit-test dbt macros (Jinja) with pytest, without dbt-core, an adapter, profiles.yml or a database.
5
+ Project-URL: Homepage, https://start-up-team-k.github.io/pytest-dbt-macros/
6
+ Project-URL: Repository, https://github.com/start-up-team-k/pytest-dbt-macros
7
+ Project-URL: Issues, https://github.com/start-up-team-k/pytest-dbt-macros/issues
8
+ Project-URL: Changelog, https://github.com/start-up-team-k/pytest-dbt-macros/blob/main/CHANGELOG.md
9
+ License-Expression: MIT
10
+ License-File: LICENSE
11
+ License-File: NOTICE
12
+ Keywords: analytics-engineering,dbt,dbt-macros,jinja,pytest,pytest-plugin,sql,unit-testing
13
+ Classifier: Framework :: Pytest
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: License :: OSI Approved :: MIT License
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3.10
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Topic :: Software Development :: Testing
21
+ Requires-Python: >=3.10
22
+ Requires-Dist: jinja2>=3.1
23
+ Requires-Dist: pytest>=7
24
+ Requires-Dist: pyyaml>=6
25
+ Requires-Dist: sqlglot>=25
26
+ Description-Content-Type: text/markdown
27
+
28
+ # pytest-dbt-macros
29
+
30
+ Unit-test dbt macros (Jinja) with pytest, **without dbt-core, an adapter, `profiles.yml` or a database**.
31
+
32
+ > This is an open-source experiment built by AI agents at start-up-team-k. It is v0.1: expect rough edges, and
33
+ > issues and feedback are welcome.
34
+
35
+ ## Why
36
+
37
+ Shared dbt macros grow, branch per warehouse (`adapter.dispatch`), and are hard to test. dbt's built-in unit tests
38
+ cover SQL models only ([dbt-labs/dbt#10547](https://github.com/dbt-labs/dbt/issues/10547) asks for macro tests).
39
+ [pytest-dbt-core](https://github.com/godatadriven/pytest-dbt-core) tests macros with pytest but builds on dbt-core,
40
+ an adapter package and a profile. This plugin instead re-implements the small part of dbt's Jinja context that macros
41
+ need (`ref`, `var`, `target`, `adapter.dispatch`, ...), so a test is: load macros, call, compare SQL strings.
42
+ The same approach is used by [SQLFluff's Jinja templater](https://docs.sqlfluff.com/en/stable/configuration/templating/jinja.html)
43
+ (Apache/MIT-style mocks); here it is packaged for pytest and checked against real `dbt compile` output.
44
+
45
+ ## Install
46
+
47
+ Not on PyPI yet (publishing is pending); install from GitHub. Python >= 3.10. Examples: [`examples/`](examples/) (dbt-utils multi-target project, GitHub Actions workflow). Docs page: https://start-up-team-k.github.io/pytest-dbt-macros/ .
48
+
49
+ ```bash
50
+ python -m venv .venv && . .venv/bin/activate
51
+ pip install pytest git+https://github.com/start-up-team-k/pytest-dbt-macros
52
+ ```
53
+
54
+ Runtime dependencies: `jinja2`, `pyyaml`, `pytest`, `sqlglot`. dbt-core is **not** installed or imported.
55
+
56
+ ## Quick start
57
+
58
+ Create a tiny dbt-style project (or use your existing one: run pytest from the folder that has `dbt_project.yml`):
59
+
60
+ ```bash
61
+ mkdir demo && cd demo && mkdir macros
62
+ printf 'name: demo\n' > dbt_project.yml
63
+ cat > macros/money.sql <<'SQL'
64
+ {% macro cents_to_dollars(col) -%}
65
+ {{ return(adapter.dispatch('cents_to_dollars')(col)) }}
66
+ {%- endmacro %}
67
+
68
+ {% macro default__cents_to_dollars(col) -%}
69
+ ({{ col }} / 100.0)
70
+ {%- endmacro %}
71
+
72
+ {% macro bigquery__cents_to_dollars(col) -%}
73
+ safe_divide({{ col }}, 100)
74
+ {%- endmacro %}
75
+
76
+ {% macro require_col(col) -%}
77
+ {%- if not col -%}{{ exceptions.raise_compiler_error("col is required") }}{%- endif -%}
78
+ {{ col }}
79
+ {%- endmacro %}
80
+ SQL
81
+ cat > test_money.py <<'PY'
82
+ import pytest
83
+ from pytest_dbt_macros import CompilationError, assert_sql_equal
84
+
85
+
86
+ def test_default(dbt_macros):
87
+ assert_sql_equal(dbt_macros.cents_to_dollars("amount"), "(amount / 100.0)")
88
+
89
+
90
+ def test_bigquery_branch(dbt_macros):
91
+ dbt_macros.target["type"] = "bigquery" # what `target.type` returns inside the macros
92
+ assert_sql_equal(dbt_macros.cents_to_dollars("amount"), "safe_divide(amount, 100)")
93
+
94
+
95
+ def test_dbt_global_macro(dbt_macros): # dbt.concat etc. are bundled
96
+ assert_sql_equal(dbt_macros.render("{{ dbt.concat(['a', 'b']) }}"), "a || b")
97
+
98
+
99
+ def test_error(dbt_macros):
100
+ with pytest.raises(CompilationError, match="col is required"):
101
+ dbt_macros.require_col("")
102
+ PY
103
+ pytest -v
104
+ ```
105
+
106
+ The `dbt_macros` fixture loads, for the project in the current directory: its `macros/` folders (`macro-paths`),
107
+ every package in `dbt_packages/` (so `dbt_macros.dbt_utils.generate_surrogate_key(["a", "b"])` works after `dbt deps`),
108
+ and dbt's own cross-database macros (`dbt.concat`, `dbt.hash`, `dbt.type_string`, `dbt.dateadd`, ...).
109
+ Calling a macro returns its rendered text (or the value passed to `return(...)`).
110
+
111
+ - `dbt_macros.<macro>(...)`, `dbt_macros.<package>.<macro>(...)`, `dbt_macros.render("{{ ... }}")`
112
+ - `dbt_macros.target["type"]` / `.vars` / `.env`: change `target.type`, `var()`, `env_var()` at any time.
113
+ - `dispatch:` in `dbt_project.yml` is honoured (`macro_namespace`, `search_order`), and so is dbt's lookup order
114
+ `<adapter>__name` -> parent adapter (`redshift` -> `postgres`) -> `default__name`.
115
+ - `assert_sql_equal(actual, expected, dialect=None)` compares after sqlglot normalization (whitespace, keyword and
116
+ identifier case). If sqlglot cannot parse a fragment, it falls back to whitespace-insensitive comparison.
117
+ - To point at another folder, override the `dbt_project_dir` fixture in `conftest.py`.
118
+
119
+ ## Test
120
+
121
+ ```bash
122
+ git clone https://github.com/start-up-team-k/pytest-dbt-macros && cd pytest-dbt-macros
123
+ python -m venv .venv && . .venv/bin/activate
124
+ pip install -e . pytest
125
+ pytest
126
+ ```
127
+
128
+ `tests/test_baselines.py` renders 17 cases (dbt-utils 1.4.1 macros, dbt global macros, project macros and a
129
+ `dispatch:` override) for four `target.type`s (postgres, snowflake, bigquery, duckdb) and compares each with the SQL that
130
+ `dbt compile` produced (stored in `tests/baselines/<target>/`). Versions used: see `tests/baselines/VERSIONS.txt`
131
+ (dbt-core 1.12.6, dbt-postgres 1.11.0, dbt-snowflake 1.12.4, dbt-bigquery 1.12.1, dbt-duckdb 1.11.1, dbt-utils 1.4.1).
132
+ To regenerate (needs [uv](https://docs.astral.sh/uv/) and network, no database): `scripts/make_baselines.sh`.
133
+
134
+ ## How dbt's built-in macros are handled
135
+
136
+ dbt-utils calls `dbt.concat`, `dbt.hash`, `dbt.dateadd`, ... which live in dbt-adapters and the adapter packages.
137
+ Instead of importing them (which would need dbt-core), the plugin **bundles unmodified copies** of the `macros/utils/`
138
+ folders (plus `timestamps.sql`) of dbt-adapters 1.24.5, dbt-postgres 1.11.0, dbt-snowflake 1.12.4, dbt-bigquery 1.12.1
139
+ and dbt-duckdb 1.11.1 (all Apache-2.0) in `src/pytest_dbt_macros/vendored/`. Each folder keeps its upstream LICENSE;
140
+ see `NOTICE`. Other adapters fall back to `default__` macros, which may not match what that adapter really does.
141
+
142
+ ## Comparison
143
+
144
+ The same five checks (`dbt_utils.generate_surrogate_key`, `dbt_utils.deduplicate`, `dbt_utils.haversine_distance`,
145
+ `dbt.dateadd`, `dbt.datediff`; dbt-utils 1.4.1, `target.type` = duckdb) written three ways. Everything is in
146
+ [`bench/`](bench/) and reproduced by [`bench/run.sh`](bench/run.sh) (needs `uv` and network, no database server).
147
+ Measured 2026-11-03 on macOS (Darwin 25.6.0), Apple M4, Python 3.12, fresh uv venvs, dbt-core 1.12.6, dbt-duckdb 1.11.1.
148
+
149
+ | | (a) pytest-dbt-macros | (b) pytest-dbt-core 0.2.4 + dbt-duckdb | (c) dbt unit tests (dummy models) + dbt-duckdb |
150
+ |---|---|---|---|
151
+ | Packages installed (`uv pip freeze` lines) | 12 | 64 | 59 |
152
+ | `site-packages` size | 17.9 MB | 166.0 MB | 157.4 MB |
153
+ | Config files you write | 1 (`dbt_project.yml`) | 3 (`dbt_project.yml`, `profiles.yml`, `packages.yml`) | 4 (same three + `unit_tests.yml`), plus 7 dummy model `.sql` files |
154
+ | Test code lines | 38 | 42 | 51 (38 YAML + 13 SQL) |
155
+ | Wall time, mean of 3 runs (whole process) | 0.214 s | 1.149 s | 2.395 s |
156
+ | Several `target.type` in one run | yes: `dbt_macros.target["type"] = ...` per test (3 targets in `bench/a_pytest_dbt_macros/test_multi_target.py`) | no: one `--dbt-target` per pytest process; each non-DuckDB type needs its adapter package and a profile it can connect with | no: one `--target` per `dbt build`; same adapter requirement |
157
+ | What is checked | rendered SQL string | rendered SQL string | result of executing the SQL on DuckDB |
158
+
159
+ Notes (facts only):
160
+ - (b) works with the latest dbt-core (1.12.6) and Python 3.12; 5/5 pass. It needs `--profiles-dir` (without it
161
+ pytest-dbt-core 0.2.4 raises `TypeError: expected str, bytes or os.PathLike object, not NoneType`), and it does not
162
+ install `pytest` itself. Its last release is 2024-06-04.
163
+ - The dbt-based setups need `dbt deps` once (not timed). (c) also builds the dummy views in a DuckDB file on each run.
164
+ - Times include interpreter start-up and imports; the first (untimed) run per setup warms bytecode caches.
165
+ (a)/(b) timings run only the five-check file; (c) runs `dbt build` (7 views + 5 unit tests).
166
+ - (b)/(c) were not tried on non-DuckDB adapters: their fixtures/commands open a connection to the warehouse.
167
+ - Compare with real warehouses: only (c) runs SQL; (a) and (b) compare strings. Raw numbers: `bench/run.sh` output.
168
+
169
+ ## Scope
170
+
171
+ Does:
172
+ - Render macros from your project and from installed packages to SQL strings, call them from Python.
173
+ - Stubs: `ref`, `source`, `var`, `env_var`, `target`, `config`, `log`, `return`, `exceptions.*`, `adapter.dispatch/type/quote`,
174
+ `api.Column.translate_type/numeric_type`, `modules`, `execute`, `dbt_version`.
175
+ - Declare a relation's columns, e.g. `dbt_macros.columns["users"] = ["id", "name"]`; then `ref('users')` works with
176
+ `adapter.get_columns_in_relation` and `dbt_utils.star(ref('users'))` renders (checked against `dbt compile` output on DuckDB
177
+ in `tests/test_star.py`). Names only: no column types.
178
+ - Check cross-database branches by switching `target.type`; assert expected errors with `pytest.raises(CompilationError)`.
179
+
180
+ Does not (yet):
181
+ - Run the SQL: no DuckDB execution of rendered SQL (planned, not implemented).
182
+ - Anything that needs a database: `run_query`, `statement`, `get_column_values`, `date_spine`. `union_relations` also
183
+ fails (needs column types). Columns can be declared by hand for `adapter.get_columns_in_relation` (see below).
184
+ - Models, materializations, hooks, `{% test %}` blocks (parsed and ignored), snapshots, docs blocks.
185
+ - Quoted, fully-qualified relations: `ref('x')` renders as `x`, `source('s', 't')` as `s.t`.
186
+ - dbt Fusion.
187
+
188
+ ## Limitations
189
+
190
+ - Fidelity: this is a re-implementation of dbt's Jinja context, not dbt. Known differences: relations render unquoted and
191
+ without database/schema; only the context names listed above exist (no `this`, `model`, `graph`, `flags`,
192
+ `modules.pytz`, ...), so macros using them fail with an `UndefinedError`; `var()` scoping is simplified (project-level
193
+ `vars:` plus `vars=` you pass; no `--vars` or package-scoped lookups beyond the root project's own); `adapter.behavior`
194
+ flags are not available; `target` has only `type`, `name`, `schema`, `database`, `threads`.
195
+ - Baselines cover 17 cases on 4 targets compared against dbt-core 1.12.6 only. Other dbt versions or macros may differ.
196
+ - The bundled dbt macros are pinned to the versions above and are not updated automatically.
197
+ - Some dbt global macros are implemented in Python by an adapter rather than in SQL, so the bundle has no version of
198
+ them. Example: `dbt.current_timestamp()` with `target.type = "duckdb"` fails with "not implemented for adapter duckdb"
199
+ ([#1](https://github.com/start-up-team-k/pytest-dbt-macros/issues/1)).
200
+
201
+ ## License
202
+
203
+ MIT (see `LICENSE`). Bundled third-party files are Apache-2.0 (see `NOTICE`).
@@ -0,0 +1,176 @@
1
+ # pytest-dbt-macros
2
+
3
+ Unit-test dbt macros (Jinja) with pytest, **without dbt-core, an adapter, `profiles.yml` or a database**.
4
+
5
+ > This is an open-source experiment built by AI agents at start-up-team-k. It is v0.1: expect rough edges, and
6
+ > issues and feedback are welcome.
7
+
8
+ ## Why
9
+
10
+ Shared dbt macros grow, branch per warehouse (`adapter.dispatch`), and are hard to test. dbt's built-in unit tests
11
+ cover SQL models only ([dbt-labs/dbt#10547](https://github.com/dbt-labs/dbt/issues/10547) asks for macro tests).
12
+ [pytest-dbt-core](https://github.com/godatadriven/pytest-dbt-core) tests macros with pytest but builds on dbt-core,
13
+ an adapter package and a profile. This plugin instead re-implements the small part of dbt's Jinja context that macros
14
+ need (`ref`, `var`, `target`, `adapter.dispatch`, ...), so a test is: load macros, call, compare SQL strings.
15
+ The same approach is used by [SQLFluff's Jinja templater](https://docs.sqlfluff.com/en/stable/configuration/templating/jinja.html)
16
+ (Apache/MIT-style mocks); here it is packaged for pytest and checked against real `dbt compile` output.
17
+
18
+ ## Install
19
+
20
+ Not on PyPI yet (publishing is pending); install from GitHub. Python >= 3.10. Examples: [`examples/`](examples/) (dbt-utils multi-target project, GitHub Actions workflow). Docs page: https://start-up-team-k.github.io/pytest-dbt-macros/ .
21
+
22
+ ```bash
23
+ python -m venv .venv && . .venv/bin/activate
24
+ pip install pytest git+https://github.com/start-up-team-k/pytest-dbt-macros
25
+ ```
26
+
27
+ Runtime dependencies: `jinja2`, `pyyaml`, `pytest`, `sqlglot`. dbt-core is **not** installed or imported.
28
+
29
+ ## Quick start
30
+
31
+ Create a tiny dbt-style project (or use your existing one: run pytest from the folder that has `dbt_project.yml`):
32
+
33
+ ```bash
34
+ mkdir demo && cd demo && mkdir macros
35
+ printf 'name: demo\n' > dbt_project.yml
36
+ cat > macros/money.sql <<'SQL'
37
+ {% macro cents_to_dollars(col) -%}
38
+ {{ return(adapter.dispatch('cents_to_dollars')(col)) }}
39
+ {%- endmacro %}
40
+
41
+ {% macro default__cents_to_dollars(col) -%}
42
+ ({{ col }} / 100.0)
43
+ {%- endmacro %}
44
+
45
+ {% macro bigquery__cents_to_dollars(col) -%}
46
+ safe_divide({{ col }}, 100)
47
+ {%- endmacro %}
48
+
49
+ {% macro require_col(col) -%}
50
+ {%- if not col -%}{{ exceptions.raise_compiler_error("col is required") }}{%- endif -%}
51
+ {{ col }}
52
+ {%- endmacro %}
53
+ SQL
54
+ cat > test_money.py <<'PY'
55
+ import pytest
56
+ from pytest_dbt_macros import CompilationError, assert_sql_equal
57
+
58
+
59
+ def test_default(dbt_macros):
60
+ assert_sql_equal(dbt_macros.cents_to_dollars("amount"), "(amount / 100.0)")
61
+
62
+
63
+ def test_bigquery_branch(dbt_macros):
64
+ dbt_macros.target["type"] = "bigquery" # what `target.type` returns inside the macros
65
+ assert_sql_equal(dbt_macros.cents_to_dollars("amount"), "safe_divide(amount, 100)")
66
+
67
+
68
+ def test_dbt_global_macro(dbt_macros): # dbt.concat etc. are bundled
69
+ assert_sql_equal(dbt_macros.render("{{ dbt.concat(['a', 'b']) }}"), "a || b")
70
+
71
+
72
+ def test_error(dbt_macros):
73
+ with pytest.raises(CompilationError, match="col is required"):
74
+ dbt_macros.require_col("")
75
+ PY
76
+ pytest -v
77
+ ```
78
+
79
+ The `dbt_macros` fixture loads, for the project in the current directory: its `macros/` folders (`macro-paths`),
80
+ every package in `dbt_packages/` (so `dbt_macros.dbt_utils.generate_surrogate_key(["a", "b"])` works after `dbt deps`),
81
+ and dbt's own cross-database macros (`dbt.concat`, `dbt.hash`, `dbt.type_string`, `dbt.dateadd`, ...).
82
+ Calling a macro returns its rendered text (or the value passed to `return(...)`).
83
+
84
+ - `dbt_macros.<macro>(...)`, `dbt_macros.<package>.<macro>(...)`, `dbt_macros.render("{{ ... }}")`
85
+ - `dbt_macros.target["type"]` / `.vars` / `.env`: change `target.type`, `var()`, `env_var()` at any time.
86
+ - `dispatch:` in `dbt_project.yml` is honoured (`macro_namespace`, `search_order`), and so is dbt's lookup order
87
+ `<adapter>__name` -> parent adapter (`redshift` -> `postgres`) -> `default__name`.
88
+ - `assert_sql_equal(actual, expected, dialect=None)` compares after sqlglot normalization (whitespace, keyword and
89
+ identifier case). If sqlglot cannot parse a fragment, it falls back to whitespace-insensitive comparison.
90
+ - To point at another folder, override the `dbt_project_dir` fixture in `conftest.py`.
91
+
92
+ ## Test
93
+
94
+ ```bash
95
+ git clone https://github.com/start-up-team-k/pytest-dbt-macros && cd pytest-dbt-macros
96
+ python -m venv .venv && . .venv/bin/activate
97
+ pip install -e . pytest
98
+ pytest
99
+ ```
100
+
101
+ `tests/test_baselines.py` renders 17 cases (dbt-utils 1.4.1 macros, dbt global macros, project macros and a
102
+ `dispatch:` override) for four `target.type`s (postgres, snowflake, bigquery, duckdb) and compares each with the SQL that
103
+ `dbt compile` produced (stored in `tests/baselines/<target>/`). Versions used: see `tests/baselines/VERSIONS.txt`
104
+ (dbt-core 1.12.6, dbt-postgres 1.11.0, dbt-snowflake 1.12.4, dbt-bigquery 1.12.1, dbt-duckdb 1.11.1, dbt-utils 1.4.1).
105
+ To regenerate (needs [uv](https://docs.astral.sh/uv/) and network, no database): `scripts/make_baselines.sh`.
106
+
107
+ ## How dbt's built-in macros are handled
108
+
109
+ dbt-utils calls `dbt.concat`, `dbt.hash`, `dbt.dateadd`, ... which live in dbt-adapters and the adapter packages.
110
+ Instead of importing them (which would need dbt-core), the plugin **bundles unmodified copies** of the `macros/utils/`
111
+ folders (plus `timestamps.sql`) of dbt-adapters 1.24.5, dbt-postgres 1.11.0, dbt-snowflake 1.12.4, dbt-bigquery 1.12.1
112
+ and dbt-duckdb 1.11.1 (all Apache-2.0) in `src/pytest_dbt_macros/vendored/`. Each folder keeps its upstream LICENSE;
113
+ see `NOTICE`. Other adapters fall back to `default__` macros, which may not match what that adapter really does.
114
+
115
+ ## Comparison
116
+
117
+ The same five checks (`dbt_utils.generate_surrogate_key`, `dbt_utils.deduplicate`, `dbt_utils.haversine_distance`,
118
+ `dbt.dateadd`, `dbt.datediff`; dbt-utils 1.4.1, `target.type` = duckdb) written three ways. Everything is in
119
+ [`bench/`](bench/) and reproduced by [`bench/run.sh`](bench/run.sh) (needs `uv` and network, no database server).
120
+ Measured 2026-11-03 on macOS (Darwin 25.6.0), Apple M4, Python 3.12, fresh uv venvs, dbt-core 1.12.6, dbt-duckdb 1.11.1.
121
+
122
+ | | (a) pytest-dbt-macros | (b) pytest-dbt-core 0.2.4 + dbt-duckdb | (c) dbt unit tests (dummy models) + dbt-duckdb |
123
+ |---|---|---|---|
124
+ | Packages installed (`uv pip freeze` lines) | 12 | 64 | 59 |
125
+ | `site-packages` size | 17.9 MB | 166.0 MB | 157.4 MB |
126
+ | Config files you write | 1 (`dbt_project.yml`) | 3 (`dbt_project.yml`, `profiles.yml`, `packages.yml`) | 4 (same three + `unit_tests.yml`), plus 7 dummy model `.sql` files |
127
+ | Test code lines | 38 | 42 | 51 (38 YAML + 13 SQL) |
128
+ | Wall time, mean of 3 runs (whole process) | 0.214 s | 1.149 s | 2.395 s |
129
+ | Several `target.type` in one run | yes: `dbt_macros.target["type"] = ...` per test (3 targets in `bench/a_pytest_dbt_macros/test_multi_target.py`) | no: one `--dbt-target` per pytest process; each non-DuckDB type needs its adapter package and a profile it can connect with | no: one `--target` per `dbt build`; same adapter requirement |
130
+ | What is checked | rendered SQL string | rendered SQL string | result of executing the SQL on DuckDB |
131
+
132
+ Notes (facts only):
133
+ - (b) works with the latest dbt-core (1.12.6) and Python 3.12; 5/5 pass. It needs `--profiles-dir` (without it
134
+ pytest-dbt-core 0.2.4 raises `TypeError: expected str, bytes or os.PathLike object, not NoneType`), and it does not
135
+ install `pytest` itself. Its last release is 2024-06-04.
136
+ - The dbt-based setups need `dbt deps` once (not timed). (c) also builds the dummy views in a DuckDB file on each run.
137
+ - Times include interpreter start-up and imports; the first (untimed) run per setup warms bytecode caches.
138
+ (a)/(b) timings run only the five-check file; (c) runs `dbt build` (7 views + 5 unit tests).
139
+ - (b)/(c) were not tried on non-DuckDB adapters: their fixtures/commands open a connection to the warehouse.
140
+ - Compare with real warehouses: only (c) runs SQL; (a) and (b) compare strings. Raw numbers: `bench/run.sh` output.
141
+
142
+ ## Scope
143
+
144
+ Does:
145
+ - Render macros from your project and from installed packages to SQL strings, call them from Python.
146
+ - Stubs: `ref`, `source`, `var`, `env_var`, `target`, `config`, `log`, `return`, `exceptions.*`, `adapter.dispatch/type/quote`,
147
+ `api.Column.translate_type/numeric_type`, `modules`, `execute`, `dbt_version`.
148
+ - Declare a relation's columns, e.g. `dbt_macros.columns["users"] = ["id", "name"]`; then `ref('users')` works with
149
+ `adapter.get_columns_in_relation` and `dbt_utils.star(ref('users'))` renders (checked against `dbt compile` output on DuckDB
150
+ in `tests/test_star.py`). Names only: no column types.
151
+ - Check cross-database branches by switching `target.type`; assert expected errors with `pytest.raises(CompilationError)`.
152
+
153
+ Does not (yet):
154
+ - Run the SQL: no DuckDB execution of rendered SQL (planned, not implemented).
155
+ - Anything that needs a database: `run_query`, `statement`, `get_column_values`, `date_spine`. `union_relations` also
156
+ fails (needs column types). Columns can be declared by hand for `adapter.get_columns_in_relation` (see below).
157
+ - Models, materializations, hooks, `{% test %}` blocks (parsed and ignored), snapshots, docs blocks.
158
+ - Quoted, fully-qualified relations: `ref('x')` renders as `x`, `source('s', 't')` as `s.t`.
159
+ - dbt Fusion.
160
+
161
+ ## Limitations
162
+
163
+ - Fidelity: this is a re-implementation of dbt's Jinja context, not dbt. Known differences: relations render unquoted and
164
+ without database/schema; only the context names listed above exist (no `this`, `model`, `graph`, `flags`,
165
+ `modules.pytz`, ...), so macros using them fail with an `UndefinedError`; `var()` scoping is simplified (project-level
166
+ `vars:` plus `vars=` you pass; no `--vars` or package-scoped lookups beyond the root project's own); `adapter.behavior`
167
+ flags are not available; `target` has only `type`, `name`, `schema`, `database`, `threads`.
168
+ - Baselines cover 17 cases on 4 targets compared against dbt-core 1.12.6 only. Other dbt versions or macros may differ.
169
+ - The bundled dbt macros are pinned to the versions above and are not updated automatically.
170
+ - Some dbt global macros are implemented in Python by an adapter rather than in SQL, so the bundle has no version of
171
+ them. Example: `dbt.current_timestamp()` with `target.type = "duckdb"` fails with "not implemented for adapter duckdb"
172
+ ([#1](https://github.com/start-up-team-k/pytest-dbt-macros/issues/1)).
173
+
174
+ ## License
175
+
176
+ MIT (see `LICENSE`). Bundled third-party files are Apache-2.0 (see `NOTICE`).
@@ -0,0 +1,22 @@
1
+ # Examples
2
+
3
+ Part of an open-source experiment built by AI agents (start-up-team-k). Copy what is useful.
4
+
5
+ ## `dbt_utils_multi_target/`
6
+
7
+ A small dbt project whose macros wrap `dbt_utils.generate_surrogate_key` and branch with `adapter.dispatch`.
8
+ `test_shop.py` checks the SQL for postgres, snowflake and bigquery in one pytest run by changing `target.type`.
9
+
10
+ ```bash
11
+ cd examples/dbt_utils_multi_target
12
+ git clone --depth 1 --branch 1.4.1 https://github.com/dbt-labs/dbt-utils dbt_packages/dbt_utils # what `dbt deps` would fetch
13
+ pytest -v
14
+ ```
15
+
16
+ `dbt_packages/` is git-ignored; the clone replaces `dbt deps` so dbt-core is not needed. Expected SQL strings were
17
+ produced with dbt-utils 1.4.1 and match the baselines in `tests/baselines/`.
18
+
19
+ ## `github-actions/test-macros.yml`
20
+
21
+ Minimal GitHub Actions workflow that runs only macro tests. The `examples` job in this repo's CI runs the same steps
22
+ against the example project above.
@@ -0,0 +1,42 @@
1
+ [build-system]
2
+ requires = ["hatchling"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "pytest-dbt-macros"
7
+ version = "0.2.1"
8
+ description = "Unit-test dbt macros (Jinja) with pytest, without dbt-core, an adapter, profiles.yml or a database."
9
+ readme = "README.md"
10
+ license = "MIT"
11
+ license-files = ["LICENSE", "NOTICE"]
12
+ requires-python = ">=3.10"
13
+ dependencies = ["jinja2>=3.1", "pyyaml>=6", "pytest>=7", "sqlglot>=25"]
14
+ keywords = ["dbt", "dbt-macros", "pytest", "pytest-plugin", "jinja", "unit-testing", "analytics-engineering", "sql"]
15
+ classifiers = [
16
+ "Framework :: Pytest",
17
+ "Intended Audience :: Developers",
18
+ "License :: OSI Approved :: MIT License",
19
+ "Programming Language :: Python :: 3",
20
+ "Programming Language :: Python :: 3.10",
21
+ "Programming Language :: Python :: 3.11",
22
+ "Programming Language :: Python :: 3.12",
23
+ "Topic :: Software Development :: Testing",
24
+ ]
25
+
26
+ [project.urls]
27
+ Homepage = "https://start-up-team-k.github.io/pytest-dbt-macros/"
28
+ Repository = "https://github.com/start-up-team-k/pytest-dbt-macros"
29
+ Issues = "https://github.com/start-up-team-k/pytest-dbt-macros/issues"
30
+ Changelog = "https://github.com/start-up-team-k/pytest-dbt-macros/blob/main/CHANGELOG.md"
31
+
32
+ [project.entry-points.pytest11]
33
+ dbt_macros = "pytest_dbt_macros.plugin"
34
+
35
+ [tool.hatch.build.targets.wheel]
36
+ packages = ["src/pytest_dbt_macros"]
37
+
38
+ [tool.hatch.build.targets.sdist]
39
+ include = ["src", "tests", "scripts", "LICENSE", "NOTICE", "README.md", "CONTRIBUTING.md"]
40
+
41
+ [tool.pytest.ini_options]
42
+ testpaths = ["tests"]
@@ -0,0 +1,6 @@
1
+ # Used only to generate tests/baselines. NOT a dependency of pytest-dbt-macros.
2
+ dbt-core==1.12.6
3
+ dbt-postgres==1.11.0
4
+ dbt-snowflake==1.12.4
5
+ dbt-bigquery==1.12.1
6
+ dbt-duckdb==1.11.1
@@ -0,0 +1,126 @@
1
+ """Run inside the baseline venv (see make_baselines.sh).
2
+
3
+ 1. Copies dbt's cross-database `utils` macros (Apache-2.0) into src/pytest_dbt_macros/vendored/.
4
+ 2. For every target type, runs `dbt compile` on the fixture project, one model per case in
5
+ tests/baselines/cases.json, and stores the compiled SQL in tests/baselines/<target>/<case>.sql.
6
+ """
7
+ import json
8
+ import shutil
9
+ import subprocess
10
+ import sys
11
+ import tempfile
12
+ from importlib import metadata
13
+ from pathlib import Path
14
+
15
+ ROOT = Path(__file__).resolve().parent.parent
16
+ FIXTURE = ROOT / "tests/fixtures/project"
17
+ BASE = ROOT / "tests/baselines"
18
+ VENDORED = ROOT / "src/pytest_dbt_macros/vendored"
19
+
20
+ # target type -> profile fields (fake values; nothing connects)
21
+ PROFILES = {
22
+ "postgres": dict(host="localhost", port=5432, user="u", password="p", dbname="d", schema="s"),
23
+ "snowflake": dict(account="a", user="u", password="p", database="d", warehouse="w", schema="s"),
24
+ # BigQuery opens a client eagerly, so give it a throwaway service-account key (never used online).
25
+ "bigquery": dict(method="service-account-json", project="p", dataset="s", keyfile_json=None),
26
+ "duckdb": dict(path=":memory:", schema="s"),
27
+ }
28
+ # vendored directory (inside site-packages/dbt/include) -> pip distribution it comes from
29
+ SOURCES = {
30
+ "global_project": "dbt-adapters", "postgres": "dbt-postgres", "snowflake": "dbt-snowflake",
31
+ "bigquery": "dbt-bigquery", "duckdb": "dbt-duckdb",
32
+ }
33
+
34
+
35
+ def vendor():
36
+ include = Path(__import__("dbt.include", fromlist=["x"]).__path__[0])
37
+ shutil.rmtree(VENDORED, ignore_errors=True)
38
+ for d in SOURCES:
39
+ shutil.copytree(include / d / "macros" / "utils", VENDORED / d)
40
+ # current_timestamp & friends
41
+ shutil.copy(include / "global_project/macros/adapters/timestamps.sql", VENDORED / "global_project/_timestamps.sql")
42
+ shutil.copy(include / "postgres/macros/timestamps.sql", VENDORED / "postgres/_timestamps.sql")
43
+ for d, dist in SOURCES.items(): # keep each upstream's own license text next to its files
44
+ d_ = metadata.distribution(dist)
45
+ shutil.copy(d_.locate_file(next(f for f in d_.files if f.name == "LICENSE")), VENDORED / d / "LICENSE")
46
+ versions = {d: f"{dist}=={metadata.version(dist)}" for d, dist in SOURCES.items()}
47
+ (VENDORED / "SOURCES.json").write_text(json.dumps(versions, indent=2) + "\n")
48
+
49
+
50
+ def fake_service_account():
51
+ from cryptography.hazmat.primitives import serialization
52
+ from cryptography.hazmat.primitives.asymmetric import rsa
53
+
54
+ pem = rsa.generate_private_key(public_exponent=65537, key_size=2048).private_bytes(
55
+ serialization.Encoding.PEM, serialization.PrivateFormat.PKCS8, serialization.NoEncryption()
56
+ )
57
+ return {
58
+ "type": "service_account", "project_id": "p", "private_key_id": "x", "private_key": pem.decode(),
59
+ "client_email": "x@p.iam.gserviceaccount.com", "client_id": "1",
60
+ "token_uri": "https://oauth2.googleapis.com/token",
61
+ }
62
+
63
+
64
+ def compile_target(target, cases, work):
65
+ proj = work / target
66
+ shutil.copytree(FIXTURE, proj)
67
+ (proj / "models").mkdir()
68
+ for name, expr in cases.items():
69
+ (proj / "models" / f"{name}.sql").write_text(expr)
70
+ fields = {**PROFILES[target]}
71
+ if target == "bigquery":
72
+ fields["keyfile_json"] = fake_service_account()
73
+ profiles = {"cedar_fixture": {"target": target, "outputs": {target: {"type": target, "threads": 1, **fields}}}}
74
+ pdir = work / f"profiles_{target}"
75
+ pdir.mkdir()
76
+ (pdir / "profiles.yml").write_text(json.dumps(profiles)) # JSON is valid YAML
77
+ subprocess.run(
78
+ [sys.executable, "-m", "dbt.cli.main", "compile", "--no-populate-cache",
79
+ "--project-dir", str(proj), "--profiles-dir", str(pdir)],
80
+ check=True,
81
+ )
82
+ out = BASE / target
83
+ shutil.rmtree(out, ignore_errors=True)
84
+ out.mkdir(parents=True)
85
+ for name in cases:
86
+ shutil.copy(proj / "target/compiled/cedar_fixture/models" / f"{name}.sql", out / f"{name}.sql")
87
+
88
+
89
+ STAR_CASES = { # need a real table: only DuckDB (a local file) can be created without a server
90
+ "star_all": "{{ dbt_utils.star(ref('users')) }}",
91
+ "star_except_prefix": "{{ dbt_utils.star(ref('users'), except=['email'], prefix='u_') }}",
92
+ }
93
+
94
+
95
+ def star_baselines(work):
96
+ """`dbt run` creates table `users` (id, name, email) in a temp DuckDB file, then `dbt compile` renders star()."""
97
+ proj = work / "star"
98
+ shutil.copytree(FIXTURE, proj)
99
+ (proj / "models").mkdir()
100
+ (proj / "models/users.sql").write_text("select 1 as id, 'x' as name, 'y' as email")
101
+ for name, expr in STAR_CASES.items():
102
+ (proj / "models" / f"{name}.sql").write_text(expr)
103
+ out = {"type": "duckdb", "threads": 1, "path": str(work / "star.duckdb")}
104
+ (work / "profiles.yml").write_text(json.dumps({"cedar_fixture": {"target": "d", "outputs": {"d": out}}}))
105
+ for cmd, extra in (("run", ["--select", "users"]), ("compile", [])):
106
+ subprocess.run([sys.executable, "-m", "dbt.cli.main", cmd, "--project-dir", str(proj),
107
+ "--profiles-dir", str(work), *extra], check=True)
108
+ dest = ROOT / "tests/baselines_star"
109
+ shutil.rmtree(dest, ignore_errors=True)
110
+ dest.mkdir()
111
+ for name in STAR_CASES:
112
+ shutil.copy(proj / "target/compiled/cedar_fixture/models" / f"{name}.sql", dest / f"{name}.sql")
113
+
114
+
115
+ if __name__ == "__main__":
116
+ vendor()
117
+ cases = json.loads((BASE / "cases.json").read_text())
118
+ with tempfile.TemporaryDirectory() as tmp:
119
+ for t in PROFILES:
120
+ compile_target(t, cases, Path(tmp))
121
+ (Path(tmp) / "s").mkdir()
122
+ star_baselines(Path(tmp) / "s")
123
+ dists = ["dbt-core", "dbt-adapters", "dbt-postgres", "dbt-snowflake", "dbt-bigquery", "dbt-duckdb"]
124
+ lines = [f"{d}=={metadata.version(d)}" for d in dists]
125
+ lines.append("dbt-utils==1.4.1 (git tag 1.4.1, copied to tests/fixtures/project/dbt_packages/dbt_utils)")
126
+ (BASE / "VERSIONS.txt").write_text("\n".join(lines) + "\n")