Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django testing on separate database giving "OperationalError: no such table: auth_user"

My problem is that I wanted to put up a separate testing database, separate from my development database. App itself is almost identical to Django-Rest-Framework quick-start tutorial, just that I use LDAP backend. My development database uses MySQL. I have separate settings file for testing.

Full error traceback I put in here: http://dpaste.com/1W3TX1E, but interesting part is:

sqlite3.OperationalError: no such table: auth_user

Full test-settings are here: http://dpaste.com/1K7KHK4. My related settings are (pyldap and django-ldap-auth are missing from installed apps, they are installed manually with pip):

    INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'rest_framework',
    'njord',
    'permissions',
]
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': ':memory:',
    }
}

Right now the app does basically only authentication with LDAP. I think that is why I have an error - when I do tests I have nothing in my database - no users, no groups. If a user is authenticated against LDAP server, user is created in database alongside with all the groups he/she is in, so it happens on-demand.

What works: Development version of my app works well against external LDAP and also testing works with development database.

What does not work: Testing with sqllite3 in-memory database(I repeat, testing with development database and mocked ldap works).

The code I test with is here:

from django.test import TestCase, Client
import django
import ldap

from mockldap import MockLdap

class AuthenticationTests(TestCase):
    """
    Set Up the structure  ( Accounts, Groups ) and try authentication
    """
    # Top level hierarchy
    top = ('dc=ee', {'dc': ['ee']})
    test = ('dc=test,dc=ee', {'dc': ['test']})

    # Top level groups
    people = ('ou=people,dc=test,dc=ee', {'ou': ['people'], 'objectClass': ['organizationalUnit', 'top']})
    groups = ('ou=groups,dc=test,dc=ee', {'ou': ['groups'], 'objectClass': ['organizationalUnit', 'top']})

    # Groups
    admins = ('cn=admins,ou=groups,dc=test,dc=ee', {'cn': ['admins'], 'memberUid': ['admin'],
                                                'objectClass': ['sambaGroupMapping', 'posixGroup', 'top'],
                                                'gidNumber': ['1']})

    group1 = ('cn=group1,ou=groups,dc=test,dc=ee', {'cn': ['group1'],
                                                'memberUid': ['alice', 'bob'],
                                      'objectClass': ['sambaGroupMapping', 'posixGroup', 'top']})

    group2 = ('cn=group2,ou=groups,dc=test,dc=ee', {'cn': ['group2'], 'memberUid': ['admin', 'bob', 'karl'],
                                      'objectClass': ['sambaGroupMapping', 'posixGroup', 'top']})

    # Users
    admin = ('uid=admin,ou=people,dc=test,dc=ee', {'uid': ['admin'], 'userPassword': ['ldaptest'], 'sn': ['Joe'],
                                               'cn': ['Admin Joe'], 'mail': ['[email protected]'],
                                               'givenName': ['Admin'], 'objectClass':
                                                   ['top', 'person', 'posixAccount', 'shadowAccount',
                                                    'inetOrgPerson', 'sambaSamAccount']})

    alice = ('uid=alice,ou=people,dc=test,dc=ee', {'uid': ['alice'], 'userPassword': ['ldaptest'], 'sn': ['Cooper'],
                                               'cn': ['Alice Cooper'], 'mail': ['[email protected]'],
                                               'givenName': ['Alice'], 'objectClass':
                                                   ['top', 'person', 'posixAccount', 'shadowAccount',
                                                    'inetOrgPerson', 'sambaSamAccount']})

    bob = ('uid=bob,ou=people,dc=test,dc=ee', {'uid': ['bob'], 'userPassword': ['ldaptest'], 'sn': ['Marley'],
                                           'cn': ['Bob Marley'], 'mail': ['[email protected]'],
                                           'givenName': ['Bob'], 'objectClass':
                                               ['top', 'person', 'posixAccount', 'shadowAccount',
                                                'inetOrgPerson', 'sambaSamAccount']})

    karl = ('uid=karl,ou=people,dc=test,dc=ee', {'uid': ['karl'], 'userPassword': ['ldaptest'], 'sn': ['Suur'],
                                             'cn': ['Karl Suur'], 'mail': ['[email protected]'],
                                             'givenName': ['Karl'], 'objectClass':
                                                 ['top', 'person', 'posixAccount', 'shadowAccount',
                                                  'inetOrgPerson', 'sambaSamAccount']})

    # This is the content of our mock LDAP directory. It takes the form
    # {dn: {attr: [value, ...], ...}, ...}.
    directory = dict([top, test, people, groups, admins, group1, group2, admin, alice, bob, karl])

    @classmethod
    def setUpTestData(cls):
        # We only need to create the MockLdap instance once. The content we
        # pass in will be used for all LDAP connections.
        cls.mockldap = MockLdap(cls.directory)

    @classmethod
    def tearDownClass(cls):
        del cls.mockldap

    def setUp(self):
        # Patch ldap.initialize
        django.setup()
        self.mockldap.start()
        self.ldapobj = self.mockldap['ldap://localhost/']

    def tearDown(self):
        # Stop patching ldap.initialize and reset state.
        self.mockldap.stop()
        del self.ldapobj

    def test_some_basic_mockldap_auth(self):
        searchStr = 'uid=alice,ou=people,dc=test,dc=ee'
        results = _do_simple_ldap_search(searchStr)
        ldapName = results[0][0]
        ldapPropDict = results[0][1]
        self.assertEqual(searchStr, ldapName)
        self.assertEqual(len(ldapPropDict), 7)

    def test_index_visible_for_all(self):
        c = Client()
        response = c.get("/")
        self.assertContains(response, "/users/", 1)
        self.assertContains(response, "/groups/", 1)

    def test_login(self):
        c = Client()
        response = c.post("/api-auth/login/", {'username': 'bob', 'password': 'ldaptest'})
        print(response.status_code)
        response = c.get("/users/")
        print(response._container)

