{"id":10354,"date":"2021-11-23T08:17:24","date_gmt":"2021-11-23T08:17:24","guid":{"rendered":"https:\/\/ee.yelkdev.site\/?p=10354"},"modified":"2023-09-21T23:49:56","modified_gmt":"2023-09-21T22:49:56","slug":"writing-unit-tests-for-dbt-with-tdd","status":"publish","type":"post","link":"https:\/\/www.equalexperts.com\/blog\/our-thinking\/writing-unit-tests-for-dbt-with-tdd\/","title":{"rendered":"Writing Unit Tests for dbt &#8211; with TDD"},"content":{"rendered":"<p><span style=\"font-weight: 400;\">This blog describes the exploration that <\/span><a href=\"https:\/\/www.equalexperts.com\/blog\/author\/claudio-diniz\/\"><span style=\"font-weight: 400;\">Cl\u00e1udio Diniz<\/span><\/a> <span style=\"font-weight: 400;\">and I have been doing around the dbt tool, trying to find a way to write unit tests using TDD. You can check this <\/span><a href=\"https:\/\/www.equalexperts.com\/blog\/our-thinking\/bringing-tdd-to-the-data-warehouse\/\"><span style=\"font-weight: 400;\">post<\/span><\/a><span style=\"font-weight: 400;\"> to understand how it all started.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">This is not a tutorial on dbt, and it\u2019s not a detailed technical document on our framework. You can check our demo dbt project <\/span><a href=\"https:\/\/github.com\/EqualExperts\/dbt-unit-test-demo\"><span style=\"font-weight: 400;\">here<\/span><\/a><span style=\"font-weight: 400;\"> if you want to see the details.<\/span><\/p>\n<p><i><span style=\"font-weight: 400;\">Note: What we are calling a framework is a set of Jinja macros. Throughout this document, we will call it a framework for simplicity.<\/span><\/i><\/p>\n<h2><b>Why do we need unit tests in dbt?<\/b><\/h2>\n<p><span style=\"font-weight: 400;\">One of the software engineering practices that we follow is TDD. We strongly believe that it helps us create better code and achieve a good level of confidence in its correctness. So, why not use this in our dbt projects? <img decoding=\"async\" class=\"alignnone wp-image-10370\" src=\"https:\/\/www.equalexperts.com\/wp-content\/uploads\/2021\/11\/Tests-for-dbt-emoji.png\" alt=\"\" width=\"30\" height=\"30\" \/><\/span><\/p>\n<h3><b>Dbt is code<\/b><\/h3>\n<p><span style=\"font-weight: 400;\">A dbt project, like a \u201cregular\u201d software project, consists of several files of SQL code. And we want to be sure that the logic of this code is correct before it jumps to production.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">We think that using TDD can also help us to write better SQL code. Using TDD, we write the test, make it pass with the simplest SQL code we can think of, and then refactor it, knowing we have a test to assure it still works. It would be awesome if we could do this on our dbt projects! <\/span><\/p>\n<h3><b>But wait, dbt already has tests<\/b><\/h3>\n<p><span style=\"font-weight: 400;\">That\u2019s right, but dbt tests were mainly designed for data tests. They are used to check the correctness of the data produced by the models. We want to write unit tests on our SQL code. We want to be sure that the logic of the code is correct.<\/span><\/p>\n<h3><b>A word on <\/b><b><i>unit tests<\/i><\/b><\/h3>\n<p><span style=\"font-weight: 400;\">The line between unit and integration tests is sometimes a bit blurred. This is also true with these tests in dbt.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">We can think of a dbt model as a function, where the inputs are other models, and the output is the result of its SQL. A unit test in dbt would be a test where we provide fake inputs to a model, and then we check the results against some expectations.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">However, a model in dbt can belong to a long chain of models (see image below), each transforming the data in its own rules. We could test a model by providing fake inputs to the first models in that chain and asserting the results on the final model. We would be checking all the intermediate transformations along the way. This, on the other end, could be called an integration test.<\/span><\/p>\n<div id=\"attachment_10364\" style=\"width: 1210px\" class=\"wp-caption alignnone\"><img decoding=\"async\" aria-describedby=\"caption-attachment-10364\" class=\"wp-image-10364 size-large\" src=\"https:\/\/www.equalexperts.com\/wp-content\/uploads\/2021\/11\/Tests-for-DBT-1-1200x741.png\" alt=\"\" width=\"1200\" height=\"741\" \/><p id=\"caption-attachment-10364\" class=\"wp-caption-text\">A complex dbt model hierarchy<\/p><\/div>\n<p><span style=\"font-weight: 400;\">These integration tests are harder to write because we have to think of how the data is transformed throughout all those models until it reaches the model we want to test. However, they provide an extra level of confidence. As usual, we need to keep a good balance between these two types of tests.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">As we will see, using this definition, our framework will allow us to create both unit and integration tests.<\/span><\/p>\n<h2><b>What do you want to achieve?<\/b><\/h2>\n<p><span style=\"font-weight: 400;\">We came up with a list of requirements that we would like to fulfill when writing tests in dbt:<\/span><\/p>\n<ul>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Use fake inputs on any model<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Focus the test on what\u2019s important<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Provide fast and valuable feedback<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Write more than one test on a dbt test file<\/span><\/li>\n<\/ul>\n<p><span style=\"font-weight: 400;\">We want to write dbt tests using TDD and receive fast feedback on the results. Running one or more dbt models each time we change them, as we were doing on the previous approach, was not the best way to do it, and we wanted to remove this step.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">The goal is to write the test, write the model, and then run the test (with \u201c<\/span><i><span style=\"font-weight: 400;\">dbt test<\/span><\/i><span style=\"font-weight: 400;\">\u201d).<\/span><\/p>\n<h3><b>Use fake inputs on any model.<\/b><\/h3>\n<p><span style=\"font-weight: 400;\">In a typical dbt model hierarchy, a model is dependent on other models.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">We can test our models by providing fake inputs to its \u201c<\/span><i><span style=\"font-weight: 400;\">parent<\/span><\/i><span style=\"font-weight: 400;\">\u201d models. However, sometimes we want to go a bit higher in the hierarchy (up to the sources, if we wish to) to have a more <\/span><i><span style=\"font-weight: 400;\">integrated<\/span><\/i> <i><span style=\"font-weight: 400;\">test<\/span><\/i><span style=\"font-weight: 400;\">.<\/span><\/p>\n<h3><b>Focus the test on what\u2019s important<\/b><\/h3>\n<p><span style=\"font-weight: 400;\">We want to test our models by providing fake input only to the relevant models for the scenario being tested. It should be possible to keep other models with no data as long as they don\u2019t interfere with the test (for instance, when using a LEFT JOIN on some model).<\/span><\/p>\n<p><span style=\"font-weight: 400;\">It is also essential that we shouldn\u2019t have to specify all the columns when we provide fake input data. Only the columns that are important for the test should be set.<\/span><\/p>\n<h3><b>Provide fast and valuable feedback<\/b><\/h3>\n<p><span style=\"font-weight: 400;\">We want the test feedback to be fast and helpful. We need to understand which test is failing and why. It should present the name of the model that failed along with its description.<\/span><\/p>\n<h3><b>Write more than one test on a dbt test file<\/b><\/h3>\n<p><span style=\"font-weight: 400;\">A dbt test file usually contains just one test. It would be nice to have more than one test on the same file if they are somehow related.<\/span><\/p>\n<h2><b>How did you do it?<\/b><\/h2>\n<p><span style=\"font-weight: 400;\">In a word, with some pain (two words, I know&#8230;). Many experiments and iterations were developed and tested until we reached the state where we are now. Fortunately, the powerful Jinja macros and the dbt engine helped us achieve what we were looking for.\u00a0\u00a0<\/span><\/p>\n<p><span style=\"font-weight: 400;\">Before we run into the details of how it is done, let\u2019s have a look at how a test looks like:<\/span><\/p>\n<img decoding=\"async\" class=\"aligncenter wp-image-10363 size-full\" src=\"https:\/\/www.equalexperts.com\/wp-content\/uploads\/2021\/11\/Tests-for-DBT-2.png\" alt=\"\" width=\"800\" height=\"356\" srcset=\"https:\/\/www.equalexperts.com\/wp-content\/uploads\/2021\/11\/Tests-for-DBT-2.png 800w, https:\/\/www.equalexperts.com\/wp-content\/uploads\/2021\/11\/Tests-for-DBT-2-300x134.png 300w, https:\/\/www.equalexperts.com\/wp-content\/uploads\/2021\/11\/Tests-for-DBT-2-768x342.png 768w\" sizes=\"(max-width: 800px) 100vw, 800px\" \/>\n<p><span style=\"font-weight: 400;\">In a nutshell:<\/span><\/p>\n<p><span style=\"font-weight: 400;\">First, we define the model to be tested with the \u201c<\/span><b>test<\/b><span style=\"font-weight: 400;\">\u201d macro.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">Then we define the fake inputs using the \u201c<\/span><b><i>mock_ref<\/i><\/b><span style=\"font-weight: 400;\">\u201d or \u201c<\/span><b><i>mock_source<\/i><\/b><span style=\"font-weight: 400;\">\u201d macros.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">Finally, we describe our expectations for the model with the \u201c<\/span><b>expect<\/b><span style=\"font-weight: 400;\">\u201d macro.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">That\u2019s it!\u00a0<\/span><\/p>\n<p><span style=\"font-weight: 400;\">If we now run this test with the \u201c<\/span><b>dbt test<\/b><span style=\"font-weight: 400;\">\u201d command (assuming we have a \u201c<\/span><b>covid19_cases_per_day<\/b><span style=\"font-weight: 400;\">\u201d model), we will see this report:<\/span><\/p>\n<p><span style=\"font-weight: 400;\"><img decoding=\"async\" class=\"alignnone size-full wp-image-10362\" src=\"https:\/\/www.equalexperts.com\/wp-content\/uploads\/2021\/11\/Tests-for-DBT-3.png\" alt=\"\" width=\"919\" height=\"249\" srcset=\"https:\/\/www.equalexperts.com\/wp-content\/uploads\/2021\/11\/Tests-for-DBT-3.png 919w, https:\/\/www.equalexperts.com\/wp-content\/uploads\/2021\/11\/Tests-for-DBT-3-300x81.png 300w, https:\/\/www.equalexperts.com\/wp-content\/uploads\/2021\/11\/Tests-for-DBT-3-768x208.png 768w\" sizes=\"(max-width: 919px) 100vw, 919px\" \/>\u00a0<\/span><\/p>\n<p><span style=\"font-weight: 400;\">Now imagine we made a mistake and typed 24 instead of 25 on the expectations. We rerun the test, and now we see the test failing:<\/span><\/p>\n<img decoding=\"async\" class=\"alignnone size-full wp-image-10361\" src=\"https:\/\/www.equalexperts.com\/wp-content\/uploads\/2021\/11\/Tests-for-DBT-4.png\" alt=\"\" width=\"893\" height=\"342\" srcset=\"https:\/\/www.equalexperts.com\/wp-content\/uploads\/2021\/11\/Tests-for-DBT-4.png 893w, https:\/\/www.equalexperts.com\/wp-content\/uploads\/2021\/11\/Tests-for-DBT-4-300x115.png 300w, https:\/\/www.equalexperts.com\/wp-content\/uploads\/2021\/11\/Tests-for-DBT-4-768x294.png 768w\" sizes=\"(max-width: 893px) 100vw, 893px\" \/>\n<p><span style=\"font-weight: 400;\">The test output displays the name of the model being tested and the description of the test. This is helpful when we have several tests running with the \u201c<\/span><b>dbt test<\/b><span style=\"font-weight: 400;\">\u201d command.<\/span><\/p>\n<h2><b>How does it work?<\/b><\/h2>\n<p><span style=\"font-weight: 400;\">Our strategy is supported by these four items:<\/span><\/p>\n<ol>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">The dbt \u201c<\/span><b>render<\/b><span style=\"font-weight: 400;\">\u201d function.<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">The dbt \u201c<\/span><b>graph.nodes<\/b><span style=\"font-weight: 400;\">\u201d internal structure.<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">SQL Common Table Expressions (CTE).<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">The ability to override the dbt \u201c<\/span><b>ref<\/b><span style=\"font-weight: 400;\">\u201d macros functionality.<\/span><\/li>\n<\/ol>\n<p><span style=\"font-weight: 400;\">Let\u2019s check one by one:<\/span><\/p>\n<h3><b>1. The dbt \u201crender\u201d function<\/b><\/h3>\n<p><span style=\"font-weight: 400;\">This function returns the compiled SQL for a model. It allows us to fetch the SQL of the model being tested and the SQL for all the other models.<\/span><\/p>\n<h3><b>2. The dbt \u201cgraph.nodes\u201d internal structure<\/b><\/h3>\n<p><span style=\"font-weight: 400;\">This structure keeps track of a lot of information related to each of the dbt models in runtime. It contains the raw SQL for the model (the SQL before compilation, with the <\/span><b>ref<\/b><span style=\"font-weight: 400;\"> and other dbt macros) and the list of models from which this one depends (it contains a lot of different things, but they are not essential for us right now).<\/span><\/p>\n<h3><b>3. SQL Common Table Expressions (CTE)<\/b><\/h3>\n<p><span style=\"font-weight: 400;\">We use CTEs to build a fully compiled SQL of the model being tested. The dependencies of the model are transverse recursively to generate a group of nested CTEs that builds up the entire model.<\/span><\/p>\n<h3><b>4. The ability to override the dbt ref macro functionality<\/b><\/h3>\n<p><span style=\"font-weight: 400;\">We can override the <\/span><b>ref<\/b><span style=\"font-weight: 400;\"> macro on dbt. This allows us to change the default behavior of emitting a fully qualified table name, like \u201c<\/span><i><span style=\"font-weight: 400;\">dbt_test_demo.models.countries<\/span><\/i><span style=\"font-weight: 400;\">\u201d, to a simplified one that will match the name of the CTEs.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">Let\u2019s see an example. Imagine we have the following (oversimplified and dumb) 3 models:<\/span><\/p>\n<img decoding=\"async\" class=\"alignnone wp-image-10360 size-full\" src=\"https:\/\/www.equalexperts.com\/wp-content\/uploads\/2021\/11\/Tests-for-DBT-5.png\" alt=\"\" width=\"1194\" height=\"500\" srcset=\"https:\/\/www.equalexperts.com\/wp-content\/uploads\/2021\/11\/Tests-for-DBT-5.png 1194w, https:\/\/www.equalexperts.com\/wp-content\/uploads\/2021\/11\/Tests-for-DBT-5-300x126.png 300w, https:\/\/www.equalexperts.com\/wp-content\/uploads\/2021\/11\/Tests-for-DBT-5-768x322.png 768w\" sizes=\"(max-width: 1194px) 100vw, 1194px\" \/>\n<p><span style=\"font-weight: 400;\">If we are testing \u201c<\/span><b>model3<\/b><span style=\"font-weight: 400;\">\u201d, our framework builds the following SQL:<\/span><\/p>\n<img decoding=\"async\" class=\"alignnone wp-image-10359 size-full\" src=\"https:\/\/www.equalexperts.com\/wp-content\/uploads\/2021\/11\/Tests-for-DBT-6.png\" alt=\"\" width=\"980\" height=\"504\" srcset=\"https:\/\/www.equalexperts.com\/wp-content\/uploads\/2021\/11\/Tests-for-DBT-6.png 980w, https:\/\/www.equalexperts.com\/wp-content\/uploads\/2021\/11\/Tests-for-DBT-6-300x154.png 300w, https:\/\/www.equalexperts.com\/wp-content\/uploads\/2021\/11\/Tests-for-DBT-6-768x395.png 768w\" sizes=\"(max-width: 980px) 100vw, 980px\" \/>\n<p><span style=\"font-weight: 400;\">Notice how the SQL for \u201c<\/span><b>model3<\/b><span style=\"font-weight: 400;\">\u201d now depends only on the CTEs defined before the final SELECT. This will be the SQL that dbt will execute when running the test and later compare its results with the expectations.<\/span><\/p>\n<h3><b>What about fake inputs?<\/b><\/h3>\n<p><span style=\"font-weight: 400;\">Good question. We need to be able to <\/span><i><span style=\"font-weight: 400;\">inject<\/span><\/i><span style=\"font-weight: 400;\"> our fake inputs into this SQL. How? Again, using CTEs.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">Suppose we want to insert fake inputs on \u201c<\/span><b>model2<\/b><span style=\"font-weight: 400;\">\u201d. And assume we don\u2019t care about \u201c<\/span><b>model1<\/b><span style=\"font-weight: 400;\">\u201d because it\u2019s on a LEFT JOIN, and our test does not depend on \u201c<\/span><b>model1<\/b><span style=\"font-weight: 400;\">\u201d columns. So we don\u2019t need to define fake inputs for this model (<\/span><i><span style=\"font-weight: 400;\">focus the test on what\u2019s important<\/span><\/i><span style=\"font-weight: 400;\">).<\/span><\/p>\n<p><span style=\"font-weight: 400;\">The SQL for \u201c<\/span><b>model3<\/b><span style=\"font-weight: 400;\">\u201d defined above is wrapped with a CTE to define the fake inputs for \u201c<\/span><b>model2<\/b><span style=\"font-weight: 400;\">\u201d, like this:<\/span><\/p>\n<img decoding=\"async\" class=\"alignnone size-full wp-image-10358\" src=\"https:\/\/www.equalexperts.com\/wp-content\/uploads\/2021\/11\/Tests-for-DBT-7.png\" alt=\"\" width=\"1048\" height=\"904\" srcset=\"https:\/\/www.equalexperts.com\/wp-content\/uploads\/2021\/11\/Tests-for-DBT-7.png 1048w, https:\/\/www.equalexperts.com\/wp-content\/uploads\/2021\/11\/Tests-for-DBT-7-300x259.png 300w, https:\/\/www.equalexperts.com\/wp-content\/uploads\/2021\/11\/Tests-for-DBT-7-768x662.png 768w\" sizes=\"(max-width: 1048px) 100vw, 1048px\" \/>\n<p><span style=\"font-weight: 400;\">However, this wouldn\u2019t work. There are two CTEs named \u201c<\/span><b>model2<\/b><span style=\"font-weight: 400;\">\u201d in this SQL, and the model being tested will use the innermost one and not the one that defines the fake inputs. An extra step is needed to remove from the model SQL the CTEs used as faked inputs.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">The final SQL will then be:<\/span><\/p>\n<img decoding=\"async\" class=\"alignnone size-full wp-image-10357\" src=\"https:\/\/www.equalexperts.com\/wp-content\/uploads\/2021\/11\/Tests-for-DBT-8.png\" alt=\"\" width=\"1048\" height=\"824\" srcset=\"https:\/\/www.equalexperts.com\/wp-content\/uploads\/2021\/11\/Tests-for-DBT-8.png 1048w, https:\/\/www.equalexperts.com\/wp-content\/uploads\/2021\/11\/Tests-for-DBT-8-300x236.png 300w, https:\/\/www.equalexperts.com\/wp-content\/uploads\/2021\/11\/Tests-for-DBT-8-768x604.png 768w\" sizes=\"(max-width: 1048px) 100vw, 1048px\" \/>\n<p><span style=\"font-weight: 400;\">Now the fake inputs for \u201c<\/span><b>model2<\/b><span style=\"font-weight: 400;\">\u201d will be used in the test.<\/span><\/p>\n<p><i><span style=\"font-weight: 400;\">(this is a simplified version of the actual SQL used for testing. For instance, a few extra steps are necessary to prevent the need to specify all the columns in the fake inputs. We simplified it here for explanation purposes)\u00a0<\/span><\/i><\/p>\n<h3><b><i>More than one test on the same file<\/i><\/b><\/h3>\n<p><span style=\"font-weight: 400;\">It\u2019s possible to specify more than one test on a single dbt test file. We just need to join all the tests with a UNION ALL statement:<\/span><\/p>\n<img decoding=\"async\" class=\"alignnone size-large wp-image-10356\" src=\"https:\/\/www.equalexperts.com\/wp-content\/uploads\/2021\/11\/Tests-for-DBT-9-863x1024.png\" alt=\"\" width=\"863\" height=\"1024\" \/>\n<p><span style=\"font-weight: 400;\">The test output will show which tests have failed, along with their name and description.\u00a0<\/span><\/p>\n<h2><b>What about the <\/b><b><i>cons<\/i><\/b><b>?<\/b><\/h2>\n<p><span style=\"font-weight: 400;\">Nothing comes for free. Using this framework has its downsides.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">The first one would be a slightly more complicated syntax to describe our tests. We did our best to keep it as simple and straightforward as possible, but the level of boilerplate is still a bit high.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">We are relying on some dbt internal details. The dbt <\/span><b>render<\/b><span style=\"font-weight: 400;\"> function is not documented. If it changes in the future, it could break our framework. (We have <a href=\"https:\/\/discourse.getdbt.com\/t\/stability-of-the-jinja-render-function\/8500\/4\" target=\"_blank\" rel=\"noopener\">this response<\/a> from the dbt team saying that this is very unlikely to happen).<\/span><\/p>\n<h2><b>Conclusion<\/b><\/h2>\n<p><span style=\"font-weight: 400;\">We are always trying to improve, and there is still some space for improvements here. Currently, our macros are running against a BigQuery database. We know we need to change a few things to make them compatible with Postgres, for instance.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">All in all, we can create our dbt tests comfortably, using TDD with fast feedback, and we are gaining confidence in the correctness of our models.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">If you want to learn more about the technical details of how this works, you can check our dbt test demo project on <\/span><a href=\"https:\/\/github.com\/EqualExperts\/dbt-unit-test-demo\"><span style=\"font-weight: 400;\">Github<\/span><\/a><span style=\"font-weight: 400;\">.\u00a0<\/span><\/p>\n<p><span style=\"font-weight: 400;\">We hope we are helping other teams to write unit tests for dbt projects.<\/span><\/p>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>One of the software engineering practices that we follow is TDD. We strongly believe that it helps us create better code and achieve a good level of confidence in its correctness. So, why not use this in our dbt projects?<\/p>\n","protected":false},"author":176,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"content-type":"","inline_featured_image":false,"footnotes":""},"categories":[5],"tags":[226,19],"location":[397],"class_list":["post-10354","post","type-post","status-publish","format-standard","hentry","category-our-thinking","tag-dbt","tag-tdd"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v25.9 (Yoast SEO v25.9) - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Writing Unit Tests for dbt - with TDD | Equal Experts<\/title>\n<meta name=\"description\" content=\"This blog post is an exploration by the author and his colleague of the dbt tool and their path to finding a way to write unit tests using TDD.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.equalexperts.com\/blog\/our-thinking\/writing-unit-tests-for-dbt-with-tdd\/\" \/>\n<meta property=\"og:locale\" content=\"en_GB\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Writing Unit Tests for dbt - with TDD\" \/>\n<meta property=\"og:description\" content=\"One of the software engineering practices that we follow is TDD. We strongly believe that it helps us create better code and achieve a good level of confidence in its correctness. So, why not use this in our dbt projects?\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.equalexperts.com\/blog\/our-thinking\/writing-unit-tests-for-dbt-with-tdd\/\" \/>\n<meta property=\"og:site_name\" content=\"Equal Experts\" \/>\n<meta property=\"article:published_time\" content=\"2021-11-23T08:17:24+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2023-09-21T22:49:56+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.equalexperts.com\/wp-content\/uploads\/2021\/11\/Claudio-Paul-B-F.png\" \/>\n\t<meta property=\"og:image:width\" content=\"1200\" \/>\n\t<meta property=\"og:image:height\" content=\"630\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Pedro Sousa\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:title\" content=\"Writing Unit Tests for dbt - with TDD\" \/>\n<meta name=\"twitter:description\" content=\"One of the software engineering practices that we follow is TDD. We strongly believe that it helps us create better code and achieve a good level of confidence in its correctness. So, why not use this in our dbt projects?\" \/>\n<meta name=\"twitter:creator\" content=\"@EqualExperts\" \/>\n<meta name=\"twitter:site\" content=\"@EqualExperts\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Pedro Sousa\" \/>\n\t<meta name=\"twitter:label2\" content=\"Estimated reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"10 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/www.equalexperts.com\/blog\/our-thinking\/writing-unit-tests-for-dbt-with-tdd\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/www.equalexperts.com\/blog\/our-thinking\/writing-unit-tests-for-dbt-with-tdd\/\"},\"author\":{\"name\":\"Pedro Sousa\",\"@id\":\"https:\/\/www.equalexperts.com\/#\/schema\/person\/f7bbf522f0c4e821b968aeaffa0e1816\"},\"headline\":\"Writing Unit Tests for dbt &#8211; with TDD\",\"datePublished\":\"2021-11-23T08:17:24+00:00\",\"dateModified\":\"2023-09-21T22:49:56+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/www.equalexperts.com\/blog\/our-thinking\/writing-unit-tests-for-dbt-with-tdd\/\"},\"wordCount\":1827,\"publisher\":{\"@id\":\"https:\/\/www.equalexperts.com\/#organization\"},\"image\":{\"@id\":\"https:\/\/www.equalexperts.com\/blog\/our-thinking\/writing-unit-tests-for-dbt-with-tdd\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.equalexperts.com\/wp-content\/uploads\/2021\/11\/Tests-for-dbt-emoji.png\",\"keywords\":[\"dbt\",\"TDD\"],\"articleSection\":[\"Our Thinking\"],\"inLanguage\":\"en-GB\"},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.equalexperts.com\/blog\/our-thinking\/writing-unit-tests-for-dbt-with-tdd\/\",\"url\":\"https:\/\/www.equalexperts.com\/blog\/our-thinking\/writing-unit-tests-for-dbt-with-tdd\/\",\"name\":\"Writing Unit Tests for dbt - with TDD | Equal Experts\",\"isPartOf\":{\"@id\":\"https:\/\/www.equalexperts.com\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/www.equalexperts.com\/blog\/our-thinking\/writing-unit-tests-for-dbt-with-tdd\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/www.equalexperts.com\/blog\/our-thinking\/writing-unit-tests-for-dbt-with-tdd\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.equalexperts.com\/wp-content\/uploads\/2021\/11\/Tests-for-dbt-emoji.png\",\"datePublished\":\"2021-11-23T08:17:24+00:00\",\"dateModified\":\"2023-09-21T22:49:56+00:00\",\"description\":\"This blog post is an exploration by the author and his colleague of the dbt tool and their path to finding a way to write unit tests using TDD.\",\"breadcrumb\":{\"@id\":\"https:\/\/www.equalexperts.com\/blog\/our-thinking\/writing-unit-tests-for-dbt-with-tdd\/#breadcrumb\"},\"inLanguage\":\"en-GB\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.equalexperts.com\/blog\/our-thinking\/writing-unit-tests-for-dbt-with-tdd\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-GB\",\"@id\":\"https:\/\/www.equalexperts.com\/blog\/our-thinking\/writing-unit-tests-for-dbt-with-tdd\/#primaryimage\",\"url\":\"https:\/\/www.equalexperts.com\/wp-content\/uploads\/2021\/11\/Tests-for-dbt-emoji.png\",\"contentUrl\":\"https:\/\/www.equalexperts.com\/wp-content\/uploads\/2021\/11\/Tests-for-dbt-emoji.png\",\"width\":64,\"height\":64},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.equalexperts.com\/blog\/our-thinking\/writing-unit-tests-for-dbt-with-tdd\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/www.equalexperts.com\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Writing Unit Tests for dbt &#8211; with TDD\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.equalexperts.com\/#website\",\"url\":\"https:\/\/www.equalexperts.com\/\",\"name\":\"Equal Experts\",\"description\":\"Making Software. Better.\",\"publisher\":{\"@id\":\"https:\/\/www.equalexperts.com\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.equalexperts.com\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-GB\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/www.equalexperts.com\/#organization\",\"name\":\"Equal Experts\",\"url\":\"https:\/\/www.equalexperts.com\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-GB\",\"@id\":\"https:\/\/www.equalexperts.com\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/www.equalexperts.com\/wp-content\/uploads\/2018\/08\/Equal_Experts_Logo_CMYK_Colour.jpg\",\"contentUrl\":\"https:\/\/www.equalexperts.com\/wp-content\/uploads\/2018\/08\/Equal_Experts_Logo_CMYK_Colour.jpg\",\"width\":719,\"height\":340,\"caption\":\"Equal Experts\"},\"image\":{\"@id\":\"https:\/\/www.equalexperts.com\/#\/schema\/logo\/image\/\"},\"sameAs\":[\"https:\/\/x.com\/EqualExperts\",\"https:\/\/www.linkedin.com\/company\/equal-experts\/?viewAsMember=true\"]},{\"@type\":\"Person\",\"@id\":\"https:\/\/www.equalexperts.com\/#\/schema\/person\/f7bbf522f0c4e821b968aeaffa0e1816\",\"name\":\"Pedro Sousa\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-GB\",\"@id\":\"https:\/\/www.equalexperts.com\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/b4ac7bb5c46dc0c3d8f9ec6993ee785f58fd64364dfa65b205f510a9f9099ba9?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/b4ac7bb5c46dc0c3d8f9ec6993ee785f58fd64364dfa65b205f510a9f9099ba9?s=96&d=mm&r=g\",\"caption\":\"Pedro Sousa\"}}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Writing Unit Tests for dbt - with TDD | Equal Experts","description":"This blog post is an exploration by the author and his colleague of the dbt tool and their path to finding a way to write unit tests using TDD.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.equalexperts.com\/blog\/our-thinking\/writing-unit-tests-for-dbt-with-tdd\/","og_locale":"en_GB","og_type":"article","og_title":"Writing Unit Tests for dbt - with TDD","og_description":"One of the software engineering practices that we follow is TDD. We strongly believe that it helps us create better code and achieve a good level of confidence in its correctness. So, why not use this in our dbt projects?","og_url":"https:\/\/www.equalexperts.com\/blog\/our-thinking\/writing-unit-tests-for-dbt-with-tdd\/","og_site_name":"Equal Experts","article_published_time":"2021-11-23T08:17:24+00:00","article_modified_time":"2023-09-21T22:49:56+00:00","og_image":[{"width":1200,"height":630,"url":"https:\/\/www.equalexperts.com\/wp-content\/uploads\/2021\/11\/Claudio-Paul-B-F.png","type":"image\/png"}],"author":"Pedro Sousa","twitter_card":"summary_large_image","twitter_title":"Writing Unit Tests for dbt - with TDD","twitter_description":"One of the software engineering practices that we follow is TDD. We strongly believe that it helps us create better code and achieve a good level of confidence in its correctness. So, why not use this in our dbt projects?","twitter_creator":"@EqualExperts","twitter_site":"@EqualExperts","twitter_misc":{"Written by":"Pedro Sousa","Estimated reading time":"10 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.equalexperts.com\/blog\/our-thinking\/writing-unit-tests-for-dbt-with-tdd\/#article","isPartOf":{"@id":"https:\/\/www.equalexperts.com\/blog\/our-thinking\/writing-unit-tests-for-dbt-with-tdd\/"},"author":{"name":"Pedro Sousa","@id":"https:\/\/www.equalexperts.com\/#\/schema\/person\/f7bbf522f0c4e821b968aeaffa0e1816"},"headline":"Writing Unit Tests for dbt &#8211; with TDD","datePublished":"2021-11-23T08:17:24+00:00","dateModified":"2023-09-21T22:49:56+00:00","mainEntityOfPage":{"@id":"https:\/\/www.equalexperts.com\/blog\/our-thinking\/writing-unit-tests-for-dbt-with-tdd\/"},"wordCount":1827,"publisher":{"@id":"https:\/\/www.equalexperts.com\/#organization"},"image":{"@id":"https:\/\/www.equalexperts.com\/blog\/our-thinking\/writing-unit-tests-for-dbt-with-tdd\/#primaryimage"},"thumbnailUrl":"https:\/\/www.equalexperts.com\/wp-content\/uploads\/2021\/11\/Tests-for-dbt-emoji.png","keywords":["dbt","TDD"],"articleSection":["Our Thinking"],"inLanguage":"en-GB"},{"@type":"WebPage","@id":"https:\/\/www.equalexperts.com\/blog\/our-thinking\/writing-unit-tests-for-dbt-with-tdd\/","url":"https:\/\/www.equalexperts.com\/blog\/our-thinking\/writing-unit-tests-for-dbt-with-tdd\/","name":"Writing Unit Tests for dbt - with TDD | Equal Experts","isPartOf":{"@id":"https:\/\/www.equalexperts.com\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.equalexperts.com\/blog\/our-thinking\/writing-unit-tests-for-dbt-with-tdd\/#primaryimage"},"image":{"@id":"https:\/\/www.equalexperts.com\/blog\/our-thinking\/writing-unit-tests-for-dbt-with-tdd\/#primaryimage"},"thumbnailUrl":"https:\/\/www.equalexperts.com\/wp-content\/uploads\/2021\/11\/Tests-for-dbt-emoji.png","datePublished":"2021-11-23T08:17:24+00:00","dateModified":"2023-09-21T22:49:56+00:00","description":"This blog post is an exploration by the author and his colleague of the dbt tool and their path to finding a way to write unit tests using TDD.","breadcrumb":{"@id":"https:\/\/www.equalexperts.com\/blog\/our-thinking\/writing-unit-tests-for-dbt-with-tdd\/#breadcrumb"},"inLanguage":"en-GB","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.equalexperts.com\/blog\/our-thinking\/writing-unit-tests-for-dbt-with-tdd\/"]}]},{"@type":"ImageObject","inLanguage":"en-GB","@id":"https:\/\/www.equalexperts.com\/blog\/our-thinking\/writing-unit-tests-for-dbt-with-tdd\/#primaryimage","url":"https:\/\/www.equalexperts.com\/wp-content\/uploads\/2021\/11\/Tests-for-dbt-emoji.png","contentUrl":"https:\/\/www.equalexperts.com\/wp-content\/uploads\/2021\/11\/Tests-for-dbt-emoji.png","width":64,"height":64},{"@type":"BreadcrumbList","@id":"https:\/\/www.equalexperts.com\/blog\/our-thinking\/writing-unit-tests-for-dbt-with-tdd\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.equalexperts.com\/"},{"@type":"ListItem","position":2,"name":"Writing Unit Tests for dbt &#8211; with TDD"}]},{"@type":"WebSite","@id":"https:\/\/www.equalexperts.com\/#website","url":"https:\/\/www.equalexperts.com\/","name":"Equal Experts","description":"Making Software. Better.","publisher":{"@id":"https:\/\/www.equalexperts.com\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.equalexperts.com\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-GB"},{"@type":"Organization","@id":"https:\/\/www.equalexperts.com\/#organization","name":"Equal Experts","url":"https:\/\/www.equalexperts.com\/","logo":{"@type":"ImageObject","inLanguage":"en-GB","@id":"https:\/\/www.equalexperts.com\/#\/schema\/logo\/image\/","url":"https:\/\/www.equalexperts.com\/wp-content\/uploads\/2018\/08\/Equal_Experts_Logo_CMYK_Colour.jpg","contentUrl":"https:\/\/www.equalexperts.com\/wp-content\/uploads\/2018\/08\/Equal_Experts_Logo_CMYK_Colour.jpg","width":719,"height":340,"caption":"Equal Experts"},"image":{"@id":"https:\/\/www.equalexperts.com\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/x.com\/EqualExperts","https:\/\/www.linkedin.com\/company\/equal-experts\/?viewAsMember=true"]},{"@type":"Person","@id":"https:\/\/www.equalexperts.com\/#\/schema\/person\/f7bbf522f0c4e821b968aeaffa0e1816","name":"Pedro Sousa","image":{"@type":"ImageObject","inLanguage":"en-GB","@id":"https:\/\/www.equalexperts.com\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/b4ac7bb5c46dc0c3d8f9ec6993ee785f58fd64364dfa65b205f510a9f9099ba9?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/b4ac7bb5c46dc0c3d8f9ec6993ee785f58fd64364dfa65b205f510a9f9099ba9?s=96&d=mm&r=g","caption":"Pedro Sousa"}}]}},"_links":{"self":[{"href":"https:\/\/www.equalexperts.com\/wp-json\/wp\/v2\/posts\/10354","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.equalexperts.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.equalexperts.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.equalexperts.com\/wp-json\/wp\/v2\/users\/176"}],"replies":[{"embeddable":true,"href":"https:\/\/www.equalexperts.com\/wp-json\/wp\/v2\/comments?post=10354"}],"version-history":[{"count":0,"href":"https:\/\/www.equalexperts.com\/wp-json\/wp\/v2\/posts\/10354\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.equalexperts.com\/wp-json\/wp\/v2\/media?parent=10354"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.equalexperts.com\/wp-json\/wp\/v2\/categories?post=10354"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.equalexperts.com\/wp-json\/wp\/v2\/tags?post=10354"},{"taxonomy":"location","embeddable":true,"href":"https:\/\/www.equalexperts.com\/wp-json\/wp\/v2\/location?post=10354"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}