Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django LiveServerTestCase with phantomjs intermittent hangs / timeouts

I'm using Django (1.5.5), selenium (2.41.0), splinter (0.6.0) and phantomjs (1.9.7) for running live tests.

While the tests mostly work, every now and then (very often on CircleCI, less often in a local VM) they hang until either there's a timeout on CircleCI or I kill the runner manually (Ctrl-C ie. KeyboardInterrupt works).

This is how my base test class looks:

class SplinterTestCase(LiveServerTestCase):
    @classmethod
    def setUpClass(cls):
        super(SplinterTestCase, cls).setUpClass()
        # start phantom just once per class, to speed up tests
        cls.phantom = splinter.Browser('phantomjs', load_images=False)

    @classmethod
    def tearDownClass(cls):
        cls.phantom.quit()
        super(SplinterTestCase, cls).tearDownClass()

    def login(self, *args, **kwargs):
        # perform a login using Django builtin "client", steal the session
        # cookie and inject it to phantomjs, avoiding the need to do the
        # login dance for each test
        from django.conf import settings
        cn = settings.SESSION_COOKIE_NAME

        self.django_client.login(*args, **kwargs)
        if cn in self.django_client.cookies:
            self.client.driver.add_cookie({
                'name': cn,
                'value': self.django_client.cookies[cn].value,
                'path': '/',
                'domain': 'localhost'
            })

    def setUp(self):
        # use phantom as the test client instead of Django's
        super(SplinterTestCase, self).setUp()
        self.django_client = self.client
        self.client = self.phantom

    def tearDown(self):
        # this seems to help somewhat (decreases the number of timeouts), but
        # doesn't solve it completely
        self.client.visit('about:config')
        super(SplinterTestCase, self).tearDown()

After Ctrl-C, this is the stacktrace I get:

Traceback (most recent call last):
  File "/usr/lib/python2.7/wsgiref/handlers.py", line 86, in run
    self.finish_response()
  File "/usr/lib/python2.7/wsgiref/handlers.py", line 127, in finish_response
    self.write(data)
  File "/usr/lib/python2.7/wsgiref/handlers.py", line 215, in write
    self._write(data)
  File "/usr/lib/python2.7/socket.py", line 324, in write
    self.flush()
  File "/usr/lib/python2.7/socket.py", line 303, in flush
    self._sock.sendall(view[write_offset:write_offset+buffer_size])
error: [Errno 104] Connection reset by peer
Traceback (most recent call last):
  File "/home/ubuntu/memo-angel/venv/local/lib/python2.7/site-packages/django/test/testcases.py", line 998, in _handle_request_noblock
    self.process_request(request, client_address)
  File "/usr/lib/python2.7/SocketServer.py", line 310, in process_request
    self.finish_request(request, client_address)
  File "/usr/lib/python2.7/SocketServer.py", line 323, in finish_request
    self.RequestHandlerClass(request, client_address, self)
  File "/home/ubuntu/memo-angel/venv/local/lib/python2.7/site-packages/django/core/servers/basehttp.py", line 150, in __init__
    super(WSGIRequestHandler, self).__init__(*args, **kwargs)
  File "/usr/lib/python2.7/SocketServer.py", line 640, in __init__
    self.finish()
  File "/usr/lib/python2.7/SocketServer.py", line 693, in finish
    self.wfile.flush()
  File "/usr/lib/python2.7/socket.py", line 303, in flush
    self._sock.sendall(view[write_offset:write_offset+buffer_size])
error: [Errno 32] Broken pipe

A similar problem might've been discussed in Django with splinter and phantomjs is painfully slow as the original poster also mentioned "it just freezes until I am out of patience to wait for it to finish". The answer there mentioned to try to put phantomjs start/stop in class setup/teardown, which I did here, but it doesn't solve the problem.

Has anyone experienced a similar problem, and if you have, what are your workarounds?

like image 926
Senko Rašić Avatar asked Apr 11 '14 09:04

Senko Rašić


Video Answer


1 Answers

To identify the issue and make your tests fail faster, you may want to configure a socket timeout inside your setUpClass / setUp:

import socket

...
socket.setdefaulttimeout(10)
like image 181
MechanTOurS Avatar answered Oct 30 '22 03:10

MechanTOurS