I have a test in Django 1.5 that passes in these conditions:
TestCase
is runBut it fails when the full test suite is run with python manage.py test
. Why might this be happening?
The aberrant test uses django.test.Client
to POST
some data to an endpoint, and then the test checks that an object was successfully updated. Could some other app be modifying the test client or the data itself?
I have tried some print debugging and I see all of the data being sent and received as expected. The specific failure is a does-not-exist exception that is raised when I try to fetch the to-be-updated object from the db. Strangely, in the exception handler itself, I can query for all objects of that type and see that the target object does in fact exist.
Edit:
My issue was resolved when I found that I was querying for the target object by id
and User
and not id
and UserProfile
, but it's still confusing to me that this would work in some cases but fail in others.
I also found that the test would fail with python manage.py test auth <myapp>
With Django's test-execution framework and assorted utilities, you can simulate requests, insert test data, inspect your application's output and generally verify your code is doing what it should be doing. The preferred way to write tests in Django is using the unittest module built-in to the Python standard library.
Order in which tests are executedAll TestCase subclasses are run first. Then, all other Django-based tests (test cases based on SimpleTestCase , including TransactionTestCase ) are run with no particular ordering guaranteed nor enforced among them.
As discussed above, we should test anything that is part of our design or that is defined by code that we have written, but not libraries/code that is already tested by Django or the Python development team. For example, consider the Author model below.
It sounds like your problem does not involve mocks, but I just spent all day debugging an issue with similar symptoms, and your question is the first one that came up when I was searching for a solution, so I wanted to share my solution here, just in case it will prove helpful for others. In my case, the issue was as follows.
I had a single test that would pass in isolation, but fail when run as part of my full test suite. In one of my view functions I was using the Django send_mail()
function. In my test, rather than having it send me an email every time I ran my tests, I patch
ed send_mail
in my test method:
from mock import patch ... def test_stuff(self): ... with patch('django.core.mail.send_mail') as mocked_send_mail: ...
That way, after my view function is called, I can test that send_mail
was called with:
self.assertTrue(mocked_send_mail.called)
This worked fine when running the test on its own, but failed when run with other tests in the suite. The reason this fails is that when it runs as part of the suite other views are called beforehand, causing the views.py
file to be loaded, causing send_mail
to be imported before I get the chance to patch
it. So when send_mail
gets called in my view, it is the actual send_mail
that gets called, not my patched version. When I run the test alone, the function gets mocked before it is imported, so the patched version ends up getting imported when views.py
is loaded. This situation is described in the mock documentation, which I had read a few times before, but now understand quite well after learning the hard way...
The solution was simple: instead of patching django.core.mail.send_mail
I just patched the version that had already been imported in my views.py
- myapp.views.send_mail
. In other words:
with patch('myapp.views.send_mail') as mocked_send_mail: ...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With