Django Selenium liveserver doesn't get started when running tests - django

I am building a Django website and I am using Selenium to test my pages. My problem is that when I run the tests, the browser is launched, but no page is loaded or even attempted to be loaded. It just opens blank and the tests hang. It seems to me that the liveserver doesn't get started. I am running on Apache2 and WSGI, but my understanding is that the Selenium tests are run by the the Django's built-in web server. Any idea what could be wrong? The relevant files are below:
tests.py:
from selenium.webdriver.firefox.webdriver import WebDriver
class MyProjectLiveServerTestCase(LiveServerTestCase):
#classmethod
def initSeleniumDriver(cls):
cls.driver = WebDriver()
#classmethod
def closeSeleniumDriver(cls):
cls.driver.quit()
def testIndexShouldLoad(self):
self.driver.get('%s%s' % (self.live_server_url, '/nd5/mybook/'))
self.assertEqual(len(self.driver.find_elements(
By.CSS_SELECTOR,
'span#copyright'
)), 1)
settings.py:
# Test database runs on SQLite
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(os.path.realpath(os.path.dirname(__file__)), '..', 'myprojectdb'),
}
}
TEST_RUNNER = 'django_nose.NoseTestSuiteRunner'
I am using django-nose, so I execute the tests this way:
python manage.py test --exe
Please, let me know if you need to see any other parts of the code.
UPDATE:
Here is update: I found out that the reason Firefox doesn't load the page is because my version of Firefox is newer than the latest version supported by Selenium. So I switched to Chrome and now the URL in the browser is requested. However, the page isn't found (404 error). This must mean that the liveserver is still not running. My tests don't turn on the liveserver when they get run. Any idea why? The port isn't blocked - I checked.

I think you forgot to select webdriver to use:
class SomethingTest(LiveServerTestCase):
def setUp(self):
self.browser = webdriver.Firefox()
self.browser.implicitly_wait(2)
def tearDown(self):
self.browser.quit()
def test_user_can_log_in(self):
self.browser.get(self.live_server_url + reverse('something'))
self.fail('write rest of the test')

This probably wasn't your problem, but what bit me was that LiveServerTestCase starts the server thread from setUpClass, which I'd defined without calling super(MyProjectLiveServerTestCase, self).setUpClass().

Related

Django Unittest runs into Error

Environment:
Intellij PyCharm, Python Django, Sqlite3
I use a standard Django setup project.
I try to write some Unittests, but I run into the following error.
After some research, I ended up here.
DB Config
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
}
}
Code of tests.py
from django.test import TestCase as djangoTestCase
import os
import unittest
# Create your tests here.
class TestExample(djangoTestCase):
def setUp(self):
print('setup')
print(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
def test_abc(self):
self.assertEqual(1,1)
def tearDown(self):
print('tearDown')
if __name__ == '__main__':
unittest.main()
This is the output
django.core.exceptions.ImproperlyConfigured: settings.DATABASES is improperly configured. Please supply the ENGINE value. Check settings documentation for more details.
I tried to find the mistake by reading documentation, but without success.
What could be the problem?
With django test you don't need this part:
if __name__ == '__main__':
unittest.main()
you just running tests with python manage.py test command.
I ran into the same problem in PyCharm. My DB config is in file config.settings_dev. By default, PyCharm is not aware of it.
To solve it,
Open PyCharm's Run/Debug Configurations in menu Run -> Edit Configurations
Expand Templates, then Djano tests.
Add environment variable DJANGO_SETTINGS_MODULE with value config.settings_dev (replace it with your own settings file)
Delete any existing configurations under Django tests
5. Run the tests in PyCharm

Running functional tests for Django on Travis?

Is it possible to run Selenium tests for Django on Travis? These are my tests:
class FrontendTest(unittest.TestCase):
def setUp(self):
self.browser = webdriver.Firefox()
self.browser.implicitly_wait(3)
def tearDown(self):
self.browser.quit()
def test_homepage(self):
self.browser.get('http://localhost:8000')
print self.browser
assert 'Home' in self.browser.title
But obviously, they depend on localhost running.
This is the relevant section of my Travis file:
script:
- python manage.py test
- python frontend/tests/functional_tests.py
manage.py test runs just fine but the functional tests fail - I guess because localhost isn't up. How can I make sure it is running?
Or should I just not bother running functional tests on Travis?
Django's LiveServerTestCase will handle server set up and tear down for you.
https://docs.djangoproject.com/en/1.8/topics/testing/tools/#liveservertestcase

Django Selenium LiveServerTestCase not loading the page in browser (error 500)

I have a test Django project called MyApp, running over WSGI on port 8083. When I go to http://myapp:8083, I see the standard Django "it's working" page. I wrote a functional test using selenium bindings in Django to launch a browser and load the above mentioned page. When I run the test, though, I get an error message "Address already in use". So I run the test using another port like this: python manage.py test --liveserver=myapp:8084
This opens the browser, but shows "Page not found" error instead of the default Django page. What am I doing wrong? Any ideas? Thank you!
The test.py file content:
class CoreSeleniumTestCase(LiveServerTestCase):
#classmethod
def setUpClass(cls):
cls.driver = webdriver.Chrome()
cls.driver.maximize_window()
super(CoreSeleniumTestCase, cls).setUpClass()
#classmethod
def tearDownClass(cls):
cls.driver.quit()
super(CoreSeleniumTestCase, cls).tearDownClass()
def testIndexShouldLoad(self):
self.driver.get('%s%s' % (self.live_server_url, '/'))
I finally found the problem. At some point, Django removed MEDIA_ROOT from the settings.py file by default. It turns out that this setting must be in the file for Selenium tests to work properly. Once I reintroduced the setting and assigned a directory to it, the Selenium tests started to work as expected.

Django LiveTestServerCase not using proper settings

In a Django project I'm using selenium to run some UI tests, using a LiveServerTestCase.
One of my test cases is failing, and when using the Firefox driver I can see a page throwing "Server Error (500)", which means DEBUG is set to False which is not the case when I run the local development server.
How is the test server being launched? Why is not using my settings which define DEBUG = True?
Other URLs (such as the homepage URL) return fine, so the server is working. But I just don't get why it's not showing debug information, and which settings it's using.
My test case for reference:
class LoginTest(LiveServerTestCase):
#classmethod
def setUpClass(cls):
try:
from selenium.webdriver import PhantomJS
cls.selenium = PhantomJS()
except:
from selenium.webdriver.firefox.webdriver import WebDriver
cls.selenium = WebDriver()
super(LoginTest, cls).setUpClass()
#classmethod
def tearDownClass(cls):
cls.selenium.quit()
super(LoginTest, cls).tearDownClass()
def test_fb_login(self):
self.selenium.get('%s%s' % (self.live_server_url, reverse('account_login')))
# TEST SERVER RETURNS 500 ON THIS URL WITH NO DEBUG INFO
According to Testing Django Application - Django Documentation:
Regardless of the value of the DEBUG setting in your configuration
file, all Django tests run with DEBUG=False. This is to ensure that
the observed output of your code matches what will be seen in a
production setting.
It should still be possible to override this using:
with self.settings(DEBUG=True):
...
Although I wouldn't recommend it, it can still be useful from time to time. (Thomas Orozco's comment)
You can also change your settings in TestCase setUp() method.
from django.conf import settings
class MyTest(LiveServerTestCase):
def setUp(self):
# Change settings here
settings.DEBUG = True
# ...
I ran into the same issue and it is possible to override settings with a decorator.
based on your example you would import override_settings and place the decorator above the class:
from django.conf import settings
from django.test import override_settings
#override_settings(DEBUG=True)
class LoginTest(LiveServerTestCase):
...
details in django docs

