hypothesis icon indicating copy to clipboard operation
hypothesis copied to clipboard

Field inference strategies for `django.contrib` modules

Open ajcerejeira opened this issue 3 years ago • 4 comments

I noticed that _global_field_lookup does not define strategies for some form fields, s.a UsernameField and ReadOnlyPasswordHashField.

This makes the code below raise a ResolutionFailed exception:

from django.contrib.auth.forms import UserCreationForm
from hypothesis import given
from hypothesis.extra.django import from_form

@given(form=from_form(UserCreationForm))
def test_signup_form(form):
    pass
hypothesis.errors.ResolutionFailed: Could not infer a strategy for <django.contrib.auth.forms.UsernameField object at >

It is quite useful in Django to use, or inherit from UserCreationForm when creating signup forms, and providing a default strategies for these fields would make testing easier without requiring to register_field_strategy for those fields.


I also noticed that there are no strategies for form fields defined django.contrib.gis module, so I assume that would be out of scope for this integration?

ajcerejeira avatar Jul 21 '22 14:07 ajcerejeira

I would be delighted to add support for anything that ships as part of the django package, whether in django.contrib.auth.forms or django.contrib.gis (though the latter might be more difficult). Our main difficulty is simply that none of the current Hypothesis maintainers use Django, and so we're fairly cautious about guessing what would be useful or idiomatic.

If you're interested, I'd love to collaborate on a PR to add support for these fields 😃

Zac-HD avatar Jul 21 '22 18:07 Zac-HD

Thanks for the feedback @Zac-HD I created #3419 to address the django.contrib.auth.forms part. I assume the django.contrib.gis support would be trickier.


A slightly unrelated question, the django UserCreationForm defines two fields, password1 and password2 that must be equal. How can we express this requirement with the from_form inside given decorator? Something along the lines of:

@given(from_form(UserCreationForm, password2="same as password1"))
def test_user_creation_form():
    pass

ajcerejeira avatar Jul 22 '22 11:07 ajcerejeira

I assume the django.contrib.gis support would be trickier.

Inasmuch as polygons are more complicated than strings, yep; but that's going from easy to medium rather than actually hard. Follow-up PR?

The django UserCreationForm defines two fields, password1 and password2 that must be equal. How can we express this requirement with the from_form inside given decorator?

The st.shared() strategy seems like what you want here - the trick is to ensure (and test) that we have a different key for each form.

From there, it looks like we need some automatic way for from_form() to recognize that two form fields must have the same value. Looking at the source, there doesn't seem to be any deliberate metadata for that, but we could add a pretty reliable heuristic based on the names and label of the fields.

Zac-HD avatar Jul 22 '22 18:07 Zac-HD

I was just going through some notes and thought that https://github.com/pytest-dev/pytest-django/issues/912 might also be of interest to you as Django dev 🙂

Zac-HD avatar Jul 25 '22 07:07 Zac-HD

Closing this because we've solved the motivating use-case and I can't think of a good general heuristic for recognizing fields that need the same value.

Zac-HD avatar Aug 20 '22 18:08 Zac-HD