2013-03-25 7 views
16

Ich bin ein relativer Django-Anfänger und habe gerade angefangen, ein paar Tests für meine Projekte durchzuführen. Ich möchte einen Funktionstest mit Selen erstellen, der sich auf der Django Admin-Site anmeldet.Wie können Sie einen Admin-Benutzer mit Factory_Boy erstellen?

Ich folgte zuerst diesem Tutorial und verwendete Fixtures und dumpdata, um die Admin-Account-Informationen für die Test-App verfügbar zu machen (die eine neue Datenbank erstellt). Das funktioniert gut.

Ich wollte dann sehen, ob ich das gleiche mit factory-boy tun kann, um die Fixtures zu ersetzen. Factory Boy arbeitet, indem er das notwendige Objekt innerhalb der Datei tests.py instanziiert, die mir sauberer erscheint. Irgendwie kann ich nicht bekommen dies funktioniert und die Factory_boy Dokumentation ist nicht allzu hilfreich ...

Hier ist meine tests.py

from django.test import LiveServerTestCase 
from django.contrib.auth.models import User 
from selenium import webdriver 
from selenium.webdriver.common.keys import Keys 
import factory 

class UserFactory(factory.Factory): 
    FACTORY_FOR = User 

    username = 'jeff' 
    password = 'pass' 
    is_superuser = True 

class AdminTest(LiveServerTestCase): 

    def setUp(self): 
     self.browser = webdriver.Firefox() 

    def tearDown(self): 
     self.browser.quit() 

    def test_if_admin_login_is_possible(self): 
     jeff = UserFactory.create() 

     # Jeff opens the browser and goes to the admin page 
     self.browser = webdriver.Firefox() 
     self.browser.get(self.live_server_url + '/admin/') 

     # Jeff sees the familiar 'Django Administration' heading 
     body = self.browser.find_element_by_tag_name('body') 
     self.assertIn('Django administration', body.text) 

     # Jeff types in his username and password and hits return 
     username_field = self.browser.find_element_by_name('username') 
     username_field.send_keys(jeff.username) 
     password_field = self.browser.find_element_by_name('password') 
     password_field.send_keys(jeff.password) 
     password_field.send_keys(Keys.RETURN) 

     # Jeff finds himself on the 'Site Administration' page 
     body = self.browser.find_element_by_tag_name('body') 
     self.assertIn('Site administration', body.text) 

     self.fail('Fail...') 

Dies als einzuloggen nicht irgendwie funktioniert es nicht schaffen gültiges Administratorkonto Wie kann ich das mit Factory-Boy machen? Ist es möglich oder muss ich dafür Geräte benutzen?

