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

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.

Related

Internal Error when using PyInstaller to make an standalone app using Flask + FlaskWebGui

Ok so I've been trying to make a standalone python app using Flask and FlaskWebGUI, it works just fine when I'm running it on VScode, print of an example program below:
Working just fine, ok. But when I use the PyInstaller command pyinstaller server.py to create the desktop app for some reason this following error occurs:
that's my server.py code:
from flask import Flask, render_template, request, redirect, url_for
#importa o Web GUI
from flaskwebgui import FlaskUI
app = Flask(__name__)
app.static_folder = 'static'
ui = FlaskUI(app, width=1150, height=700)
# A decorator used to tell the application
# which URL is associated function
#app.route('/', methods =["GET", "POST"])
def gfg():
if request.method == "POST":
# getting input with name = fname in HTML form
first_name = request.form.get("fname")
# getting input with name = lname in HTML form
last_name = request.form.get("lname")
return "Your name is "+first_name + last_name
return render_template("index.html")
# runs app
if __name__ == "__main__":
# app.run(debug=True)
# Default start flask
FlaskUI(
app=app,
server="flask",
width=1150,
height=700,
).run()
I have no idea why it isn't working.
In case it's useful, here's the PyInstaller log after running the command: https://pastebin.com/6dC6fTBs
==========
I also have tried using the following PyInstaller commands:
pyinstaller --name myapp --onefile server.py -> still not working
pyinstaller --name myapp --onefile --add-data "templates;." server.py -> also not working
It was a dependent files issue, PyInstaller you need to specify the dependency files to PyInstaller and I just wasn't managing to do it.
I then instead of typing the PyInstaller command by myself, i used it's GUI (by running "auto-py-to-exe" on a terminal in the script folder) then i used the GUI to select the dependency files (I did not had to select libraries manually, just files like .html, .png) and it worked just fine.
There's also a lot of other configs you can set using the GUI, but that's all i needed to make the program run properly.

pytest-django won't allow database access even with mark

I'm having a difficult time figuring out what is wrong with my setup. I'm trying to test a login view, and no matter what I try, I keep getting:
Database access not allowed, use the "django_db" mark, or the "db" or "transactional_db" fixtures to enable it.
My test:
import pytest
from ..models import User
#pytest.mark.django_db
def test_login(client):
# If an anonymous user accesses the login page:
response = client.get('/users/login/')
# Then the server should respond with a successful status code:
assert response.status_code == 200
# Given an existing user:
user = User.objects.get(username='user')
# If we attempt to log into the login page:
response = client.post('/users/login/', {'username': user.username, 'password': 'somepass'})
# Then the server should redirect the user to the default redirect location:
assert response.status_code == 302
My conftest.py file, in the same tests directory:
import pytest
from django.core.management import call_command
#pytest.fixture(autouse=True)
def django_db_setup(django_db_setup, django_db_blocker):
with django_db_blocker.unblock():
call_command('loaddata', 'test_users.json')
My pytest.ini file (which specifies the correct Django settings file):
[pytest]
DJANGO_SETTINGS_MODULE = config.settings
I'm stumped. I've tried using scope="session" like in the documentation together with either an #pytest.mark.django_db mark, a db fixture (as a parameter to the test function), or both with no luck. I've commented out each line of the test to figure out which one was triggering the problem, but couldn't figure it out. I could only get the test to run at all if I removed all db-dependent fixtures/marks/code from the test and had a simple assert True. I don't believe the issue is in my Django settings, as the development server runs fine and is able to access the database.
What am I missing here?
Apparently this is a case of "deceiving exception syndrome". I had a migration that created groups with permissions, and since tests run all migrations at once, the post-migrate signal that creates the permissions that migration depends on was never run before getting to that migration.
It seems that if there is any database-related error before the actual tests start running, this exception is raised, which makes it very difficult to debug exactly what is going wrong. I ended up updating my migration script to manually cause permissions to be created so that the migration could run, and the error went away.
You can add below code in your conftest.py as per the official documentation to allow DB access without django_db marker.
#pytest.fixture(autouse=True)
def enable_db_access_for_all_tests(db):
pass
Ref: https://pytest-django.readthedocs.io/en/latest/faq.html#how-can-i-give-database-access-to-all-my-tests-without-the-django-db-marker

Why I see no Django log in git-bash?

I am using Python 3's print to log from Django dev server. I should mention that I also tried to configure Django to use the Python logger but without much luck. I am using pipenv run but the same happens when I activate the virtual env using pipenv shell.
I have a very simple view:
from django.shortcuts import render
def index(request):
print('Printing to the console from myapp.views.index')
return render(request, 'myapp/index.html', {
'message': 'Hello, World!'
})
While everything works perfectly fine in cmd.exe, git-bash does not display any output from my custom logging. See image below.
Why is that? Does it have to deal with the fact that one console is considered a terminal (tty) and the other is not?

Django Selenium liveserver doesn't get started when running tests

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().

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.