tests - python django unittest




Wie kann Djangos Testdatenbank nur im Speicher ausgeführt werden? (5)

Ein anderer Ansatz: Lassen Sie eine andere MySQL-Instanz in einem tempfs laufen, der eine RAM-Disk verwendet. Anleitung in diesem Blogbeitrag: Beschleunigung von MySQL zum Testen in Django .

Vorteile:

  • Sie verwenden genau die gleiche Datenbank, die Ihr Produktionsserver verwendet
  • keine Notwendigkeit, Ihre Standard-MySQL-Konfiguration zu ändern

Meine Django-Komponententests benötigen viel Zeit, daher suche ich nach Möglichkeiten, dies zu beschleunigen. Ich überlege mir, eine SSD installieren, aber ich weiß, dass das auch seine Schattenseiten hat. Natürlich gibt es Dinge, die ich mit meinem Code machen könnte, aber ich suche nach einer strukturellen Lösung. Das Ausführen eines einzelnen Tests ist langsam, da die Datenbank jedes Mal neu erstellt / nach Süden migriert werden muss. Also hier ist meine Idee ...

Da ich weiß, dass die Testdatenbank immer sehr klein sein wird, warum kann ich das System nicht so konfigurieren, dass immer die gesamte Testdatenbank im RAM bleibt? Berühren Sie niemals die Festplatte. Wie konfiguriere ich das in Django? Ich würde es vorziehen, MySQL da ich es 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, die vollständig im Speicher ausgeführt werden kann? Es sollte möglich sein, eine RAM-Disk zu konfigurieren und dann die Test-Datenbank zu konfigurieren, um ihre Daten dort zu speichern, aber ich bin nicht sicher, wie man Django / MySQL anweist, ein anderes Datenverzeichnis für eine bestimmte Datenbank zu verwenden, besonders da es immer gelöscht wird und erstellt jeden Lauf neu. (Ich bin auf einem Mac FWIW.)


Erweiternd auf Anurags Antwort Ich vereinfachte den Prozess, indem ich die gleichen test_settings erstellte und zu manage.py folgendes hinzufügte

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")

Es scheint sauberer zu sein, da sys bereits importiert wurde und manage.py nur über die Befehlszeile verwendet wird, sodass keine Einstellungen unnötig werden


MySQL unterstützt eine Speicher-Engine namens "MEMORY", die Sie in Ihrer Datenbank-Konfiguration ( settings.py ) als solche 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 Speicher-Engine MEMORY keine Blob / Text-Spalten unterstützt. Wenn Sie also django.db.models.TextField verwenden, django.db.models.TextField dies nicht für Sie.


Normalerweise erstelle ich eine separate Einstellungsdatei für Tests und verwende sie im Testbefehl zB

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

Es hat zwei Vorteile:

  1. Sie müssen in sys.argv nicht nach einem test oder einem solchen Zauberwort suchen, test_settings.py kann einfach sein

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

    Oder Sie können es für Ihre Bedürfnisse weiter optimieren, indem Sie die Testeinstellungen sauber von den Produktionseinstellungen trennen.

  2. Ein weiterer Vorteil ist, dass Sie Test mit Produktionsdatenbank-Engine anstelle von sqlite3 ausführen können, um subtile Fehler zu vermeiden, also während der Entwicklung

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

    und bevor der Code ausgeführt wird, wird er einmal ausgeführt

    python manage.py test myapp
    

    nur um sicher zu gehen, dass alle Tests wirklich bestanden werden.


Wenn Sie Ihre Datenbank-Engine beim Ausführen der Tests auf sqlite3 setzen, verwendet Django eine speicherinterne Datenbank .

Ich verwende einen Code wie diesen in meiner settings.py , um die Engine auf sqlite zu setzen, wenn ich meine Tests durchführe:

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, aber die Einstellung wird mit dem Befehl kompatibel gemacht.)

Sie können auch die folgende Zeile hinzufügen, falls Sie Probleme mit South-Migrationen haben:

    SOUTH_TESTS_MIGRATE = False




unit-testing