验证现在我们已经完成了视图的测试,让我们添加对表单的验证。但首先我们要写一个测试,惊喜吧! 在“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个测试会通过的:
新增联系人由于我们增加了验证,我们想测试一下在管理员区域这个验证功能是可以工作的,所以更新“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个测试都通过了。耶!现在可以提交代码了。
| ![Django 1.6 的测试驱动开发-LMLPHP Django 1.6 的测试驱动开发-LMLPHP]() 翻译的不错哦! |