验证
现在我们已经完成了视图的测试,让我们添加对表单的验证。但首先我们要写一个测试,惊喜吧!
-
在“tests”目录下新增一个叫“test_validator.py”的文件并增加以下代码:
01 |
from django.core.exceptions import ValidationError |
02 |
from django.test import TestCase |
03 |
from user_contacts.validators import validate_number, validate_string class ValidatorTest(TestCase): |
04 |
def test_string_is_invalid_if_contains_numbers_or_special_characters(self): |
05 |
with self.assertRaises(ValidationError): |
06 |
validate_string('@test') |
07 |
validate_string('tester#') |
08 |
def test_number_is_invalid_if_contains_any_character_except_digits(self): |
09 |
with self.assertRaises(ValidationError): |
10 |
validate_number('123ABC') |
11 |
validate_number('75431#') |
-
在运行测试之前,你猜猜会有什么情况发生?提示:请密切注意代码上面导入进来的包。你会有以下错误信息,因为我们没有“validators.py”文件:
1 |
ImportError: cannot import name validate_string |
换言之,我们测试所需的逻辑验证文件还不存在。
-
在“user_contacts”目录下新增一个叫“validators.py”的文件:
1 |
import refrom django.core.exceptions import ValidationErrordef validate_string(string): |
2 |
if re.search('^[A-Za-z]+$', string) is None: |
3 |
raise ValidationError('Invalid')def validate_number(value): |
4 |
if re.search('^[0-9]+$', value) is None: |
5 |
raise ValidationError('Invalid') |
-
再次运行测试。5个测试会通过的:
1 |
Ran 5 tests in 0.019sOK |
新增联系人
-
由于我们增加了验证,我们想测试一下在管理员区域这个验证功能是可以工作的,所以更新“test_views.py”:
01 |
from django.template.loader import render_to_stringfrom django.test import TestCase, Clientfrom user_contacts.models import Person, Phonefrom user_contacts.views import *class ViewTest(TestCase): |
03 |
self.client_stub = Client() |
04 |
self.person = Person(first_name = 'TestFirst',last_name = 'TestLast') |
06 |
self.phone = Phone(person = self.person,number = '7778889999') |
08 |
def test_view_home_route(self): |
09 |
response = self.client_stub.get('/') |
10 |
self.assertEquals(response.status_code, 200) |
11 |
def test_view_contacts_route(self): |
12 |
response = self.client_stub.get('/all/') |
13 |
self.assertEquals(response.status_code, 200) |
14 |
def test_add_contact_route(self): |
15 |
response = self.client_stub.get('/add/') |
16 |
self.assertEqual(response.status_code, 200) |
17 |
def test_create_contact_successful_route(self): |
18 |
response = self.client_stub.post('/create',data = {'first_name' : 'testFirst', 'last_name':'tester', 'email':'test@tester.com', 'address':'1234 nowhere', 'city':'far away', 'state':'CO', 'country':'USA', 'number':'987654321'}) |
19 |
self.assertEqual(response.status_code, 302) |
20 |
def test_create_contact_unsuccessful_route(self): |
21 |
response = self.client_stub.post('/create',data = {'first_name' : 'tester_first_n@me', 'last_name':'test', 'email':'tester@test.com', 'address':'5678 everywhere', 'city':'far from here', 'state':'CA', 'country':'USA', 'number':'987654321'}) |
22 |
self.assertEqual(response.status_code, 200) |
两个测试会失败。
我们要怎么做才能让测试通过呢?首先我们要为添加数据到数据库增加一个视图功能来查看。
-
添加路径:
1 |
url(r'^create$', create), |
-
更新“views.py”:
2 |
form = ContactForm(request.POST)if form.is_valid(): |
4 |
return HttpResponseRedirect('all/')return render(request, 'add.html', {'person_form' : form}, context_instance = RequestContext(request)) |
-
再次测试:
1 |
$ python manage.py test user_contacts |
这次只有一个测试会失败 - AssertionError: 302 != 200 - 因为我们尝试添加一些不通过验证的数据但添加成功了。换言之,我们需要更新“models.py”文件中的表单都要把验证考虑进去。
-
更新“models.py”:
01 |
from django.db import modelsfrom user_contacts.validators import validate_string, validate_numberclass Person(models.Model): |
02 |
first_name = models.CharField(max_length = 30, validators = [validate_string]) |
03 |
last_name = models.CharField(max_length = 30, validators = [validate_string]) |
04 |
email = models.EmailField(null = True, blank = True) |
05 |
address = models.TextField(null = True, blank = True) |
06 |
city = models.CharField(max_length = 15, null = True,blank = True) |
07 |
state = models.CharField(max_length = 15, null = True, blank = True, validators = [validate_string]) |
08 |
country = models.CharField(max_length = 15, null = True, blank = True) |
10 |
def __unicode__(self): |
11 |
return self.last_name +", "+ self.first_nameclass Phone(models.Model): |
12 |
person = models.ForeignKey('Person') |
13 |
number = models.CharField(max_length=10, validators = [validate_number]) |
15 |
def __unicode__(self): |
-
删除当前的数据库,“db.sqlite3”,重新同步数据库:
1 |
$ python manage.py syncdb |
再次设置一个管理员账户。
-
新增验证,更新new_contact_form.py:
01 |
import refrom django import formsfrom django.core.exceptions import ValidationErrorfrom user_contacts.models import Person, Phonefrom user_contacts.validators import validate_string, validate_numberclass ContactForm(forms.Form): |
02 |
first_name = forms.CharField(max_length=30, validators = [validate_string]) |
03 |
last_name = forms.CharField(max_length=30, validators = [validate_string]) |
04 |
email = forms.EmailField(required=False) |
05 |
address = forms.CharField(widget=forms.Textarea, required=False) |
06 |
city = forms.CharField(required=False) |
07 |
state = forms.CharField(required=False, validators = [validate_string]) |
08 |
country = forms.CharField(required=False) |
09 |
number = forms.CharField(max_length=10, validators = [validate_number]) |
12 |
data = self.cleaned_data |
13 |
person = Person.objects.create(first_name=data.get('first_name'), last_name=data.get('last_name'), |
14 |
email=data.get('email'), address=data.get('address'), city=data.get('city'), state=data.get('state'), |
15 |
country=data.get('country')) |
16 |
phone = Phone.objects.create(person=person, number=data.get('number')) |
-
再次运行测试,7个测试会通过的。
-
现在,先脱离开TDD一会儿。我想在客户端添加一个额外的测试验证。所以添加test_contact_form.py:
1 |
from django.test import TestCasefrom user_contacts.models import Personfrom user_contacts.new_contact_form import ContactFormclass TestContactForm(TestCase): |
2 |
def test_if_valid_contact_is_saved(self): |
3 |
form = ContactForm({'first_name':'test', 'last_name':'test','number':'9999900000'}) |
5 |
self.assertEqual(contact.person.first_name, 'test') |
6 |
def test_if_invalid_contact_is_not_saved(self): |
7 |
form = ContactForm({'first_name':'tes&t', 'last_name':'test','number':'9999900000'}) |
9 |
self.assertEqual(contact, None) |
-
运行测试,所有9个测试都通过了。耶!现在可以提交代码了。
|
顶 翻译的不错哦!
|