亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > Python > 正文

對Python的Django框架中的項目進行單元測試的方法

2020-01-04 17:33:23
字體:
來源:轉載
供稿:網友
這篇文章主要介紹了對Python的Django框架中的項目進行單元測試的方法,使用Django中的tests.py模塊可以輕松地檢測出一些常見錯誤,需要的朋友可以參考下
 

 Python中的單元測試

我們先來回顧一下Python中的單元測試方法。
下面是一個 Python的單元測試簡單的例子:

假如我們開發一個除法的功能,有的同學可能覺得很簡單,代碼是這樣的:

def division_funtion(x, y):  return x / y

但是這樣寫究竟對還是不對呢,有些同學可以在代碼下面這樣測試:

def division_funtion(x, y):  return x / y  if __name__ == '__main__':  print division_funtion(2, 1)  print division_funtion(2, 4)  print division_funtion(8, 3)

但是這樣運行后得到的結果,自己每次都得算一下去核對一遍,很不方便,Python中有 unittest 模塊,可以很方便地進行測試,詳情可以文章最后的鏈接,看官網文檔的詳細介紹。

下面是一個簡單的示例:

import unittest  def division_funtion(x, y):  return x / y  class TestDivision(unittest.TestCase):  def test_int(self):    self.assertEqual(division_funtion(9, 3), 3)   def test_int2(self):    self.assertEqual(division_funtion(9, 4), 2.25)   def test_float(self):    self.assertEqual(division_funtion(4.2, 3), 1.4)  if __name__ == '__main__':  unittest.main()


我簡單地寫了三個測試示例(不一定全面,只是示范,比如沒有考慮除數是0的情況),運行后發現:

F.F======================================================================FAIL: test_float (__main__.TestDivision)----------------------------------------------------------------------Traceback (most recent call last): File "/Users/tu/YunPan/mydivision.py", line 16, in test_float  self.assertEqual(division_funtion(4.2, 3), 1.4)AssertionError: 1.4000000000000001 != 1.4 ======================================================================FAIL: test_int2 (__main__.TestDivision)----------------------------------------------------------------------Traceback (most recent call last): File "/Users/tu/YunPan/1.py", line 13, in test_int2  self.assertEqual(division_funtion(9, 4), 2.25)AssertionError: 2 != 2.25 ----------------------------------------------------------------------Ran 3 tests in 0.001s FAILED (failures=2)

汗!發現了沒,竟然兩個都失敗了,測試發現:

4.2除以3 等于 1.4000000000000001 不等于期望值 1.4

9除以4等于2,不等于期望的 2.25

下面我們就是要修復這些問題,再次運行測試,直到運行不報錯為止。

譬如根據實際情況,假設我們只需要保留到小數點后6位,可以這樣改:

def division_funtion(x, y):  return round(float(x) / y, 6)

再次運行就不報錯了:

...----------------------------------------------------------------------Ran 3 tests in 0.000s

 
OK

Django中的單元測試

盡早進行單元測試(UnitTest)是比較好的做法,極端的情況甚至強調“測試先行”。現在我們已經有了第一個model類和Form類,是時候開始寫測試代碼了。

Django支持python的單元測試(unit test)和文本測試(doc test),我們這里主要討論單元測試的方式。這里不對單元測試的理論做過多的闡述,假設你已經熟悉了下列概念:test suite, test case, test/test action,  test data, assert等等。

在單元測試方面,Django繼承python的unittest.TestCase實現了自己的django.test.TestCase,編寫測試用 例通常從這里開始。測試代碼通常位于app的tests.py文件中(也可以在models.py中編寫,但是我不建議這樣做)。在Django生成的 depotapp中,已經包含了這個文件,并且其中包含了一個測試用例的樣例:

depot/depotapp/tests.py

from django.test import TestCaseclass SimpleTest(TestCase):def test_basic_addition(self):"""Tests that 1 + 1 always equals 2."""self.assertEqual(1 + 1, 2)