def _do_simple_ldap_search(searchStr):
    conn = ldap.initialize('ldap://localhost/')
    conn.simple_bind_s(searchStr, 'ldaptest')
    results = conn.search_s(searchStr, ldap.SCOPE_SUBTREE, )

    return results

Code also available here: http://dpaste.com/3D2H4NK (syntax highlight).

I am not sure, what the problem is. Only thing I can think of is that because there are no users in database at the creation, database is not created, but I am not sure. Any help is much appreciated.

I have done all the migrations.

(venv)user@box:~/workspace/fileshare/njord$ python manage.py showmigrationsadmin
 [X] 0001_initial
 [X] 0002_logentry_remove_auto_add
auth
 [X] 0001_initial
 [X] 0002_alter_permission_name_max_length
 [X] 0003_alter_user_email_max_length
 [X] 0004_alter_user_username_opts
 [X] 0005_alter_user_last_login_null
 [X] 0006_require_contenttypes_0002
 [X] 0007_alter_validators_add_error_messages
contenttypes
 [X] 0001_initial
 [X] 0002_remove_content_type_name
sessions
 [X] 0001_initial
(venv)user@box:~/workspace/fileshare/njord$ python manage.py makemigrationsNo changes detected
(venv)user@box:~/workspace/fileshare/njord$ python manage.py migrate
Operations to perform:
  Apply all migrations: admin, sessions, auth, contenttypes
Running migrations:
  No migrations to apply.
like image 785
La'tel Avatar asked Jul 15 '16 08:07

La'tel


1 Answers

run
python manage.py makemigrations <appname>
for each applications in INSTALLED_APPS.(Specially the apps that has a ForeignKey field on auth_user)

I got different error to get me here, but think cause is the same.
django.db.utils.OperationalError: (1005, "Can't create table '<test_db>.#sql-3821_1c9' (errno: 150)")

In both cases all tables related to auth module are only not created when testing, without executing makemigrations command.
I found the solution from here

like image 53
ruwan800 Avatar answered Oct 13 '22 17:10

ruwan800