Search code examples
djangoneo4jneomodel

Django testing of neo4j database


I'm using django with neo4j as database and noemodel as OGM. How do I test it?

When I run python3 manage.py test all the changes, my tests make are left.

And also how do I make two databases, one for testing, another for working in production and specify which one to use how?


Solution

  • I assume the reason all of your changes are being retained is due to using the same neo4j database for testing as you are using in development. Since neomodel isn't integrated tightly with Django it doesn't act the same way Django's ORM does when testing. Django will do some helpful things when you run tests using its ORM, such as creating a test database that will be destroyed upon completion.

    With neo4j and neomodel I'd recommend doing the following:

    Create a Custom Test Runner

    Django enables you to define a custom test runner by setting the TEST_RUNNER settings variable. An extremely simple version of this to get you going would be:

    from time import sleep
    from subprocess import call
    
    from django.test.runner import DiscoverRunner
    
    
    class MyTestRunner(DiscoverRunner):
        def setup_databases(self, *args, **kwargs):
            # Stop your development instance
            call("sudo service neo4j-service stop", shell=True)
            # Sleep to ensure the service has completely stopped
            sleep(1)
            # Start your test instance (see section below for more details)
            success = call("/path/to/test/db/neo4j-community-2.2.2/bin/neo4j"
                           " start-no-wait", shell=True)
            # Need to sleep to wait for the test instance to completely come up
            sleep(10)
            if success != 0:
                return False
            try:
                # For neo4j 2.2.x you'll need to set a password or deactivate auth
                # Nigel Small's py2neo gives us an easy way to accomplish this
                call("source /path/to/virtualenv/bin/activate && "
                     "/path/to/virtualenv/bin/neoauth "
                     "neo4j neo4j my-p4ssword")
            except OSError:
                pass
            # Don't import neomodel until we get here because we need to wait 
            # for the new db to be spawned
            from neomodel import db
            # Delete all previous entries in the db prior to running tests
            query = "match (n)-[r]-() delete n,r"
            db.cypher_query(query)
            super(MyTestRunner, self).__init__(*args, **kwargs)
    
        def teardown_databases(self, old_config, **kwargs):
            from neomodel import db
            # Delete all previous entries in the db after running tests
            query = "match (n)-[r]-() delete n,r"
            db.cypher_query(query)
            sleep(1)
            # Shut down test neo4j instance
            success = call("/path/to/test/db/neo4j-community-2.2.2/bin/neo4j"
                           " stop", shell=True)
            if success != 0:
                return False
            sleep(1)
            # start back up development instance
            call("sudo service neo4j-service start", shell=True)
    

    Add a secondary neo4j database

    This can be done in a couple ways but to follow along with the test runner above you can download a community distribution from neo4j's website. With this secondary instance you can now swap between which database you'd like to use utilizing the command line statements used in the calls within the test runner.

    Wrap Up

    This solution assume's you're on a linux box but should be portable to a different OS with minor modifications. Also I'd recommend checking out the Django's Test Runner Docs to expand upon what the test runner can do.