jeudi 7 décembre 2017

Same test for different states of the same object without persisting changes

I am trying to run the same exact test on a single obj which is a models.Model instance and has some relations with other models. I do not want to persist changes in that instance, so effectively I want the same effect of the tearDown method which rollbacks transactions.

To illustrate this:

class MyTestCase(django.test.TestCase):

    def test():
        # main test that calls the same test using all 
        # different states of `obj` that need to be tested

        # different values of data that update the state of `obj`
        # with state I simply mean the values of `obj`'s attributes and relationships
        data = [state1, state2, state3]
        for state in data:
            obj = Obj.objects.get(pk=self.pk)  # gets that SINGLE object from the test db
            # applies the state data to `obj` to change its state
            obj.update(state)
            # performs the actual test on `obj` with this particular state
            self._test_obj(obj)

    def _test_obj(self, obj):
        self.assertEqual(len(obj.vals), 10)
        self.assertLess(obj.threshold, 99)
        # more assert statements...

This design has two problems:

  • The changes on obj persist on the test database, so on the next iteration the data would be tainted. I would want to rollback those changes and get a fresh instance of obj as if the test method was just called and we are getting the data straight from the fixtures.

  • If an assert statement fails I will be able to see which one it it, but I won't be able to determine what case (state) failed because of the for loop. I can try-except the _test_obj_ call in the test method but then I wouldn't be able to tell what assert failed.

Does django.test provide any tool to run the same test for different states of the same model? If it doesn't, how can I do what I am trying to do while solving both points mentioned above?

Aucun commentaire:

Enregistrer un commentaire