2010-07-01 12 views
7

Je voudrais tester unitairement une vue django en ajoutant un formulaire. Le problème est que ce formulaire a un champ captcha (basé sur django-simple-captcha).Comment tester un formulaire avec un champ captcha dans django?

from django import forms 
from captcha.fields import CaptchaField 

class ContactForm(forms.forms.Form): 
    """ 
    The information needed for being able to download 
    """ 
    lastname = forms.CharField(max_length=30, label='Last name') 
    firstname = forms.CharField(max_length=30, label='First name') 
    ... 
    captcha = CaptchaField() 

Le code de test:

class ContactFormTest(TestCase): 

    def test_submitform(self): 
     """Test that the contact page""" 
     url = reverse('contact_form') 

     form_data = {} 
     form_data['firstname'] = 'Paul' 
     form_data['lastname'] = 'Macca' 
     form_data['captcha'] = '28if' 

     response = self.client.post(url, form_data, follow=True) 

Y at-il approche de test d'unité ce code et se débarrasser du captcha lors du test?

Merci à l'avance

+0

Au cas où d'autres finiraient ici comme je l'ai fait, je suis tombé sur ce post en essayant de trouver une réponse similaire pour le paquet 'django-recaptcha'; s'avère qu'ils ont aussi un réglage. Leurs documents décrivent son utilisation: https://github.com/praekelt/django-recaptcha –

Répondre

6

Voici comment je m'en suis sorti. Importez le modèle qui détient effectivement les informations Captcha:

from captcha.models import CaptchaStore 

Tout d'abord, je vérifie que la table captcha test est vide:

captcha_count = CaptchaStore.objects.count() 
self.failUnlessEqual(captcha_count, 0) 

Après chargement de la page (dans ce cas, il est une page d'inscription), vérifier qu'il ya une nouvelle instance d'objet captcha:

captcha_count = CaptchaStore.objects.count() 
self.failUnlessEqual(captcha_count, 1) 

Ensuite, je récupère les données d'instance captcha et POST avec la forme. Dans mon cas, le POST s'attend à ce que 'captcha_0' contienne le hashkey, et 'captcha_1' contienne la réponse.

captcha = CaptchaStore.objects.all()[0] 
registration_data = { # other registration data here 
        'captcha_0': captcha.hashkey, 
        'captcha_1': captcha.response } 

Vous devrez peut-être modifier un peu ce paramètre si vous commencez par les instances CaptchaStore avant d'exécuter ce test. J'espère que cela pourra aider.

+0

La façon dont je l'ai fait (avant de noter votre réponse) était d'analyser la forme non liée 'dom = PyQuery (' {}' .format (f.as_p())', récupère le hash 'hashkey = dom ('entrée [name =" captcha_0 "]'). attr ('valeur ') 'et ensuite interroger la base de données en l'utilisant.Le reste est la plupart du temps le même.espérons qu'il espère quelqu'un. – alfetopito

1

Une solution est d'avoir un cadre « test » qui est vrai ou faux. Et puis juste

if not testing: 
    # do captcha stuff here 

C'est simple et facile, et un basculement facile.

+0

Cela fonctionne mais les paramètres. UNIT_TEST = True doivent être définis avant d'importer le formulaire dans le module de test.Cela a été la cause de mon erreur – luc

+1

vous pouvez définir des tests dans le fichier de paramètres aussi: 'si" test "dans sys.argv: TESTING = True' – leech

0

Avec une approche similaire que Jim McGaw, mais en utilisant BeautifulSoup:

from captcha.models import CaptchaStore 
from BeautifulSoup import BeautifulSoup 

data = {...} #The data to post 
soup = BeautifulSoup(self.client.get(url).content) 
for field_name in ('captcha_0', ...): #get fields from the form 
    data[field_name] = soup.find('input',{'name':field_name})['value'] 
captcha = CaptchaStore.objects.get(hashkey=data['captcha_0']) 
data['captcha_1'] = captcha.challenge 
response = self.client.post(url, data=data) 

# check the results 
... 
10

je sais que c'est un ancien poste, mais django-simple captcha a maintenant un CAPTCHA_TEST_MODE de réglage qui rend la réussite captcha si vous fournissez la valeur 'PASSÉE'. Il vous suffit de vous assurer d'envoyer quelque chose pour les deux champs d'entrée captcha:

post_data['captcha_0'] = 'dummy-value' 
post_data['captcha_1'] = 'PASSED' 
self.client.post(url, data=post_data) 

Le réglage CAPTCHA_TEST_MODE ne doit être utilisé au cours des essais. Mon settings.py:

if 'test' in sys.argv: 
    CAPTCHA_TEST_MODE = True 
1

Une autre solution qui est similaire à la réponse de Jim McGaw, mais supprimer la nécessité de table CaptchaStore de table vide.

captcha = CaptchaStore.objects.get(hashkey=CaptchaStore.generate_key()) 

registration_data = { # other registration data here 
       'captcha_0': captcha.hashkey, 
       'captcha_1': captcha.response } 

Ceci générera un nouveau captcha juste pour ce test.