-
Notifications
You must be signed in to change notification settings - Fork 1.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Bug] Custom tests whose fail_calc
is a sum() function cannot run properly when the test produces no rows at all
#4248
Comments
@EPNickBosma Thank you for the incredibly thorough write-up, and the detailed reproduction case! I completely agree with your ultimate conclusion. The right next step here is to document that That's handled quite gracefully by the default Given that, I think your move would be to either:
I don't think the latter should be too tricky at all: {{
config(
error_if = '>=1',
fail_calc = 'case when count(*) = 0 then 404 else sum(non_abc_letters) end'
)
}}
I'm going to close this issue in favor of a proposed change to docs.getdbt.com, specifically this page: https://docs.getdbt.com/reference/resource-configs/fail_calc Would you be up for opening an issue, or (if you feel moved) making the change yourself? |
fail_calc
is a sum() function cannot run properly when the test produces no rows at all
I got bit by this today, and it took me a long while to figure out what was going on. As a result, I opened a PR to update the docs: dbt-labs/docs.getdbt.com#5221 It would have been nice if either of the following happened instead:
|
## What are you changing in this pull request and why? The current code example does not always work and may raise an error like this: ``` 14:01:53 None is not of type 'integer' 14:01:53 14:01:53 Failed validating 'type' in schema['properties']['failures']: 14:01:53 {'type': 'integer'} 14:01:53 14:01:53 On instance['failures']: 14:01:53 None ``` As described in dbt-labs/dbt-core#4248, it's known that: - tests whose `fail_calc` is a sum() function raises an error when the test produces no rows at all Well, that explains why the code example doesn't work! Jerco described two options for dealing with this: 1. rewrite the test query, to ensure it always returns at least one row 1. rewrite the `fail_calc`, to handle the case in which no rows are returned This PR adopts the 2nd option and updates the code example to handle the case in which no rows are returned. ## Checklist - [x] Review the [Content style guide](https://github.com/dbt-labs/docs.getdbt.com/blob/current/contributing/content-style-guide.md) so my content adheres to these guidelines. - [x] I've verified that the updated code example works
…no rows at all (#5246) [Preview](https://docs-getdbt-com-git-dbeatty10-patch-1-dbt-labs.vercel.app/reference/resource-configs/fail_calc) ## What are you changing in this pull request and why? Follow-up to #5221 resolves #918 See also: dbt-labs/dbt-core#4248 ## Checklist - [x] Review the [Content style guide](https://github.com/dbt-labs/docs.getdbt.com/blob/current/contributing/content-style-guide.md) so my content adheres to these guidelines.
Is there an existing issue for this?
Current Behavior
Running a custom test whose
fail_calc
issum(some_col)
causes the test to crash if the custom test query itself produces no rows.We have a custom test that deals with a very important and therefore heavily tested staging model. We wrote a custom test to aggregate the sum of erroneous entries per month, and error when the total sum of erroneous entries over the months returned was > x.
The way the test was written, it had a where clause saying rows should only be returned if they had discrepancies. Any month without a discrepancy doesn't need a row, in other words. No discrepancies, no rows. So when the discrepancies stopped, the rows stopped, the sum() function stopped, and the test stopped working.
To begin with we didn't know that this error was happening instead of a pass. We just knew that the error was happening sometimes. It would also intermittently work just fine, but in hindsight that was when it was failing because there were rows to sum.
Expected Behavior
When we run a custom test we generally expect it to end up in one of a few states. It might pass, it might error because of test failures, it might warn because of test failures, and it might skip.
However, and this is what makes this interesting, we do also accept that tests can fail for other reasons --
database error:
being one.This, not being a database error (and therefore not being bad sql), and not being an explicit pass/fail/warn/skip in everyday dbt terms (and therefore not being an expected outcome of
dbt test
) strikes me as a strange middle ground worth talking about a bit.Some things are totally out of dbt's hands, and perhaps how we choose to configure our fail_calcs is one of those things. However if we can anticipate that users will try certain things and those certain things can go wrong in certain predictable ways, then maybe the product can get ahead of that in some cases. (Maybe this is one of those cases.)
Steps To Reproduce
Let's say we have a model:
model_that_needs_a_custom_test.sql
Let's say we give that model a test:
assert_only_categories_abc_exist.sql
We run the model:
dbt run --models model_that_needs_a_custom_test
We run the test:
dbt test --models model_that_needs_a_custom_test
The culprit is obvious in this case. We've put an impossible condition on the test and it can never return any rows. Without any rows to sum, the fail_calc is going to try to sum(null) and it's going to complain about it. The test therefore does not pass, ironically, because no erroneous records are found.
In our case it was much less obvious to begin with; we just knew we had an important model and the tests on it weren't working properly.
Relevant log output
Environment
What database are you using dbt with?
redshift
Additional Context
This is potentially a super duper
wontfix
from a code perspective.In some ways it's self-evident. How can you expect to sum something if you can't produce it?
There's also the question of what a fix would look like. Should
dbt test
try all tests with user-specified fail_calc first, and then revert to some other fail_calc in case of error? Should it instead explicitly skip and/or log something to the effect ofyou need to address one or more misconfigured tests: assert_only_categories_abc_exist
?The
fix
might look a lot more like this:If the docs had a warning section saying make sure you only deviate from count(*) to sum(some_col) if you expect there to be a result set to speak of, otherwise you'll see this error:
Then anyone googling either fail_calc or the error itself would eventually find what was wrong, with no changes to the code base necessary.
The best outcome here really might be just to put something in the docs about it. That would have helped us when we were trying to figure out what was wrong, and that would lead to this not being an issue because it's in the docs.
The text was updated successfully, but these errors were encountered: