第12章 输入验证和测试的组织方式
12.1 针对验证的功能测试:避免提交空待办事项
functional_tests/tests.py
def test_can_not_add_empty_list_items(self):
# 乔伊访问首页,不小心提交一个空待办事项
# 输入框中没输入内容,她就按下了回车
#首页刷新了,显示了一个错误信息
#提示待办事项不能为空
#她输入了一些文字,然后再次提交,这次没有问题了
#她有点儿调皮,又提交了一个空待办事项
#在清单页她看到了一个类似的错误消息
#输入文字之后就没问题了
self.fail('wirte me!')
12.1.1 跳过测试
from unittest import skip
[...] @skip def can_not_add_empty_list_items(self):
python manage.py test functional_tests
ps:跳过测试很危,在提交前要删除掉@skip
12.1.2 分拆功能测试
把每个测试方法改为单独的类
functional_tests/tests.py-->base.py
from django.contrib.staticfiles.testing import StaticLiveServerTestCase # 增加
from selenium import webdriver
import time
from selenium.common.exceptions import WebDriverException
import os
MAX_WAIT = 10
class FunctionalTest(StaticLiveServerTestCase):
def setUp(self): # 测试执行前
self.browser = webdriver.Firefox()
staging_server = os.environ.get('STAGING_SERVER')
if staging_server:
self.live_server_url = 'http://' + staging_server
def tearDown(self): # 测试方法执行后
self.browser.quit()
def wait_for_row_in_list_table(self, row_text):
start_time = time.time()
while True:
try:
table = self.browser.find_element_by_id('id_list_table')
rows = table.find_elements_by_tag_name('tr')
self.assertIn(row_text, [row.text for row in rows])
return
except (AssertionError, WebDriverException) as e:
if time.time() - start_time > MAX_WAIT:
raise e
time.sleep(0.5)
functional_tests/test_simple_list_creation.py
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from .base import FunctionalTest
class NewVisitorTest(FunctionalTest):
def test_can_start_a_list_for_one_user(self): # 测试方法
[...]
def test_multiple_users_can_start_lists_at_different_urls(self):
[...]
functional_tests/test_list_item_validation.py
from .base import FunctionalTest
class ItemValidationTest(FunctionalTest):
[...]
functional_tests/test_layout_and_stying.py
from .base import FunctionalTest
from selenium.webdriver.common.keys import Keys
class LayoutAndStylingTest(FunctionalTest):
def test_layout_and_styling(self):
[...]
12.1.3 运行单个测试
python manage.py test functional_tests.test_simple_list_creation
python manage.py test functional_tests.test_layout_and_stying
python manage.py test functional_tests.test_list_item_validation
git commit -am 'Moved Fts into their own individual files'
12.2 功能测试新工具:通用显式等待辅助方式
functional_tests/base.py
def wait_for(self, fn):
start_time = time.time()
while True:
try:
return fn()
except (AssertionError, WebDriverException) as e:
if time.time() - start_time > MAX_WAIT:
raise e
time.sleep(0.5)
functional_tests/test_list_item_validation.py
from .base import FunctionalTest
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
import time
from selenium.common.exceptions import WebDriverException
MAX_WAIT = 10
class ItemValidationTest(FunctionalTest):
def test_can_not_add_empty_list_items(self):
# 乔伊访问首页,不小心提交一个空待办事项
# 输入框中没输入内容,她就按下了回车
self.browser.get(self.live_server_url)
self.browser.find_element_by_id('id_new_item').send_keys(Keys.ENTER)
# 首页刷新了,显示了一个错误信息
# 提示待办事项不能为空
self.wait_for(lambda: self.assertEqual(
self.browser.find_element_by_css_selector('.has-error').text,
"You can't have an empty list item"
))
# 她输入了一些文字,然后再次提交,这次没有问题了
self.fail('Finish this test!')
# 她有点儿调皮,又提交了一个空待办事项
# 在清单页她看到了一个类似的错误消息
# 输入文字之后就没问题了
selenium.common.exceptions.NoSuchElementException: Message: Unable to locate element: .has-error
12.3 补完功能测试
functional_tests/test_list_item_validation.py
def test_can_not_add_empty_list_items(self):
# 乔伊访问首页,不小心提交一个空待办事项
# 输入框中没输入内容,她就按下了回车
self.browser.get(self.live_server_url)
self.browser.find_element_by_id('id_new_item').send_keys(Keys.ENTER)
# 首页刷新了,显示了一个错误信息
# 提示待办事项不能为空
self.wait_for(lambda: self.assertEqual(
self.browser.find_element_by_css_selector('.has-error').text,
"You can't have an empty list item"
))
# 她输入了一些文字,然后再次提交,这次没有问题了
self.browser.find_element_by_id('id_new_item').send_keys('Buy milk')
self.browser.find_element_by_id('id_new_item').send_keys(Keys.ENTER)
self.wait_for_row_in_list_table('1: Buy milk')
# 她有点儿调皮,又提交了一个空待办事项
self.browser.find_element_by_id('id_new_item').send_keys(Keys.ENTER)
# 在清单页她看到了一个类似的错误消息
self.wait_for(lambda: self.assertEqual(
self.browser.find_element_by_css_selector('.has-error').text,
"You can't have an empty list item"
))
# 输入文字之后就没问题了
self.browser.find_element_by_id('id_new_item').send_keys('Make tea')
self.browser.find_element_by_id('id_new_item').send_keys(Keys.ENTER)
self.wait_for_row_in_list_table('1: Buy milk')
self.wait_for_row_in_list_table('1: Make tea')
12.4 重构单元测试。分拆成多个文件
lists/tests/test_models.py
from django.test import TestCase from lists.models import Item, List class ListAndItemModelTest(TestCase):
lists/tests/test_views.py
#!/usr/bin/python3
# -*- coding: utf-8 -*-
# @Author : Marvin King
# Date : 2019-02-22
from django.test import TestCase
from lists.models import Item, List
[...]
class HomePageTest(TestCase):
[...]
class ListViewTest(TestCase):
[...]
class NewListTest(TestCase):
[...]
python manage.py test lists
Ran 9 tests in 0.037s
OK
git commit -m 'Split out unit tests into ewo files'