[{"data":1,"prerenderedAt":247},["ShallowReactive",2],{"blog-/blog/dbt-bdd-financial-reporting":3},{"id":4,"title":5,"body":6,"date":236,"description":237,"extension":238,"meta":239,"navigation":147,"path":240,"seo":241,"stem":242,"tags":243,"__hash__":246},"blog/blog/dbt-bdd-financial-reporting.md","Financial reporting pipelines don't have a testing problem — they have a contract problem",{"type":7,"value":8,"toc":230},"minimark",[9,14,18,21,24,28,31,46,49,53,56,59,199,202,206,209,212,215,226],[10,11,13],"h2",{"id":12},"the-gap-nobody-names","The gap nobody names",[15,16,17],"p",{},"Walk into a data engineering team at a bank or insurer, and you'll find tests. Usually plenty of them. Schema checks, row-count assertions, null validations. The pipeline goes green, the report ships, and the compliance officer signs off.",[15,19,20],{},"Until it doesn't. Until someone notices that a transformation quietly dropped a product category three months ago, or that a rounding convention changed between two DBT models without anyone realising it had business significance.",[15,22,23],{},"The tests were passing. The business expectation was violated. These are not the same thing.",[10,25,27],{"id":26},"what-bdd-actually-changes","What BDD actually changes",[15,29,30],{},"Behaviour-Driven Development is often introduced as a testing methodology. That framing misses the point — especially in data contexts.",[15,32,33,34,38,39,38,42,45],{},"BDD's actual contribution is a forcing function for making implicit domain knowledge explicit before any code is written. When you describe expected behaviour in Gherkin — ",[35,36,37],"code",{},"Given",", ",[35,40,41],{},"When",[35,43,44],{},"Then"," — you are obliging a business analyst and an engineer to agree, in writing, on what a transformation is supposed to mean. Not just whether it runs.",[15,47,48],{},"In financial reporting, that distinction is not a nice-to-have. It's an audit requirement.",[10,50,52],{"id":51},"what-this-looks-like-in-dbt","What this looks like in DBT",[15,54,55],{},"DBT's test architecture maps onto BDD naturally. A schema test expresses a constraint. A singular test expresses a scenario. The gap is usually that teams write their tests after the model, inferring constraints from the implementation rather than deriving the implementation from stated requirements.",[15,57,58],{},"The reversal matters:",[60,61,66],"pre",{"className":62,"code":63,"language":64,"meta":65,"style":65},"language-yaml shiki shiki-themes github-light github-dark","# Not this — a post-hoc constraint check\nmodels:\n  - name: regulatory_capital_report\n    columns:\n      - name: exposure_amount\n        tests:\n          - not_null\n\n# But this — a named expectation with business provenance\ntests:\n  - name: exposure_amount_includes_off_balance_sheet_items\n    description: >\n      Per Basel III Article 111, off-balance-sheet items must be\n      converted to credit exposure equivalents before aggregation.\n","yaml","",[35,67,68,77,88,104,112,125,133,142,149,155,163,175,187,193],{"__ignoreMap":65},[69,70,73],"span",{"class":71,"line":72},"line",1,[69,74,76],{"class":75},"sJ8bj","# Not this — a post-hoc constraint check\n",[69,78,80,84],{"class":71,"line":79},2,[69,81,83],{"class":82},"s9eBZ","models",[69,85,87],{"class":86},"sVt8B",":\n",[69,89,91,94,97,100],{"class":71,"line":90},3,[69,92,93],{"class":86},"  - ",[69,95,96],{"class":82},"name",[69,98,99],{"class":86},": ",[69,101,103],{"class":102},"sZZnC","regulatory_capital_report\n",[69,105,107,110],{"class":71,"line":106},4,[69,108,109],{"class":82},"    columns",[69,111,87],{"class":86},[69,113,115,118,120,122],{"class":71,"line":114},5,[69,116,117],{"class":86},"      - ",[69,119,96],{"class":82},[69,121,99],{"class":86},[69,123,124],{"class":102},"exposure_amount\n",[69,126,128,131],{"class":71,"line":127},6,[69,129,130],{"class":82},"        tests",[69,132,87],{"class":86},[69,134,136,139],{"class":71,"line":135},7,[69,137,138],{"class":86},"          - ",[69,140,141],{"class":102},"not_null\n",[69,143,145],{"class":71,"line":144},8,[69,146,148],{"emptyLinePlaceholder":147},true,"\n",[69,150,152],{"class":71,"line":151},9,[69,153,154],{"class":75},"# But this — a named expectation with business provenance\n",[69,156,158,161],{"class":71,"line":157},10,[69,159,160],{"class":82},"tests",[69,162,87],{"class":86},[69,164,166,168,170,172],{"class":71,"line":165},11,[69,167,93],{"class":86},[69,169,96],{"class":82},[69,171,99],{"class":86},[69,173,174],{"class":102},"exposure_amount_includes_off_balance_sheet_items\n",[69,176,178,181,183],{"class":71,"line":177},12,[69,179,180],{"class":82},"    description",[69,182,99],{"class":86},[69,184,186],{"class":185},"szBVR",">\n",[69,188,190],{"class":71,"line":189},13,[69,191,192],{"class":102},"      Per Basel III Article 111, off-balance-sheet items must be\n",[69,194,196],{"class":71,"line":195},14,[69,197,198],{"class":102},"      converted to credit exposure equivalents before aggregation.\n",[15,200,201],{},"The second form is a contract. The first is a guard rail. Both have their place; only one of them tells a regulator what you intended.",[10,203,205],{"id":204},"the-platform-angle","The platform angle",[15,207,208],{},"This matters to platform engineering because data pipelines in regulated industries are shared infrastructure. Multiple product teams consume the same transformation layer. When the logic is implicit — when the \"why\" behind a transformation lives in a Jira ticket from 2019 and the memory of one senior analyst — the pipeline cannot safely evolve.",[15,210,211],{},"Codifying the business rules as BDD specs doesn't just improve test quality. It transforms the pipeline from a black box that happens to produce correct output into a documented contract that anyone can challenge, verify, and extend. That's the difference between infrastructure that teams depend on because it works and infrastructure that teams can rely on because they understand it.",[213,214],"hr",{},[15,216,217,218,225],{},"The full implementation — including a working DBT project with BDD-style tests wired to real financial reporting scenarios — is on ",[219,220,224],"a",{"href":221,"rel":222},"https://github.com/Senhaji-Rhazi-Hamza/dbt-bdd",[223],"nofollow","GitHub",".",[227,228,229],"style",{},"html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .s9eBZ, html code.shiki .s9eBZ{--shiki-default:#22863A;--shiki-dark:#85E89D}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":65,"searchDepth":79,"depth":79,"links":231},[232,233,234,235],{"id":12,"depth":79,"text":13},{"id":26,"depth":79,"text":27},{"id":51,"depth":79,"text":52},{"id":204,"depth":79,"text":205},"2025-07-10","Most data teams test whether their pipelines run. Few test whether they express the right thing. In regulated environments, that distinction is the whole game.","md",{},"/blog/dbt-bdd-financial-reporting",{"title":5,"description":237},"blog/dbt-bdd-financial-reporting",[244,245],"data engineering","platform engineering","jMDMnz7ePU_tjsHT7Dj8B4dkpDxOdPhKNLYsJvDMsjI",1771989752006]