Selenium cleaning database in Django Application - django

I have a Django Application and I'm trying to create some selenium tests for it. The problem is that every time I run the test my database gets cleaned.
This is my test:
import time
from django.contrib.auth.models import User
from django.contrib.staticfiles.testing import StaticLiveServerTestCase
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
class CrewTest(StaticLiveServerTestCase):
def setUp(self):
self.selenium = webdriver.Chrome('chromedriver')
super(CrewTest, self).setUp()
self.user = User.objects.create_user(username='user',
email=None,
password='password')
def test_register(self):
selenium = self.selenium
selenium.get('http://127.0.0.1:8000/static/myapp.html')
name = selenium.find_element_by_id('username')
password = selenium.find_element_by_id('password')
submit = selenium.find_element_by_id('submit')
name.send_keys('user')
password.send_keys('password')
submit.send_keys(Keys.RETURN)
selenium.page_source
time.sleep(1)
assert 'Welcome user' in selenium.page_source
The test is successful, but my database is empty after I run it. Should I have a separate database for selenium tests? Or can I just disable cleaning the database after the test.

Related

Transaction rollback and dropping database in pytest fixtures

I'm writing functional tests to test API endpoints with pytest.
I want to achieve:
that at the end of each test DB transaction rolls back so that each test starts with the same data.
at the end of the test session, I want to delete the testing DB.
Bellow is my conftest.py file, and what is currently happening is that transactions aren't rolled back, and when it comes to the end of the session, it keeps hanging at drop_database on teardown, while it doesn't hang at the beginning when checking if DB exists (marked also in comments).
What do I need to do to make those rollbacks? And is there anything else I need to close, in order for that drop_database to take place?
Thank you!
import pytest
import sqlalchemy
from sqlalchemy_utils import database_exists, create_database, drop_database
from alembic.command import upgrade
from alembic.config import Config
from flask import Flask
from flask_migrate import Migrate
from flask_sqlalchemy import SQLAlchemy
from api.views import dtm_api, diagrams_api, labels_api
from .data.dummy_data import import_dummy
ALEMBIC_CONFIG = 'migrations/alembic.ini'
#pytest.fixture(scope='session')
def app(request):
_app = Flask(__name__)
_app.config.from_object('api.config.TestingConfig')
_app.register_blueprint(diagrams_api.bp)
_app.register_blueprint(dtm_api.bp)
_app.register_blueprint(labels_api.bp)
ctx = _app.app_context()
ctx.push()
def teardown():
ctx.pop()
request.addfinalizer(teardown)
yield _app
#pytest.fixture(scope='session')
def test_client(app, request):
yield app.test_client()
#pytest.yield_fixture(scope='session')
def db(app, request):
engine = sqlalchemy.create_engine(app.config.get("SQLALCHEMY_DATABASE_URI"))
if database_exists(engine.url):
drop_database(engine.url) #here it doesn't hang
create_database(engine.url)
_db = SQLAlchemy()
_db.init_app(app)
_db.app = app
#Make migrations and add dummy data
Migrate(app, _db)
config = Config(ALEMBIC_CONFIG)
config.set_main_option("script_location", "migrations")
with app.app_context():
upgrade(config, 'head')
import_dummy(_db)
def teardown():
drop_database(engine.url) #here it hangs
engine.dispose()
request.addfinalizer(teardown)
yield _db
#pytest.fixture(scope='function', autouse=True)
def session(db, request):
connection = db.engine.connect()
options = dict(bind=connection, binds={}, autoflush=False, autocommit=False)
db.session = db.create_scoped_session(options=options)
def teardown():
db.session.rollback()
db.session.close()
connection.close()
request.addfinalizer(teardown)
yield db.session

Django test setup not being used

