Test——很重要可是沒有被重視起來的一個環節,至少是我本身,其實本身以前在作java web的時候就去嘗試過怎麼作REST接口的測試,一直沒有找到一種合適方式,並且由於時間緊沒有進一步深究,可是形成的後果每次作了修改以後都測試不充分,引發新的問題,因此此次對於python正好看看Django的單元測試。java
用的是單獨的數據庫,數據庫是乾淨的(暫未有數據庫,test全部操做都是從零開始),不會對正式的數據庫形成影響python
到如今咱們主要的業務邏輯代碼在model和view裏面,因此咱們的測試也主要是針對model和view。在Django中咱們的測試代碼寫在tests.py裏面,這裏咱們先在models.py的Question類裏面添加一個was_published_recently方法:web
def was_published_recently(self): now = timezone.now() return self.publ_date >= now - datetime.timedelta(days=1)
接下來針對這個方法寫單元測試數據庫
class QuestionMethodTest(TestCase): def test_was_pblished_recently_with_future_question(self): time = timezone.now() + datetime.timedelta(days=30) future_question = Question(publ_date=time) self.assertEqual(future_question.was_published_recently(), False) def test_was_pblished_recently_with_old_question(self): time = timezone.now() - datetime.timedelta(days=30) future_question = Question(publ_date=time) self.assertEqual(future_question.was_published_recently(), False) def test_was_pblished_recently_with_recently_question(self): time = timezone.now() - datetime.timedelta(hours=1) future_question = Question(publ_date=time) self.assertEqual(future_question.was_published_recently(), True)
這裏先寫了三個測試用例,分別測試django
咱們再看看Django爲咱們的單元測試提供了怎樣的環境。服務器
咱們在mysite目錄裏面運行測試app
python manage.py test polls
能夠看到輸出ide
Creating test database for alias 'default'... F.. ====================================================================== FAIL: test_was_pblished_recently_with_future_question (polls.tests.QuestionMethodTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/root/django/mysite/polls/tests.py", line 17, in test_was_pblished_recently_with_future_question self.assertEqual(future_question.was_published_recently(), False) AssertionError: True != False ---------------------------------------------------------------------- Ran 3 tests in 0.001s FAILED (failures=1) Destroying test database for alias 'default'...
能夠看到總共三個測試,失敗1個,查看失敗信息發現返回的是true,和咱們預期的不符,說明咱們的was_published_recently函數的邏輯不正確,全部時間大於當前時間的應該不被查詢出來,咱們修正以下函數
def was_published_recently(self): now = timezone.now() return now >= self.publ_date >= now - datetime.timedelta(days=1)
再次運行就會發現三個均成功,結果是OKpost
Creating test database for alias 'default'... ... ---------------------------------------------------------------------- Ran 3 tests in 0.001s OK Destroying test database for alias 'default'...
view層會調用model層的代碼實現業務邏輯,咱們經過上面model的測試保證了model層的正確性,接下來能夠借用django提供的環境測試咱們的業務邏輯是否正確,編輯tests.py
from django.test import TestCase import datetime from django.utils import timezone from polls.models import Question from django.core.urlresolvers import reverse # Create your tests here. def create_question(question_text, days): time = timezone.now() + datetime.timedelta(days=days) return Question.objects.create(question_text=question_text, publ_date=time) class QuestionMethodTest(TestCase): def test_was_pblished_recently_with_future_question(self): time = timezone.now() + datetime.timedelta(days=30) future_question = Question(publ_date=time) self.assertEqual(future_question.was_published_recently(), False) def test_was_pblished_recently_with_old_question(self): time = timezone.now() - datetime.timedelta(days=30) future_question = Question(publ_date=time) self.assertEqual(future_question.was_published_recently(), False) def test_was_pblished_recently_with_recently_question(self): time = timezone.now() - datetime.timedelta(hours=1) future_question = Question(publ_date=time) self.assertEqual(future_question.was_published_recently(), True) class QuestionViewTest(TestCase): def test_index_view_with_no_questions(self): response = self.client.get(reverse('polls:index')) self.assertEqual(response.status_code, 200) self.assertContains(response, 'No polls are available') self.assertQuerysetEqual(response.context['latest_question_list'], []) def test_index_view_with_a_past_question(self): create_question('Past question.', -30) response = self.client.get(reverse('polls:index')) self.assertQuerysetEqual(response.context['latest_question_list'], ['<Question: Past question.>']) def test_index_view_with_a_future_question(self): create_question('Future question.', 30) response = self.client.get(reverse('polls:index')) self.assertContains(response, 'No polls are available') self.assertQuerysetEqual(response.context['latest_question_list'], []) def test_index_view_with_future_question_and_past_question(self): create_question('Past question.', -30) create_question('Future question.', 30) response = self.client.get(reverse('polls:index')) self.assertQuerysetEqual(response.context['latest_question_list'], ['<Question: Past question.>']) def test_index_view_with_two_past_question(self): create_question('Past question 1.', -30) create_question('Past question 2.', -5) response = self.client.get(reverse('polls:index')) self.assertQuerysetEqual(response.context['latest_question_list'], ['<Question: Past question 2.>', '<Question: Past question 1.>'])
django爲咱們的view層測試提供了更多的幫助
完整代碼