Meine Django Komponententests dauern sehr lange, daher suche ich nach Möglichkeiten, dies zu beschleunigen. Ich erwäge die Installation einer SSD , aber ich weiß, dass dies auch Nachteile hat. Natürlich gibt es Dinge, die ich mit meinem Code tun könnte, aber ich suche nach einer strukturellen Lösung. Selbst das Ausführen eines einzelnen Tests ist langsam, da die Datenbank dies benötigt jedes Mal wieder aufgebaut/nach Süden migriert werden. Also hier ist meine Idee ...
Da ich weiß, dass die Testdatenbank immer recht klein ist, kann ich das System nicht so konfigurieren, dass immer die gesamte Testdatenbank im RAM bleibt. Berühren Sie niemals die Scheibe. Wie konfiguriere ich das in Django? Ich würde es vorziehen, weiterhin MySQL zu verwenden, da dies das ist, was ich in der Produktion verwende, aber wenn SQLite 3 oder etwas anderes dies einfach macht, würde ich diesen Weg gehen.
Verfügt SQLite oder MySQL über eine Option, um vollständig im Arbeitsspeicher ausgeführt zu werden? Es sollte möglich sein, eine RAM Disk zu konfigurieren und dann die Testdatenbank so zu konfigurieren, dass ihre Daten dort gespeichert werden, aber ich bin nicht sicher, wie ich Django/MySQL verwendet ein anderes Datenverzeichnis für eine bestimmte Datenbank, insbesondere weil es bei jedem Durchlauf gelöscht und neu erstellt wird. (Ich bin auf einem Mac FWIW.)
Wenn Sie Ihr Datenbankmodul bei der Ausführung Ihrer Tests auf sqlite3 setzen, Django verwendet eine speicherinterne Datenbank .
Ich verwende Code wie diesen in meinem settings.py
, um die Engine beim Ausführen meiner Tests auf SQLite zu setzen:
if 'test' in sys.argv:
DATABASE_ENGINE = 'sqlite3'
Oder in Django 1.2:
if 'test' in sys.argv:
DATABASES['default'] = {'ENGINE': 'sqlite3'}
Und schließlich in Django 1.3 und 1.4:
if 'test' in sys.argv:
DATABASES['default'] = {'ENGINE': 'Django.db.backends.sqlite3'}
(Der vollständige Pfad zum Backend ist bei Django 1.3 nicht unbedingt erforderlich, macht die Einstellung jedoch vorwärtskompatibel.)
Sie können auch die folgende Zeile hinzufügen, falls Sie Probleme mit Südmigrationen haben:
SOUTH_TESTS_MIGRATE = False
Normalerweise erstelle ich eine separate Einstellungsdatei für Tests und verwende sie im Testbefehl, z.
python manage.py test --settings=mysite.test_settings myapp
Es hat zwei Vorteile:
Sie müssen nicht nach test
oder einem solchen Zauberwort in sys.argv suchen, test_settings.py
Kann einfach sein
from settings import *
# make tests faster
SOUTH_TESTS_MIGRATE = False
DATABASES['default'] = {'ENGINE': 'Django.db.backends.sqlite3'}
Sie können es aber auch an Ihre Anforderungen anpassen und die Testeinstellungen sauber von den Produktionseinstellungen trennen.
Ein weiterer Vorteil ist, dass Sie Tests mit der Produktionsdatenbank-Engine ausführen können, anstatt sqlite3 zu verwenden, um subtile Fehler zu vermeiden
python manage.py test --settings=mysite.test_settings myapp
und vor dem Festschreiben des Codes einmal ausführen
python manage.py test myapp
nur um sicherzugehen, dass alle Tests wirklich bestanden haben.
MySQL unterstützt eine Speicher-Engine namens "MEMORY", die Sie in Ihrer Datenbankkonfiguration (settings.py
) Folgendermaßen konfigurieren können:
'USER': 'root', # Not used with sqlite3.
'PASSWORD': '', # Not used with sqlite3.
'OPTIONS': {
"init_command": "SET storage_engine=MEMORY",
}
Beachten Sie, dass die MEMORY-Speicher-Engine keine Blob-/Textspalten unterstützt. Wenn Sie also Django.db.models.TextField
Verwenden, funktioniert dies nicht für Sie.
Ich kann Ihre Hauptfrage nicht beantworten, aber es gibt ein paar Dinge, die Sie tun können, um die Dinge zu beschleunigen.
Stellen Sie zunächst sicher, dass Ihre MySQL-Datenbank für die Verwendung von InnoDB eingerichtet ist. Dann kann es Transaktionen verwenden, um den Status der Datenbank vor jedem Test zurückzusetzen, was meiner Erfahrung nach zu einer massiven Beschleunigung geführt hat. Sie können einen Datenbank-Init-Befehl in Ihrer settings.py übergeben (Django 1.2-Syntax):
DATABASES = {
'default': {
'ENGINE':'Django.db.backends.mysql',
'Host':'localhost',
'NAME':'mydb',
'USER':'whoever',
'PASSWORD':'whatever',
'OPTIONS':{"init_command": "SET storage_engine=INNODB" }
}
}
Zweitens müssen Sie die Südmigrationen nicht jedes Mal durchführen. Einstellen SOUTH_TESTS_MIGRATE = False
in Ihrer settings.py und die Datenbank wird mit einfachem syncdb erstellt, was viel schneller ist als das Durchlaufen aller historischen Migrationen.
Sie können doppelte Optimierungen vornehmen:
Ich benutze beide Tricks und bin ziemlich glücklich.
So richten Sie es für MySQL unter Ubuntu ein:
$ 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
Achtung, es ist nur zum Testen, nach dem Neustart geht Ihre Datenbank aus dem Speicher verloren!
Ein anderer Ansatz: Lassen Sie eine andere Instanz von MySQL in einem tempfs laufen, das eine RAM Disk verwendet. Anweisungen in diesem Blogeintrag: Beschleunigen von MySQL für Testen in Django .
Vorteile:
Ausgehend von der Antwort von Anurag habe ich den Prozess vereinfacht, indem ich dieselben test_settings erstellt und Folgendes zu manage.py hinzugefügt habe
if len(sys.argv) > 1 and sys.argv[1] == "test":
os.environ.setdefault("Django_SETTINGS_MODULE", "mysite.test_settings")
else:
os.environ.setdefault("Django_SETTINGS_MODULE", "mysite.settings")
scheint sauberer zu sein, da sys bereits importiert ist und manage.py nur über die Befehlszeile verwendet wird, sodass keine Einstellungen überladen werden müssen