A theoretical question about testing application state, which got stuck in my mind for a while:
Let's assume you're doing some kind of feature inside the code base, which requires you to create a new query to a Django Model.
For example let's use Question model which we have.
Requirement for my feature is that I want to retrieve Question with its some_field equal to 1337 or 1338 and I want it to present to a user.
class Question:
id = PKField()
one_of_bools = BoolField()
some_field = IntegerField()
date = TimestampField()
One most obvious way is that I do a query to database which will be something along these lines:
Question.objects.filter(some_field__in=[1337,1338]).all()
Which let's me have these Questions that match criteria be pulled from a database. I'd like to put that query into a function that can be used in my API view, so I wrap it in a function:
def get_specific_questions():
return Question.objects.filter(some_field__in=[1337,1338]).all()
So I'll be retrieving them in single place, and reuse that part of the code whenever I need it (might be few different places, for the sake of argument).
Now to the actual quesiton that I have:
How do you test that function?
One obvious way is to just a test for best-case scenario:
def test_get_specific_questions():
QuestionFactory(some_field=1337) # creates question in database
QuestionFactory(some_field=1338)
questions = get_specific_questions()
assert len(questions) == 2
for question in questions:
assert (question.some_field == 1337 or question.some_field == 1338)
But what do you actually test here?
We assume database of a perfect state where there are only two objects that match our criteria.
If I modify my query to be instead some_field__in=[1337, 1338, 1339], this test will still pass.
If I modify my query to be instead some_field__in=[1337, 1338], another_field=True this test will also pass.
I might also change it to be a query that retrieves all the objects (without filter) which I have in database - which will still work.
How do you test it in a way that the output is the only expected one - and any modification that doesn't match the requirements fail?