How to fix "Django test setUp() function not creating the django users"? - django

I am doing the django test cases. Now I have a problem that, user created in django test is not shown in the database created for test. consider my database name as db.
from django.contrib.auth.models import User,AnonymousUser
from django.test import TestCase,LiveServerTestCase
from django.db import connection
class machinelist(TestCase):
def setUp(self):
self.user=User.objects.create_user(username="vishnu***",email="vishnu#clartrum.com",password="vishnu#12345")
print self.user.username
db_name = connection.settings_dict['NAME']
print db_name
t=raw_input("PAUSE")
def tearDown(self):
print 'd'
def test1(self):#view function
print "2"
The output will print the username vishnu*** and db_name as test_db. But when you observe the database, there is no data.
In the code, when the raw_input is executed, I will sign into the mysql server and verified that test_db is created successfully and also the django's tables. But when i checked auth_user table there is no data in it.
I am using django 1.11.20 and mysql 5.6.33.
Why User is not updating on the database table?

Tests inside TestCase classes run in a transaction, which is rolled back at the end of each test. Since the default MySQL transaction isolation level is REPEATABLE READ, the data inserted within the transaction is not visible from outside.
I'm not sure why you want to check the data from outside the test, though. You can print it or assert on it from within the test itself.

Related

why records are not being inserted into postgresql database in pytest-django?

I tried to use postgres database with pytest-django and I've encountered a problem. I have a fixture named populate_db which creates some records in the database. To check if pytest actually creates records, I put a 60-seconds sleep after creating the model objects and checked the panel admin but none of the created objects were present there. I think the pytest can't connect to my database and doesn't create any records in the database. Below are the functions that I have in my conftest.py file and I have another test file which tries to retrieve a database record from the API.
Here is my code for the populate_db fixture:
#pytest.fixture(autouse=True)
def populate_db():
sport = Vertical.objects.create(name='sport')
bazar = Vertical.objects.create(name='bazar')
time.sleep(60)
yield

Django LiveServerTestCase appears to reload fixtures between tests

I'm running this with Django 2.2.5 and Postgres 11
It appears that the Django test framework's LiveServerTestCase reloads fixture data in-between each test without deleting the previous data. I come across this with a consistent error:
> ./manage.py test functional_tests
Creating test database for alias 'default'...
System check identified no issues (0 silenced).
.EE
======================================================================
The first test passes but the subsequent tests fail.
The error I get is:
django.db.utils.IntegrityError: Problem installing fixture '.../fixtures/unit_test.json': Could not load app.Configuration(pk=1): duplicate key value violates unique constraint "app_configuration_site_id_3124a87d_uniq"
DETAIL: Key (site_id)=(1) already exists.
If I comment out and don't load fixtures the 3 tests work perfectly fine.
There is only one record entry with the PK in question in the fixtures. This tells me that the Test reloads the data and fails because it finds an existing record with the same PK.
Is there a way to tell it to either overwrite the data with the same PKs or ignore (a-la get_or_create)?
Is there a better practice to follow with LiveServerTestCase?
It's frustrating because I can't seem to be able to use this test class with fixtures when I need to.
Any insight is appreciated.
RB
Here is the test setup:
from django.contrib.staticfiles.testing import LiveServerTestCase
from selenium.webdriver.chrome.webdriver import WebDriver
class TestHeaderNavigation(LiveServerTestCase):
fixtures = ['unit_test']
def setUp(self):
super().setUp()
self.selenium = WebDriver()
self.selenium.implicitly_wait(5)
self.selenium.get('%s' % (self.live_server_url))
def tearDown(self):
super().tearDown()
self.selenium.quit()

Graphene query hangs indefinitely when testing with pytest

