135 votes

Comment faire fonctionner django ' base de données de test s uniquement en mémoire ?

Mon django tests unitaires prendre beaucoup de temps pour courir, donc je suis à la recherche de moyens à la vitesse. J'envisage l'installation d'un SSD, mais je sais qui a ses inconvénients aussi. Bien sûr il y a des choses que je pouvais faire avec mon code, mais je suis à la recherche d'une structurel corrigé. Même en cours d'exécution d'un test unique est lent depuis la base de données doit être reconstruit / sud migré à chaque fois. Voici donc mon idée...

Depuis que je connais la base de données de test sera toujours assez faible, pourquoi ne puis-je configurer le système afin de toujours garder la totalité de la base de données de test dans la mémoire RAM? Ne jamais toucher le disque. Quelqu'un sait comment configurer cela dans django? Je préfère garder de l'utilisation de mysql puisque c'est ce que j'utilise dans la production, mais si sqlite3 ou autre chose qui rend ce facile, j'irais de cette façon.

Ne sqlite ou mysql dispose d'une option permettant d'exécuter entièrement dans la mémoire? Il devrait être possible de configurer un disque RAM et ensuite configurer la base de données de test pour stocker ses données, mais je ne suis pas sûr de la façon de dire django / mysql pour utiliser un autre datadir pour une certaine base de données, en particulier depuis il ne cesse de se effacé et recréé à chaque exécution. (Je suis sur un Mac FWIW.)

Tous les pointeurs ou de l'expérience appréciée. Toutes mes excuses si ce n'est pas littéralement une question sur code, mais il est certainement un logiciel d'ingénierie problème que je pari serait bénéfique beaucoup de gens si il y a un élégant résoudre.

177voto

Etienne Points 6176

Si vous réglez votre moteur de base de données sqlite3 lorsque vous exécutez vos tests, Django utilisera une base de données en mémoire.

Je suis en utilisant ce type de code pour définir le moteur sqlite lors de l'exécution de mes tests:

if 'test' in sys.argv:
    DATABASE_ENGINE = 'sqlite3'

Ou dans Django 1.2:

if 'test' in sys.argv:
    DATABASES['default'] = {'ENGINE': 'sqlite3'}

Et enfin dans Django 1.3 et 1.4:

if 'test' in sys.argv:
    DATABASES['default'] = {'ENGINE': 'django.db.backends.sqlite3'}

(Le chemin d'accès complet à l'arrière-plan n'est pas strictement nécessaire avec Django 1.3, mais rend la mise en avant de compatibilité.)

86voto

Anurag Uniyal Points 31931

J'ai l'habitude de créer un fichier de paramètres pour les tests et les utiliser dans la commande test par exemple

python manage.py test --settings=mysite.test_settings myapp

Il a deux avantages:

  1. Vous n'avez pas à vérifier test ou le mot magique dans le sys.argv, test_settings.py peut être simplement

    from settings import *
    
    # make tests faster
    SOUTH_TESTS_MIGRATE = False
    DATABASES['default'] = {'ENGINE': 'django.db.backends.sqlite3'}
    

    Ou vous pouvez l'ajuster à vos besoins, proprement, la séparation des paramètres de test à partir de paramètres de production.

  2. Un autre avantage est que vous pouvez exécuter le test avec la production de moteur de base de données au lieu de sqlite3 éviter les bogues subtils, de sorte que, tout en développant l'utilisation

    python manage.py test --settings=mysite.test_settings myapp
    

    et avant d'engager de code à exécuter une seule fois

    python manage.py test myapp
    

    juste pour être sûr que tous les tests sont vraiment passer.

21voto

muudscope Points 1326

MySQL supporte un moteur de stockage appelé « Mémoire », qui vous pouvez de configurer dans votre fichier de config de base de données ( `` ) comme tel :

Remarque que le moteur de table MEMORY ne supporte pas les blob / colonnes de texte, donc si vous utilisez `` cela ne marchera pas pour vous.

14voto

Daniel Roseman Points 199743

Je ne peux pas répondre à votre question principale, mais il ya un couple de choses que vous pouvez faire pour accélérer les choses.

Tout d'abord, assurez-vous que votre base de données MySQL est configuré pour utiliser InnoDB. Ensuite, il peut utiliser les opérations de restauration de l'état de la db avant chaque test, ce qui dans mon expérience a conduit à une énorme vitesse. Vous pouvez passer d'une base de données de la commande init dans votre settings.py (Django 1.2 syntaxe):

DATABASES = {
    'default': {
            'ENGINE':'django.db.backends.mysql',
            'HOST':'localhost',
            'NAME':'mydb',
            'USER':'whoever',
            'PASSWORD':'whatever',
            'OPTIONS':{"init_command": "SET storage_engine=INNODB" } 
        }
    }

Deuxièmement, vous n'avez pas besoin d'exécuter le Sud migrations à chaque fois. Ensemble SOUTH_TESTS_MIGRATE = False dans votre settings.py et la base de données sera créée avec la plaine syncdb, qui sera beaucoup plus rapide que de courir à travers tout l'historique des migrations.

10voto

Potr Czachur Points 1556

Vous pouvez faire un double de peaufinage:

  • utilisation transactionnelle tables: les premiers montages de l'état à l'aide de la base de données de restauration après chaque cas de test.
  • mettre votre base de données dir sur ramdisk: vous gagnerez plus loin que la création de la base, et aussi un test en cours sera plus rapide.

Je suis à l'aide de deux tours et je suis très heureux.

Comment le mettre en place pour MySQL sous Ubuntu:

$ sudo service mysql stop
$ sudo cp -pRL /var/lib/mysql /dev/shm/mysql

$ vim /etc/mysql/my.cnf
# datadir = /dev/shm/mysql
$ sudo service mysql start

Méfiez-vous, c'est juste pour le test, après le redémarrage de votre base de données à partir de la mémoire est perdu!

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X