How do you set DEBUG to True when running a Django test?

I'm currently running some Django tests and it looks that DEBUG=False by default. Is there a way to run a specific test where I can set DEBUG=True at the command line or in code?
For a specific test inside a test case, you can use the override_settings decorator:
from django.test.utils import override_settings
from django.conf import settings
class TestSomething(TestCase):
#override_settings(DEBUG=True)
def test_debug(self):
assert settings.DEBUG
Starting with Django 1.11 you can use --debug-mode to set the DEBUG setting to True prior to running tests.
The accepted answer didn't work for me. I use Selenium for testing, and setting #override_settings(DEBUG=True) makes the test browser always display 404 error on every page. And DEBUG=False does not show exception tracebacks. So I found a workaround.
The idea is to emulate DEBUG=True behaviour, using custom 500 handler and built-in django 500 error handler.
Add this to myapp.views:
import sys
from django import http
from django.views.debug import ExceptionReporter
def show_server_error(request):
"""
500 error handler to show Django default 500 template
with nice error information and traceback.
Useful in testing, if you can't set DEBUG=True.
Templates: `500.html`
Context: sys.exc_info() results
"""
exc_type, exc_value, exc_traceback = sys.exc_info()
error = ExceptionReporter(request, exc_type, exc_value, exc_traceback)
return http.HttpResponseServerError(error.get_traceback_html())
urls.py:
from django.conf import settings
if settings.TESTING_MODE:
# enable this handler only for testing,
# so that if DEBUG=False and we're not testing,
# the default handler is used
handler500 = 'myapp.views.show_server_error'
settings.py:
# detect testing mode
import sys
TESTING_MODE = 'test' in sys.argv
Now if any of your Selenium tests encounters 500 error, you'll see a nice error page with traceback and everything. If you run a normal non-testing environment, default 500 handler is used.
Inspired by:
Where in django is the default 500 traceback rendered so that I can use it to create my own logs?
django - how to detect test environment
Okay let's say you want to write tests for error testcase for which the urls are :-
urls.py
if settings.DEBUG:
urlpatterns += [
url(r'^404/$', page_not_found_view),
url(r'^500/$', my_custom_error_view),
url(r'^400/$', bad_request_view),
url(r'^403/$', permission_denied_view),
]
test_urls.py:-
from django.conf import settings
class ErroCodeUrl(TestCase):
def setUp(self):
settings.DEBUG = True
def test_400_error(self):
response = self.client.get('/400/')
self.assertEqual(response.status_code, 500)
Hope you got some idea!
Nothing worked for me except https://stackoverflow.com/a/1118271/5750078
Use Python 3.7
breakpoint()
method.
Works fine on pycharm
You can't see the results of DEBUG=True when running a unit test. The pages don't display anywhere. No browser.
Changing DEBUG has no effect, since the web pages (with the debugging output) are not visible anywhere.
If you want to see a debugging web page related to a failing unit test, then do this.
Drop your development database.
Rerun syncdb to build an empty development database.
Run the various loaddata scripts to rebuild the fixtures for that test in your development database.
Run the server and browse the page.
Now you can see the debug output.