Django                
            Unit Testing
        
        
            
    Suche…
Testen - ein vollständiges Beispiel
Dies setzt voraus, dass Sie die Dokumentation zum Starten eines neuen Django-Projekts gelesen haben. Nehmen wir an, die Haupt-App in Ihrem Projekt heißt td (kurz für testgetrieben). Um Ihren ersten Test zu erstellen, erstellen Sie eine Datei mit dem Namen test_view.py und fügen Sie den folgenden Inhalt ein.
from django.test import Client, TestCase
class ViewTest(TestCase):
    def test_hello(self):
        c = Client()
        resp = c.get('/hello/')
        self.assertEqual(resp.status_code, 200)
Sie können diesen Test mit durchführen
 ./manage.py test
und es wird am natürlichsten scheitern! Es wird ein Fehler ähnlich dem folgenden angezeigt.
Traceback (most recent call last):
  File "/home/me/workspace/td/tests_view.py", line 9, in test_hello
    self.assertEqual(resp.status_code, 200)
AssertionError: 200 != 404
Warum passiert das? Weil wir noch keine Sicht dafür definiert haben! Also machen wir's. Erstellen Sie eine Datei mit dem Namen views.py, und fügen Sie den folgenden Code ein
from django.http import HttpResponse
def hello(request):
    return HttpResponse('hello')
Als nächstes ordnen Sie es dem / hello / durch Bearbeiten der URLs py wie folgt zu:
from td import views
urlpatterns = [
    url(r'^admin/', include(admin.site.urls)),
    url(r'^hello/', views.hello),
    ....
]
 Führen Sie den Test jetzt erneut aus ./manage.py test erneut und Viola !! 
Creating test database for alias 'default'...
.
----------------------------------------------------------------------
Ran 1 test in 0.004s
OK
Django-Modelle effektiv testen
Eine Klasse annehmen
from django.db import models
class Author(models.Model):
   name = models.CharField(max_length=50)
   
    def __str__(self):
        return self.name
    
    def get_absolute_url(self):
        return reverse('view_author', args=[str(self.id)])
class Book(models.Model):
    author = models.ForeignKey(Manufacturer, on_delete=models.CASCADE)
    private = models.BooleanField(default=false)
    publish_date = models.DateField()
    def get_absolute_url(self):
        return reverse('view_book', args=[str(self.id)])
    
    def __str__(self):
        return self.name
Testbeispiele
from django.test import TestCase
from .models import Book, Author
class BaseModelTestCase(TestCase):
    @classmethod
    def setUpClass(cls):
        super(BaseModelTestCase, cls).setUpClass()
        cls.author = Author(name='hawking')
        cls.author.save()
        cls.first_book = Book(author=cls.author, name="short_history_of_time")
        cls.first_book.save()
        cls.second_book = Book(author=cls.author, name="long_history_of_time")
        cls.second_book.save()
class AuthorModelTestCase(BaseModelTestCase):
    def test_created_properly(self):
         self.assertEqual(self.author.name, 'hawking')
         self.assertEqual(True, self.first_book in self.author.book_set.all())
    
    def test_absolute_url(self):
        self.assertEqual(self.author.get_absolute_url(), reverse('view_author', args=[str(self.author.id)]))
