2010-07-01 59 views
7

我想单元测试一个django视图通过提交表单。问题是这个表单有一个验证码字段(基于django-simple-captcha)。如何使用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() 

测试代码:

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) 

有什么方法来单元测试代码并进行测试时摆脱Captcha验证码?

在此先感谢

+0

如果其他人最终在这里像我一样,我偶然发现这篇文章试图找到类似的答案'django-recaptcha'包;原来他们也有一个设置。他们的文档描述了它的使用:https://github.com/praekelt/django-recaptcha – 2016-03-23 14:43:13

回答

6

这是我解决它的方法。导入实际持有验证码信息模式:

from captcha.models import CaptchaStore 

首先,我检查测试验证码表是空的:

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

加载页面后(在这种情况下,这是一个注册页面)检查是否有新的验证码对象实例:

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

然后,我检索到带有表单的验证码实例数据和POST。在我的例子中,POST期望'captcha_0'包含hashkey,'captcha_1'包含响应。

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

如果您在运行此测试之前以CaptchaStore实例开始,则可能需要稍微调整一下。希望有所帮助。

+0

我做的方式(在注意到你的答案之前)是解析未绑定的表单HTML ''dom = PyQuery''' {}'.format(f.as_p())',从那里得到散列hashkey = dom('input [name =“captcha_0”]')。attr('value ')'然后使用它查询数据库,其余的大部分都是一样的,希望它能寄予希望。 – alfetopito 2013-07-02 16:20:26

1

一种解决方案是有一个设置为“测试”,也就是真或假。然后只是

if not testing: 
    # do captcha stuff here 

它简单易用,而且很容易切换。

+0

它可以工作,但是在导入测试模块中的表单之前必须设置settings.UNIT_TEST = True。这是我错误的原因 – luc 2010-07-01 16:01:06

+1

你也可以在设置文件中设置测试:'if“test”in sys.argv:TESTING = True' – leech 2012-10-30 19:26:33

0

用类似的方法比吉姆McGaw但使用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

我知道这是旧的文章,但现在的Django简单的验证码有一个设置CAPTCHA_TEST_MODE这使得如果你提供的验证码成功值“通过”。你只需要确保送东西两个验证码输入字段:

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

的CAPTCHA_TEST_MODE设置应该只在测试中使用。我的settings.py:

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

另一个类似于Jim McGaw的答案的解决方案,但删除了对空表CaptchaStore表的需求。

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

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

这将为该测试生成新的验证码。