8

I've witten a few functional tests using the StaticLiveServerCase. This works great for local testing, but now I'd like to test my staging server as well. The author of the book I'm reading suggests the following hack:

import sys
[...]

class NewVisitorTest(StaticLiveServerCase):

    @classmethod
    def setUpClass(cls):
        for arg in sys.argv:
            if 'liveserver' in arg:
                cls.server_url = 'http://' + arg.split('=')[1]
                return
        super().setUpClass()
        cls.server_url = cls.live_server_url

    @classmethod
    def tearDownClass(cls):
        if cls.server_url == cls.live_server_url:
            super().tearDownClass()

    # Now use self.server_url instead of self.live_server_url

I adjusted it to call super(LiveServerTestCase, cls).setUpClass() (as well as tearDownClass) instead, when not using the "temporary server", because bluntly ignoring the (grand)parent's implementation feels wrong.

Still it's a hack, and I'd like to know if cleaner solutions exist. Django does have a --liveserver argument of its own, but it can only be used to change the bindings of the temporary server.

So far, I've come up with the following ideas:

  • Subclassing StaticLiveServerCase to parse the argument, change the live_server_url property accordingly, and let the temporary server just be started/stopped unused. Costs some performance and in theory, makes the tests less reliable.
  • Exploiting Python's dynamic typing to determine the base class (StaticLiveServerCase or some StagingServerTestCase subclassing TransactionTestCase) at runtime. This is not much less of a hack, and my IDE probably isn't going to like it either.
  • Writing a third class that delegates to either StaticLiveServerTestCase or TransactionTestCase (composition instead of inheritance). Looks like a lot of work to achieve this one thing.
Thijs van Dien
  • 6,516
  • 1
  • 29
  • 48
  • 1
    @hwjp Just giving you a ping so you're aware of my question as well. – Thijs van Dien Aug 21 '14 at 15:14
  • Same issue here. On my windows machine I'm getting the following error when running the FT: "[Errno 10013] An attempt was made to access a socket in a way forbidden by its access permissions". The solution I've found is to use --liveserver=localhost:8000 (or any other port). The hack suggested in the book breaks my hacky fix :-) – Nagasaki45 Oct 15 '14 at 16:41
  • What's the problem with the --liveserver argument ? – Pierre Criulanscy Jun 20 '15 at 16:51
  • Old question but aren't you actually talking about StaticLiveServer*Test*Case – e4c5 May 08 '16 at 14:22

2 Answers2

2

Although this hack might work, I think it would be better to use a tool made for testing remote servers.

The most known tool is Selenium, which have a good integration with Django. A test with Django + Selenium would look a lot like the tests you did with StaticLiveServerTestCase, eg:

class MyTestCase(SeleniumLiveTestCase):

    def test_home(self):
        self.driver.open_url(reverse('main'))
        self.assertEquals(self.driver.get_title(), 'Sample Test Page')
        self.driver.type_in('input#id_query', 'search something')
        self.driver.click('.form-search button[type="submit"]')

        self.assertEquals(self.driver.get_text('#success'), 'SUCCESS')

Django-Selenium works either with local and remote servers, take a look at its settings.

Renan Ivo
  • 1,368
  • 9
  • 17
0

Django works out of the box with Selenium and you can use it even without third party packages like django-selenium. In fact it would be simpler to do so. You can test on your development machine using LiveServerTestCase. Event StaticLiveServerTestCase isn't really needed in most cases.

from selenium import webdriver
os.environ['DJANGO_LIVE_TEST_SERVER_ADDRESS'] = 'localhost:8082'

class MySeleniumTest(LiveServerTestCase):

    def setup_webdriver(self, driver_name = 'Firefox', mobile_emulation = None, 
                    implicit_wait = None, desired_capabilities = None):

        if driver_name == 'Firefox':
            profile = webdriver.FirefoxProfile('/home/raditha/.mozilla/firefox/bjfo3emg.selenium/')
            self.driver = webdriver.Firefox()     
            self.driver.set_window_position(1200, 0)
            self.driver.maximize_window()    
            self.driver.implicitly_wait(10)
            self.driver.set_page_load_timeout(5)

     def test_something(self):
         p = self.driver.get('http://localhost:8082')
         self.assertEqual(self.driver.get_title(),'My Home Page')

If you wanted to test against your production server you could do that to by using unittest.TestCase instead of LiveServerTestCase and avoid all the slow down associated with it. You could use the same approach to test against the development server too.

e4c5
  • 52,766
  • 11
  • 101
  • 134