I am trying to test my backend, written in Django 2.2.2 and Python 3. I created some graphql queries which are definitely working when testing with the graphql web interface. When testing with pytest and the graphene test client, however, these queries would always hang indefinitely. I put together a reproducible example which is actually based on the code example from the graphene-django documentation.
test_example.py:
import pytest
import graphene
from graphene_django import DjangoObjectType
from graphene.test import Client
from django.db import models
class UserModel(models.Model):
name = models.CharField(max_length=100)
last_name = models.CharField(max_length=100)
class User(DjangoObjectType):
class Meta:
model = UserModel
class Query(graphene.ObjectType):
users = graphene.List(User)
def resolve_users(self, info):
return UserModel.objects.all()
schema = graphene.Schema(query=Query)
client = Client(schema)
def test_user():
query = '''
query {
users {
name,
lastName
}
}
'''
result = client.execute(query)
assert 0 # dummy assert
This example behaves in the same way (stalls forever, no errors). I am using the latest graphene-django (2.3.2) and pytest (4.6.3). I should probably also mention that I'm running this inside a Docker container. Any ideas why this happens? Is this a bug in the graphene-django library?
I found the answer myself after a while digging through the documentation. Pytest needs permission to use the database. So the issue is solved by simply adding the pytest mark #pytest.mark.django_db before the test. As an alternative the whole module can be marked to allow database access by using pytestmark = pytest.mark.django_db. See pytest-django docs.
The documentation says the tests will fail if db access is not granted, so I would not expect them to stall forever.

Run Django tests against an existing database with custom testrunner

I've got an application that is running Django 2 that connects to a Microsoft SQL Server backend.
We're in a big environment where things are pretty tightly controlled - a user account has access to the database that houses all the tables for my django application.
So I have found through various posts that I need to create a testrunner for my application - which is fine. I can override the setup_databases function - but I'm not sure exactly how to do that.
My TestRunner(DiscoverRunner) looks like this:
class ExistingDbTestRunner(DiscoverRunner):
""" A test runner to test without database creation """
def setup_databases(self, **kwargs):
""" Override the database creation defined in parent class """
# force Django to connect to the correct db for tests
connection = self.connections['default']
db_conf = connection.settings_dict
connection.connect()
def teardown_databases(self, old_config, **kwargs):
""" Override the database teardown defined in parent class """
pass
But this fails with AttributeError: 'ExistingDbTestRunner' object has no attribute 'connections'
I'm just trying to get this to use the 'default' database that I have set in the settings for testing purposes.
It's worth noting - the default database specified in settings is a duplicate copy of the production database with a different name.
So I just want my tests to run against this duplicate database. What should I be changing so it connects?
Django tests do not operate on existing database or are meant to be used that way. Django always creates a new database, with the name test_db_name_specified_in_settings for all its tests.
More documentation can be found here: https://docs.djangoproject.com/en/2.0/topics/testing/overview/#the-test-database

How to prepopulate test database by necessary data?

I need to do some unit tests in my Django project. The problem is that almost every use case depends on prepopulated database objects.
For example, I want to create a product and test, if there were all pre_save signals successful.
from django.contrib.auth.models import User
from django.test import TestCase
from .models import Product
class ProductTestCase(TestCase):
def setUp(self):
self.user = User.objects.create(username='test_user')
self.product = Product.objects.create(name='Test product',user=self.user)
def test_product_exists(self):
self.assertIsNotNone(self.product)
def product_is_active_by_default(self):
...
I can't do that because product has to have User object related. But I can't create a User object because User has to have related plan object. There are multiple plans in my production database from which one is default but there are no plans inside test database.
So to be able to do unit tests I need to prepopulate test database with multiple objects from multiple apps.
How can I do that?
you can simply use django fixtures for that :-)
first populate a sample db with data then export data with python manage.py dumpdata
then in one of your apps create a directory named fixtures and put exported json file there (named tests.json or something else)
in your test class load fixtures like this
class ProductTestCase(TestCase):
fixtures = ['tests.json', ]
checkout django docs
PS: checkout factory boy too (#Gabriel Muj) answer
I don't recommend using fixture since you will need to maintain them each time you make changes to the model. Here is a better approach on creating objects for tests by using this library https://factoryboy.readthedocs.io/en/latest/ which is more flexible.