(In diesem Post einige Leute vorgeschlagen, Fixtures sind notwendig, aber Fabrik Junge kam nicht: How to create admin user in django tests.py. Ich habe auch versucht, die Lösung unten in der gleichen Antwort vorgeschlagen: https://stackoverflow.com/a/3495219/1539688. Es hat nicht funktioniert für mich .. .)

Antwort

6

Ich gehe davon aus, dass Sie an der Anleitung arbeiten, weil das ist, wo ich auch stecken geblieben bin. Du hast das wahrscheinlich schon herausgefunden, aber für die nächste Person, hier ist der Code, der für mich funktioniert hat, war der Trick das Hinzufügen der _prepare Methode um sicherzustellen, dass das Passwort verschlüsselt ist und alle Flags auf true setzen (Dies wurde mit Django 1.5 gemacht. 1, wenn Sie eine frühere Version verwenden, die Modellbenutzerimporte ändern)

from django.test import LiveServerTestCase 
from selenium import webdriver 
from selenium.webdriver.common.keys import Keys 

import factory 
from django.contrib.auth import get_user_model 
User = get_user_model() 


class UserFactory(factory.DjangoModelFactory): 
    FACTORY_FOR = User 

    email = '[email protected]' 
    username = 'admin' 
    password = 'adm1n' 

    is_superuser = True 
    is_staff = True 
    is_active = True 

    @classmethod 
    def _prepare(cls, create, **kwargs): 
     password = kwargs.pop('password', None) 
     user = super(UserFactory, cls)._prepare(create, **kwargs) 
     if password: 
      user.set_password(password) 
      if create: 
       user.save() 
     return user 

class PollsTest(LiveServerTestCase): 

    def setUp(self): 
     self.browser = webdriver.Firefox() 
     self.browser.implicitly_wait(3) 
     self.user = UserFactory.create() 


    def tearDown(self): 
     self.browser.quit() 

    def test_can_create_new_poll_via_admin_site(self): 
     self.browser.get(self.live_server_url+'/admin/') 

     body = self.browser.find_element_by_tag_name('body') 
     self.assertIn('Django administration', body.text) 

     username_field = self.browser.find_element_by_name('username') 
     username_field.send_keys(self.user.username) 

     password_field = self.browser.find_element_by_name('password') 
     password_field.send_keys('adm1n') 
     password_field.send_keys(Keys.ENTER) 

     body = self.browser.find_element_by_tag_name('body') 
     self.assertIn('Site administration', body.text) 

     polls_links = self.browser.find_element_by_link_text('Polls') 
     self.assertEqual(len(polls_links), 2) 


     self.fail('Finish the test!') 
28

wenn Sie eine Unterklasse factory.DjangoModelFactory sollte das Benutzerobjekt für Sie speichern. Siehe den Hinweis unter PostGenerationMethodCall. Dann müssen Sie nur Folgendes tun:

class UserFactory(factory.DjangoModelFactory): 
    FACTORY_FOR = User 

    email = '[email protected]' 
    username = 'admin' 
    password = factory.PostGenerationMethodCall('set_password', 'adm1n') 

    is_superuser = True 
    is_staff = True 
    is_active = True 
+0

Wie können Sie 'User Groups' einstellen? – Shubham

+0

Für diejenigen, die diesen Beitrag jetzt finden, ignoriert 2.5.0+ jetzt die Attribute "FACTORY_ *" zugunsten der Definition von Attributen in einer inneren Meta-Klasse: http://factoryboy.readthedocs.io/en/latest/changelog.html#upgrading – RevolutionTech

0

Hier ist, wie ich es mit Factory Boy 2.7.0 und Django 1.8.4 getan haben. Im Folgenden sind zwei Factorys aufgeführt, eines für einen Basisbenutzer und eines für den Admin-Benutzer, das von Basic nur die erforderlichen Felder hinzufügt.

class UserFactory(DjangoModelFactory): 

    class Meta: 
     model = User 
     django_get_or_create = ('username', 'email', 'password') 

    username = 'basic' 
    email = '[email protected]_admin.com' 
    password = 'basicpassword' 


class AdminFactory(UserFactory): 
    username = 'admin' 
    is_superuser = True 
0

Ich hatte ein ähnliches Problem, wenn ein Benutzer erstellt wurde. Django-Hash-Passwörter, wenn ein Benutzer erstellt wird und Sie das Passwort mit DjangoFactory ohne Hash speichern. Bei der Anmeldung überprüft Django das Passwort, das Sie mit dem gespeicherten Hash-Wert gesendet haben. Bei diesem Schritt schlägt die Überprüfung fehl, da Sie das nicht gehashte Passwort mit einem nicht gehashten Passwort prüfen. Hier ist ein Beispiel, wie ich dies in meinem Code festgelegt:

from django.contrib.auth.hashers import make_password 
from factory import DjangoModelFactory, Sequence 



class UserFactory(DjangoModelFactory): 
    class Meta: 
     model = User 
     django_get_or_create = ('username', 'password') 

    username = Sequence(lambda n: 'somename%s' % n) 
    password = Sequence(lambda p: 'mysuperpass%s' % p) 

    @classmethod 
    def _create(cls, model_class, *args, **kwargs): 
     """Override the default ``_create`` with our custom call.""" 
     kwargs['password'] = make_password(kwargs['password']) 
     return super(UserFactory, cls)._create(model_class, *args, **kwargs) 

ich Passwort nehmen, die generiert wurde Sequenz mit und Hash es Django make_password Methode. In Tests können Sie eine Variable mit nicht gehashten Werten erstellen und einen Benutzer mit dieser Variablen erstellen. Beispiel:

password = 'test123' 
user = UserFactory(password=my_password)