验证
现在我们已经完成了视图的测试,让我们添加对表单的验证。但首先我们要写一个测试,惊喜吧!
-
在“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个测试都通过了。耶!现在可以提交代码了。
|
顶 翻译的不错哦!
|