On Wed, Dec 18, 2013 at 11:57 PM, Harry Percival
<harry.perci...@gmail.com>wrote:

> Django's test runner overrides your settings to force DEBUG to be True,
> which I understand the intention behind, but it is occasionally annoying.
> One solution for those cases is to use `override_settings`, but that has
> very weird effects when using `LiveServerTestCase`.
>

I presume this is just a typo, but for clarity - it's the other way around.
TestRunner forces DEBUG=False, with the theory being that you should be
testing "production" behaviour as much as possible.


> Minimal repro:
>
>     django-admin.py startproject myproj
>     cd myproj
>     vi tests.py
>
> In tests.py:
>
> from django.test import LiveServerTestCase
> from selenium import webdriver
> from django.test.utils import override_settings
>
> @override_settings(DEBUG=True)
> class MinimalTest(LiveServerTestCase):
>
>     def setUp(self):
>         self.browser = webdriver.Firefox()
>         self.browser.implicitly_wait(3)
>
>     def tearDown(self):
>         self.browser.quit()
>
>
>     def test_admin_site_is_there(self):
>         self.browser.get(self.live_server_url + '/admin')
>         self.assertIn('Django administration',
> self.browser.find_element_by_tag_name('body').text)
>
> Change DEBUG=True to DEBUG=False and this passes.  But, as-is, you get:
>
>   File "/tmp/myproj/test1.py", line 18, in test_admin_site_is_there
>     self.assertIn('Django administration',
> self.browser.find_element_by_tag_name('body').text)
> AssertionError: 'Django administration' not found in 'Page not found
> (404)\nRequest Method: GET\nRequest URL: http://localhost:8081/admin\n"admin";
> does not exist\nYou\'re seeing this error because you have DEBUG = True in
> your Django settings file. Change that to False, and Django will display a
> standard 404 page.'
>
> I'm just using the admin URL because it's one that is activated by
> default.  Normal URLs, eg a home page view, also return 404s.  What's going
> on?
>

Ok - the reason for this is a little complicated.

The LiveTestServer is actually three media servers, layered over each other
(like an onion. Or a parfait :-). The outer layer is the static files
server, the middle layer is the media file server, and the inner layer is
the actual WSGI server providing your URLs.

Starting from the outside and moving in, each layer does a check to see
"should I serve this URL"; if it does, it returns the appropriate page/file.

However, if the file *doesn't* match, the behaviour of these layers is
different depending on the value of DEBUG. If DEBUG=False, it *raises* a
Http404; if DEBUG=True, it *returns* a technical 404 response. This is the
page you're seeing during the test -- the technical 404 response that says
"I couldn't find a file name 'admin'".

The internals of the server implementation catches Http404 exceptions and
tries a deeper layer; but if a 404 is returned as a view response, it just
gets returned.

So - why does this behaviour change matter?

Well, the default value for MEDIA_ROOT is ''. Which means it matches *all*
URL requests. When DEBUG=False, this doesn't matter - it just means no
files are ever matches by the middle media layer, a 404 is raised, and the
next layer is tried; but when you force DEBUG=True, the media layer
dutifully says "I can't find that file" - for every request it receives. It
doesn't hit this problem for static files because STATIC_ROOT = '/static/'
by default, and the requested URL doesn't match, so the static layer is
never asked to response with file or 404.

You only see this on the LiveTestServer because runserver doesn't include
the Media layer -- it only serve staticfiles and the main app. If have to
manually add the media handler to your URLconf if you want media files to
be served, and that handler will run *after* all the normal URLs have been
tried. And you don't normally see the problem during testing because, as
you've noted, DEBUG is forced to False by the test running infrastructure.

The upside - If you add MEDIA_ROOT='/media/' to settings.py, the problem
goes away, because it gives the media layer something to match against that
won't catch all files.

Yours,
Russ Magee %-)

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-developers+unsubscr...@googlegroups.com.
To post to this group, send email to django-developers@googlegroups.com.
Visit this group at http://groups.google.com/group/django-developers.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-developers/CAJxq84_F%3DRrop%2Bn-8i7Krv6zr3Gqdvd%2B%3D%3DK2a1W%3DHfcGJLJiMA%40mail.gmail.com.
For more options, visit https://groups.google.com/groups/opt_out.

Reply via email to