class BookModelTestCase(BaseModelTestCase):
    
    def test_created_properly(self:
        ...
        self.assertEqual(1, len(Book.objects.filter(name__startswith='long'))
    
    def test_absolute_url(self):
        ...
Ein paar Punkte
-  created_properlyTests werden verwendet, um die Zustandseigenschaften von Django-Modellen zu überprüfen. Sie helfen dabei, Sicherheitsmaßnahmen zu treffen, wenn wir Standardwerte, file_upload_paths usw. geändert haben.
-  absolute_urlmag trivial erscheinen, aber ich habe festgestellt, dass es mir dabei geholfen hat, einige Fehler beim Ändern von URL-Pfaden zu vermeiden
-  Ebenso schreibe ich Testfälle für alle innerhalb eines Modells implementierten Methoden (unter Verwendung von mockObjekten usw.).
-  Durch die Definition eines gemeinsamen BaseModelTestCasewir die notwendigen Beziehungen zwischen den ModellenBaseModelTestCase, um ein ordnungsgemäßes Testen sicherzustellen.
Wenn Sie Zweifel haben, schreiben Sie einen Test. Triviale Verhaltensänderungen werden durch die Aufmerksamkeit für Details aufgefangen und lange vergessene Teile des Codes verursachen keine unnötigen Probleme.
Zugriffssteuerung in Django-Ansichten testen
 tl; dr : Erstellen Sie eine Basisklasse, die zwei Benutzerobjekte definiert (z. B. user und another_user ). Erstellen Sie Ihre anderen Modelle und definieren Sie drei Client Instanzen. 
-  self.client: In Browser angemeldeteruser
-  self.another_client: Repräsentant eines anderenanother_user
-  self.unlogged_client: Repräsentation einer nicht angemeldeten Person
 Greifen Sie jetzt auf alle Ihre öffentlichen und privaten URLs von diesen drei Clientobjekten zu und richten Sie die erwartete Antwort ein. Im Folgenden habe ich die Strategie für ein Book Objekt vorgestellt, das entweder private (im Besitz einiger privilegierter Benutzer) oder public (für jeden sichtbar) sein kann. 
from django.test import TestCase, RequestFactory, Client
from django.core.urlresolvers import reverse
class BaseViewTestCase(TestCase):
    @classmethod
    def setUpClass(cls):
        super(BaseViewTestCase, cls).setUpClass()
        cls.client = Client()
        cls.another_client = Client()
        cls.unlogged_client = Client()
        cls.user = User.objects.create_user(
                'dummy',password='dummy'
                )
        cls.user.save()
        cls.another_user = User.objects.create_user(
                'dummy2', password='dummy2'
                )
        cls.another_user.save()
        cls.first_book = Book.objects.create(
                name='first',
                private = true
        )
        cls.first_book.readers.add(cls.user)
        cls.first_book.save()
        cls.public_book = Template.objects.create(
                name='public',
                private=False
        )
        cls.public_book.save()
    def setUp(self):
        self.client.login(username=self.user.username, password=self.user.username)
        self.another_client.login(username=self.another_user.username, password=self.another_user.username)
"""
   Only cls.user owns the first_book and thus only he should be able to see it.
   Others get 403(Forbidden) error
"""
class PrivateBookAccessTestCase(BaseViewTestCase):
    
    def setUp(self):
        super(PrivateBookAccessTestCase, self).setUp()
        self.url = reverse('view_book',kwargs={'book_id':str(self.first_book.id)})
    def test_user_sees_own_book(self):
        response = self.client.get(self.url)
        self.assertEqual(200, response.status_code)
        self.assertEqual(self.first_book.name,response.context['book'].name)
        self.assertTemplateUsed('myapp/book/view_template.html')
    def test_user_cant_see_others_books(self):
        response = self.another_client.get(self.url)
        self.assertEqual(403, response.status_code)
        
    def test_unlogged_user_cant_see_private_books(self):
        response = self.unlogged_client.get(self.url)
        self.assertEqual(403, response.status_code)
"""
    Since book is public all three clients should be able to see the book
"""
 class PublicBookAccessTestCase(BaseViewTestCase):
    
    def setUp(self):
        super(PublicBookAccessTestCase, self).setUp()
        self.url = reverse('view_book',kwargs={'book_id':str(self.public_book.id)})
    def test_user_sees_book(self):
        response = self.client.get(self.url)
        self.assertEqual(200, response.status_code)
        self.assertEqual(self.public_book.name,response.context['book'].name)
        self.assertTemplateUsed('myapp/book/view_template.html')
    def test_another_user_sees_public_books(self):
        response = self.another_client.get(self.url)
        self.assertEqual(200, response.status_code)
        
    def test_unlogged_user_sees_public_books(self):
        response = self.unlogged_client.get(self.url)
        self.assertEqual(200, response.status_code)
Die Datenbank und das Testen
Django verwendet beim Testen spezielle Datenbankeinstellungen, sodass Tests die Datenbank normalerweise verwenden können, aber standardmäßig in einer leeren Datenbank ausgeführt werden. Datenbankänderungen in einem Test werden von einem anderen nicht erkannt. Zum Beispiel werden die beiden folgenden Tests bestanden:
from django.test import TestCase
from myapp.models import Thing
class MyTest(TestCase):
    def test_1(self):
        self.assertEqual(Thing.objects.count(), 0)
        Thing.objects.create()
        self.assertEqual(Thing.objects.count(), 1)
    def test_2(self):
        self.assertEqual(Thing.objects.count(), 0)
        Thing.objects.create(attr1="value")
        self.assertEqual(Thing.objects.count(), 1)
Fixtures
 Wenn Sie Datenbankobjekte für mehrere Tests verwenden möchten, erstellen Sie sie entweder in der setUp Methode des Testfalls. Wenn Sie in Ihrem Django-Projekt Fixtures definiert haben, können diese zusätzlich so eingefügt werden: 
class MyTest(TestCase):
    fixtures = ["fixture1.json", "fixture2.json"]
 Standardmäßig sucht Django in jeder App nach Fixtures im fixtures Verzeichnis. Weitere Verzeichnisse können mit der Einstellung FIXTURE_DIRS gesetzt werden: 
# myapp/settings.py
FIXTURE_DIRS = [
    os.path.join(BASE_DIR, 'path', 'to', 'directory'),
]
Angenommen, Sie haben ein Modell wie folgt erstellt:
# models.py
from django.db import models
class Person(models.Model):
    """A person defined by his/her first- and lastname."""
    firstname = models.CharField(max_length=255)
    lastname = models.CharField(max_length=255)
Dann könnten Ihre .json-Fixtures so aussehen:
# fixture1.json
[
    { "model": "myapp.person",
        "pk": 1,
        "fields": {
            "firstname": "Peter",
            "lastname": "Griffin"
        }
    },
    { "model": "myapp.person",
        "pk": 2,
        "fields": {
            "firstname": "Louis",
            "lastname": "Griffin"
        }
    },
]
Verwenden Sie die Testdatenbank erneut
 Um Ihre Testläufe zu beschleunigen, können Sie dem Verwaltungsbefehl mitteilen, die Testdatenbank erneut zu verwenden (und zu verhindern, dass sie vor jedem Testlauf erstellt und gelöscht wird). Dies kann mit dem keepdb-Flag (oder der Abkürzung -k ) wie folgt durchgeführt werden: 
# Reuse the test-database (since django version 1.8)
$ python manage.py test --keepdb
Begrenzen Sie die Anzahl der durchgeführten Tests
 Es ist möglich, die von manage.py test ausgeführten Tests manage.py test indem Sie manage.py test , welche Module vom manage.py test sollen: 
# Run only tests for the app names "app1"
$ python manage.py test app1
# If you split the tests file into a module with several tests files for an app
$ python manage.py test app1.tests.test_models
# it's possible to dig down to individual test methods.
$ python manage.py test app1.tests.test_models.MyTestCase.test_something
Wenn Sie eine Reihe von Tests durchführen möchten, können Sie ein Muster von Dateinamen übergeben. Beispielsweise möchten Sie möglicherweise nur Tests ausführen, die Ihre Modelle betreffen:
$ python manage.py test -p test_models*
Creating test database for alias 'default'...
.................................................
----------------------------------------------------------------------
Ran 115 tests in 3.869s
OK
 Schließlich ist es möglich, die Testsuite beim ersten Fehler mithilfe von --failfast . Dieses Argument ermöglicht es, den potenziellen Fehler in der Suite schnell zu ermitteln: 
$ python manage.py test app1
...F..
----------------------------------------------------------------------
Ran 6 tests in 0.977s
FAILED (failures=1)
$ python manage.py test app1 --failfast
...F
======================================================================
[Traceback of the failing test]
----------------------------------------------------------------------
Ran 4 tests in 0.372s
FAILED (failures=1)