1

One of the two tests below is doomed to fail because @override_settings(....) only gets executed ONCE ever for tests. The database is rewound so that it is consistent, but the models are not reconfigured based on the settings. So if the default setting is True, the second testCaseFalse will fail, and if the default setting is False, testCaseTrue will fail.

How in the following code do I force a reload of the Patient model so that both the unit test cases will work. I'd like this to be something I only have to do in one place instead of the 2 commented out possibilities below, should be some way to be DRY and still get this accomplished.

class Patient(models.Model):
    x = models.IntegerField(null=True, blank=not settings.REQUIRE_X_FOR_PATIENT)

class PatientForm(forms.ModelForm):
    #x = forms.CharField(required=settings.REQUIRE_X_FOR_PATIENT)  Don't want to have to do this
    class Meta:
        model = Patient

    #def __init__(self, *args, **kwargs):                   #Don't want to have to do this either
        #super(PatientForm, self).__init__(*args, **kwargs)
        #self.fields['x'].required = settings.REQUIRE_X_FOR_PATIENT

@override_settings(REQUIRE_X_FOR_PATIENT=True)
def testCaseTrue...
    form = PatientForm()
    self.assertTrue(form.fields['x'].required, "X should be required")

@override_settings(REQUIRE_X_FOR_PATIENT=False)
def testCaseFalse...
    form = PatientForm()
    self.assertTrue(form.fields['x'].required, "X should NOT be required")
boatcoder
  • 17,525
  • 18
  • 114
  • 178
  • Just a note. I see that you have `null=True` in your `Charfield`. That's against the recommendation in the [docs](https://docs.djangoproject.com/en/dev/ref/models/fields/#django.db.models.Field.null) – Adrián Apr 22 '13 at 23:14
  • 1
    The field in question is actually a ForeignKey, I just didn't want to cloud the code with more models. I've changed it to an IntegerField to avoid the confusion. – boatcoder Apr 23 '13 at 01:58

2 Answers2

1

I would use the setting in the form only. It doesn't seem model related to me. In fact, it is stated in the docs that the blank option is for validation-only:

Note that this is different than null. null is purely database-related, whereas blank is validation-related. If a field has blank=True, form validation will allow entry of an empty value. If a field has blank=False, the field will be required.

class Patient(models.Model):
    x = models.CharField(max_length...., blank=True)

class PatientForm(forms.ModelForm):
    x = forms.CharField(required=settings.REQUIRE_X_FOR_PATIENT)  
    class Meta:
        model = Patient

If you're still decided on leaving the setting in the model, you could check the answer by Chad Braun-Duin to this question. In my opinion is not worth it for just some tests and it's likely to break the test running environment.

Community
  • 1
  • 1
Adrián
  • 6,135
  • 1
  • 27
  • 49
  • By having it in the model, I pick it up in the Django Admin as well as this form, and if anyone creates another form with this model in it, its handled there as well, that's why I wanted to get it in one place. I've often wondered why the Django devs put form logic into the model like blank=, verbose_name, help_text, but since they are there, I'm trying to cut down on the places you have to look to see this particular condition. – boatcoder Apr 23 '13 at 02:00
0

In the end I put the logic into the model and then had the test work differently depending on the configuration. So the test became cognizant of the setting, and the right path was tested. Not ideal, but I found no way of reloading the models because of the app cache.

I also added validation in the models clean method, raising a validation error if the configuration required it.

boatcoder
  • 17,525
  • 18
  • 114
  • 178