I am using Django cookiecutter 1.11 for a project.
Trying to write some basic tests for a model. But the setup method is not being used in the test cases.
from django.test import TestCase
from myapp.users.models import User
from ..models import Book
class ModelTests(TestCase):
def setup(self):
self.username = 'john'
self.password = '123'
self.user = User.objects.create(name=self.username,
password=self.password
)
def test_create_book(self):
Book.objects.create(artist=self.user,
title=“An Art Book“,
category=“Art”,
)
self.assertEquals(Book.objects.all().count(), 1)
I get this error message after running manage.py test
Book.objects.create(artist=self.user,
AttributeError: 'ModelTests' object has no attribute 'user'
But it works when I put the lines from setup into the test case.
Did I miss something?
The method should be called setUp, not setup.

Django pytest-selenium functional tests

I've created the tests folder, written my first test that should open a browser, point to a page and login, then go to home page.
Test run and fail, as expected, but I can't find out why.
browser should be available, pytest-selenium is installed by pip.
import pytest
from django.contrib.auth.models import Group, Permission, User
from django.test import TestCase, RequestFactory
class CreaPageTest(TestCase):
def setUp(self):
self.factory = RequestFactory()
def test_homepage(self):
request = self.client.get('/new')
request.user = self.user
self.assertEqual(request.status_code, 200)
def test_login(self):
request = self.client.get('/per/login')
username_field = self.browser.find_element_by_name('username')
username_field.send_keys('peppa')
password_field = self.browser.find_element_by_name('password')
password_field.send_keys('pig')
password_field.send_keys(Keys.RETURN)
test_homepage()
> username_field = self.browser.find_element_by_name('username')
E AttributeError: 'CreaPageTest' object has no attribute 'browser'
tests/test_ore_app_views.py:27: AttributeError
what am I missing?
Any advice to examples of this kind of test is really appreciated.
You should configure self.browser inside setUp function. You are also missing an import for Keys. Code should be like this.
import pytest
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from django.contrib.auth.models import Group, Permission, User
from django.test import TestCase, RequestFactory
class CreaPageTest(TestCase):
def setUp(self):
self.factory = RequestFactory()
self.browser = webdriver.Firefox()
Also please refer to the docs, here http://selenium-python.readthedocs.org/getting-started.html

How to prevent double data submission in flask-sqlalchemy

I'm studying now main concepts of flask and flask-sqlalchemy. Keeping in my mind info from the tutorial (intro and contexts) I'm trying to create a simple database.
My Flask app is strucured as follows:
./db/
./db/models.py
./main.py
The contents of the files is as follows:
./main.py:
from flask import Flask
from flask.ext.sqlalchemy import SQLAlchemy
app = Flask(__name__)
app.config.from_object(__name__)
from db.models import create_app
dbapp = create_app()
with dbapp.test_request_context():
from db.models import db, mumsUsers
db.create_all()
db.session.rollback()
admin = mumsUsers("admin", "admin#example.com")
db.session.add(admin)
db.session.commit()
./db/models.py:
from flask.ext.sqlalchemy import SQLAlchemy
from flask import Flask, current_app
db = SQLAlchemy()
def create_app():
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:////tmp/test.db'
db.init_app(app)
return(app)
class mumsUsers(db.Model):
__tablename__ = 'mumsUsers'
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(80), unique=True)
email = db.Column(db.String(80), unique=True)
def __init__(self, username, email):
self.username = username
self.email = email
def __repr__(self):
return '<User %r>' % self.username
When I check the sqlite database, I see that sqlalchemy is trying to send commit() twice. So I have to remove the unique=True parameter in order to stop application crash. Meantime when I run the following commans from the python shell:
admin = mumsUsers('admin', 'admin#example.com')
db.session.add(admin)
db.session.commit()
only one record appears (as it is expected).
Therefore my question is how to prevent double call for commit()?
Update
The appeared problem has been caused by my fault, while making looped imports. Indeed I didn't notice I called import for the application package.
Therefore please ignore this post.
The caused problem has been related to looped imports.
Please check what you import before asking.

Unregistering default Django apps from admin breaks tests

In one of my apps/admin.py I have
from django.contrib import admin
from django.contrib.sites.models import Site
from django.contrib.redirects.models import Redirect
from mezzanine.generic.models import ThreadedComment
from mezzanine.conf.models import Setting
admin.site.unregister(Site)
admin.site.unregister(Redirect)
admin.site.unregister(ThreadedComment)
admin.site.unregister(Setting)
This causes them to be removed from the admin like I want, and the application works fine.
However, when I run my tests via nose, I get this error raise NotRegistered('The model %s is not registered' % model.__name__)
NotRegistered: The model Site is not registered Which I assume is because it is trying to unregister something which is already unregistered. This is an example of a test that is failing:
class TestRegistration(TestCase):
def setUp(self):
self.client = Client()
email = ConfirmedEmail(email='test.com',company='Test Industries')
email.save()
def test_landing(self):
response = self.client.get(reverse('home'))
self.assertEqual(response.status_code, 200)