你可以有幾種方式運行單元測試:

  • python manage.py test:執行所有的測試用例
  • python manage.py test app_name, 執行該app的所有測試用例
  • python manage.py test app_name.case_name: 執行指定的測試用例

用第三種方式執行上面提供的樣例,結果如下:

$ python manage.py test depotapp.SimpleTest
Creating test database for alias 'default'....----------------------------------------------------------------------Ran 1 test in 0.012sOKDestroying test database for alias 'default'...

你可能會主要到,輸出信息中包括了創建和刪除數據庫的操作。為了避免測試數據造成的影響,測試過程會使用一個單獨的數據庫,關于如何指定測試數據庫 的細節,請查閱Django文檔。在我們的例子中,由于使用sqlite數據庫,Django將默認采用內存數據庫來進行測試。

下面就讓我們來編寫測試用例。在《Agile Web Development with Rails 4th》中,7.2節,最終實現的ProductTest代碼如下:

class ProductTest < ActiveSupport::TestCasetest "product attributes must not be empty"doproduct = Product.newassert product.invalid?assert product.errors[:title].any?assert product.errors[:description].any?assert product.errors[:price].any?assert product.errors[:image_url].any?endtest "product price must be positive"doproduct = Product.new(:title => "My Book Title",:description => "yyy",:image_url => "zzz.jpg")product.price = -1assert product.invalid?assert_equal "must be greater than or equal to 0.01",product.errors[:price].join('; ')product.price = 0assert product.invalid?assert_equal "must be greater than or equal to 0.01",product.errors[:price].join('; ')product.price = 1assert product.valid?enddef new_product(image_url)Product.new(:title => "My Book Title",:description => "yyy",:price => 1,:image_url => image_url)endtest "image url"dook = %w{ fred.gif fred.jpg fred.png FRED.JPG FRED.Jpghttp://a.b.c/x/y/z/fred.gif }bad = %w{ fred.doc fred.gif/more fred.gif.more }ok.eachdo |name|assert new_product(name).valid?, "#{name} shouldn't be invalid"endbad.eachdo |name|assert new_product(name).invalid?, "#{name} shouldn't be valid"endendtest "product is not valid without a unique title"doproduct = Product.new(:title => products(:ruby).title,:description => "yyy",:price => 1,:image_url => "fred.gif")assert !product.saveassert_equal "has already been taken", product.errors[:title].join('; ')endtest "product is not valid without a unique title - i18n"doproduct = Product.new(:title => products(:ruby).title,:description => "yyy",:price => 1,:image_url => "fred.gif")assert !product.saveassert_equal I18n.translate('activerecord.errors.messages.taken'),product.errors[:title].join('; ')endend

對Product測試的內容包括:

1.title,description,price,image_url不能為空;

2. price必須大于零;

3. image_url必須以jpg,png,jpg結尾,并且對大小寫不敏感;

4. titile必須唯一;

讓我們在Django中進行這些測試。由于ProductForm包含了模型校驗和表單校驗規則,使用ProductForm可以很容易的實現上述測試:

depot/depotapp/tests.py

#/usr/bin/python#coding: utf8"""This file demonstrates writing tests using the unittest module. These will passwhen you run "manage.py test".Replace this with more appropriate tests for your application."""from django.test import TestCasefrom forms import ProductFormclass SimpleTest(TestCase):def test_basic_addition(self):"""Tests that 1 + 1 always equals 2."""self.assertEqual(1 + 1, 2)class ProductTest(TestCase):def setUp(self):self.product = {'title':'My Book Title','description':'yyy','image_url':'http://google.com/logo.png','price':1}f = ProductForm(self.product)f.save()self.product['title'] = 'My Another Book Title'#### title,description,price,image_url不能為空def test_attrs_cannot_empty(self):f = ProductForm({})self.assertFalse(f.is_valid())self.assertTrue(f['title'].errors)self.assertTrue(f['description'].errors)self.assertTrue(f['price'].errors)self.assertTrue(f['image_url'].errors)####  price必須大于零def test_price_positive(self):f = ProductForm(self.product)self.assertTrue(f.is_valid())self.product['price'] = 0f = ProductForm(self.product)self.assertFalse(f.is_valid())self.product['price'] = -1f = ProductForm(self.product)self.assertFalse(f.is_valid())self.product['price'] = 1####  image_url必須以jpg,png,jpg結尾,并且對大小寫不敏感;def test_imgae_url_endwiths(self):url_base = 'http://google.com/'oks = ('fred.gif', 'fred.jpg', 'fred.png', 'FRED.JPG', 'FRED.Jpg')bads = ('fred.doc', 'fred.gif/more', 'fred.gif.more')for endwith in oks:self.product['image_url'] = url_base+endwithf = ProductForm(self.product)self.assertTrue(f.is_valid(),msg='error when image_url endwith '+endwith)for endwith in bads:self.product['image_url'] = url_base+endwithf = ProductForm(self.product)self.assertFalse(f.is_valid(),msg='error when image_url endwith '+endwith)self.product['image_url'] = 'http://google.com/logo.png'###  titile必須唯一def test_title_unique(self):self.product['title'] = 'My Book Title'f = ProductForm(self.product)self.assertFalse(f.is_valid())self.product['title'] = 'My Another Book Title'

然后運行 python manage.py test depotapp.ProductTest。如同預想的那樣,測試沒有通過:

Creating test database for alias 'default'....F..======================================================================FAIL: test_imgae_url_endwiths (depot.depotapp.tests.ProductTest)----------------------------------------------------------------------Traceback (most recent call last):File "/Users/holbrook/Documents/Dropbox/depot/../depot/depotapp/tests.py", line 65, in test_imgae_url_endwithsself.assertTrue(f.is_valid(),msg='error when image_url endwith '+endwith)AssertionError: False is not True : error when image_url endwith FRED.JPG----------------------------------------------------------------------Ran 4 tests in 0.055sFAILED (failures=1)Destroying test database for alias 'default'...

因為我們之前并沒有考慮到image_url的圖片擴展名可能會大寫。修改ProductForm的相關部分如下:

def clean_image_url(self):url = self.cleaned_data['image_url']ifnot endsWith(url.lower(), '.jpg', '.png', '.gif'):raise forms.ValidationError('圖片格式必須為jpg、png或gif')return url

然后再運行測試:

$ python manage.py test depotapp.ProductTest
Creating test database for alias 'default'.......----------------------------------------------------------------------Ran 4 tests in 0.060sOKDestroying test database for alias 'default'...

測試通過,并且通過單元測試,我們發現并解決了一個bug。


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
在线观看国产成人av片| 亚洲韩国青草视频| 97精品国产97久久久久久春色| 亚洲人精选亚洲人成在线| 热久久99这里有精品| 一本色道久久综合狠狠躁篇的优点| 国产精品视频yy9099| 6080yy精品一区二区三区| 久久久久久久久久久国产| 欧美性xxxx极品hd欧美风情| 日本久久精品视频| 欧美日韩精品在线| 国产成人综合一区二区三区| 美女精品视频一区| 久久天天躁夜夜躁狠狠躁2022| 不卡av在线网站| 国产成人精品最新| 国产小视频国产精品| 国产盗摄xxxx视频xxx69| 北条麻妃一区二区在线观看| 久久久久国产精品一区| 欧美巨乳在线观看| 在线观看欧美www| 91av在线免费观看| 91天堂在线视频| 亚洲第一精品福利| 丝袜亚洲欧美日韩综合| 欧美一级免费视频| 亚洲片在线资源| 亚洲网站在线看| 久久国产精品影片| 成人久久精品视频| 日韩欧美一区二区在线| 欧美午夜美女看片| 国产综合香蕉五月婷在线| 国产精品日韩在线观看| 91理论片午午论夜理片久久| 亚洲人成在线免费观看| 91在线高清免费观看| 久久影视三级福利片| 一区二区三区精品99久久| 国产精品www| 精品在线欧美视频| 成人午夜激情网| 在线观看精品自拍私拍| 成人中文字幕在线观看| 成人精品网站在线观看| 国产精品白丝av嫩草影院| 欧美大片免费观看| 国产成人精品优优av| 热re99久久精品国产66热| 欧美精品免费播放| 亚洲va欧美va国产综合剧情| 久久av在线播放| 中文.日本.精品| 久久韩国免费视频| 国产精品91久久久久久| 国产精品久久久久久久午夜| 欧美性xxxxxx| 性日韩欧美在线视频| 午夜精品久久久久久久白皮肤| 97人人模人人爽人人喊中文字| 国产精品第3页| 两个人的视频www国产精品| 中文字幕欧美国内| 日韩av网址在线| 欧美激情视频在线| 91国产高清在线| 久久不射电影网| 九九热这里只有在线精品视| 国产精品wwwwww| 久久五月天色综合| 亚洲品质视频自拍网| 亚洲娇小xxxx欧美娇小| 55夜色66夜色国产精品视频| 91网在线免费观看| 9.1国产丝袜在线观看| 一区二区三区国产视频| 色妞一区二区三区| 亚洲天堂男人天堂女人天堂| 久久久欧美精品| 成人做爽爽免费视频| 国产成人高清激情视频在线观看| 91中文精品字幕在线视频| 久久久久免费视频| 欧美激情视频播放| 国产91色在线播放| 国产精品情侣自拍| 国产日韩欧美夫妻视频在线观看| 97人人做人人爱| 欧美激情视频在线免费观看 欧美视频免费一| 欧美日韩第一视频| 中文字幕日韩精品在线观看| 欧美午夜www高清视频| 国产精品久久久久久久久| 亚洲电影成人av99爱色| 亚洲性生活视频在线观看| 精品久久久久久中文字幕| 国产有码一区二区| 日本高清+成人网在线观看| 国产精品专区第二| 国产精品pans私拍| 久久夜精品va视频免费观看| 国产精品亚洲精品| 亚洲日本欧美日韩高观看| 97视频在线播放| 久久视频国产精品免费视频在线| 国产国语videosex另类| 日韩中文在线不卡| www.亚洲一区| 亚洲人成网在线播放| 亚洲精品自产拍| 久久精品国产一区| 在线视频亚洲欧美| 久久九九国产精品怡红院| 亚洲第五色综合网| 国产精品网站入口| 国产视频一区在线| 日韩欧美在线视频| 国产欧美久久久久久| 日韩av电影国产| 久久久久www| 久热精品视频在线免费观看| 亚洲毛茸茸少妇高潮呻吟| 国产精品国模在线| 欧美在线免费视频| 日韩成人在线观看| 国产精品入口日韩视频大尺度| 精品亚洲va在线va天堂资源站| 国产精品老女人精品视频| 国产精品免费电影| 久久av资源网站| 久久影院模特热| 亚洲欧美在线一区二区| 午夜精品一区二区三区视频免费看| 成人黄色免费在线观看| 久久好看免费视频| 欧美福利视频在线观看| xxxx欧美18另类的高清| 亚洲国产高清福利视频| 日韩精品中文字幕视频在线| 操日韩av在线电影| 亚洲一区二区三区乱码aⅴ蜜桃女| 亚洲一区中文字幕在线观看| 亚洲韩国欧洲国产日产av| 国产va免费精品高清在线| 日韩精品久久久久久久玫瑰园| 欧美多人爱爱视频网站| 欧美精品久久久久久久久| 国产精品v日韩精品| 国产精品一区av| 国产91精品黑色丝袜高跟鞋| 亚洲国产精品视频在线观看| 久久久91精品国产一区不卡| 中文字幕亚洲精品| 国产日韩在线视频| 亚洲图片欧美午夜| 日韩成人在线播放| 久久人人爽亚洲精品天堂| 亚洲一区二区三区视频播放| 亚洲国产成人精品女人久久久| 久久成人免费视频| 日韩欧美主播在线| 欧美激情在线播放|