最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

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

 更新時間:2016年04月11日 16:07:10   作者:心內(nèi)求法  
這篇文章主要介紹了對Python的Django框架中的項目進行單元測試的方法,使用Django中的tests.py模塊可以輕松地檢測出一些常見錯誤,需要的朋友可以參考下

 Python中的單元測試

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

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

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

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

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)

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

下面是一個簡單的示例:

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()


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

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)

汗!發(fā)現(xiàn)了沒,竟然兩個都失敗了,測試發(fā)現(xiàn):

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

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

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

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

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

再次運行就不報錯了:

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

 
OK

Django中的單元測試

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

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

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

depot/depotapp/tests.py

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

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

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

用第三種方式執(zhí)行上面提供的樣例,結(jié)果如下:

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

OK
Destroying test database for alias 'default'...

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

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

class ProductTest < ActiveSupport::TestCase
test "product attributes must not be empty"do
product = Product.new
assert product.invalid?
assert product.errors[:title].any?
assert product.errors[:description].any?
assert product.errors[:price].any?
assert product.errors[:image_url].any?
end
test "product price must be positive"do
product = Product.new(:title => "My Book Title",
:description => "yyy",
:image_url => "zzz.jpg")
product.price = -1
assert product.invalid?
assert_equal "must be greater than or equal to 0.01",
product.errors[:price].join('; ')
product.price = 0
assert product.invalid?
assert_equal "must be greater than or equal to 0.01",
product.errors[:price].join('; ')
product.price = 1
assert product.valid?
end
def new_product(image_url)
Product.new(:title => "My Book Title",
:description => "yyy",
:price => 1,
:image_url => image_url)
end
test "image url"do
ok = %w{ fred.gif fred.jpg fred.png FRED.JPG FRED.Jpg
http://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"
end
bad.eachdo |name|
assert new_product(name).invalid?, "#{name} shouldn't be valid"
end
end
test "product is not valid without a unique title"do
product = Product.new(:title => products(:ruby).title,
:description => "yyy",
:price => 1,
:image_url => "fred.gif")
assert !product.save
assert_equal "has already been taken", product.errors[:title].join('; ')
end
test "product is not valid without a unique title - i18n"do
product = Product.new(:title => products(:ruby).title,
:description => "yyy",
:price => 1,
:image_url => "fred.gif")
assert !product.save
assert_equal I18n.translate('activerecord.errors.messages.taken'),
product.errors[:title].join('; ')
end
end

對Product測試的內(nèi)容包括:

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

2. price必須大于零;

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

4. titile必須唯一;

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

depot/depotapp/tests.py

#/usr/bin/python
#coding: utf8
"""
This file demonstrates writing tests using the unittest module. These will pass
when you run "manage.py test".
Replace this with more appropriate tests for your application.
"""
from django.test import TestCase
from forms import ProductForm
class 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'] = 0
f = ProductForm(self.product)
self.assertFalse(f.is_valid())
self.product['price'] = -1
f = ProductForm(self.product)
self.assertFalse(f.is_valid())
self.product['price'] = 1
####  image_url必須以jpg,png,jpg結(jié)尾,并且對大小寫不敏感;
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+endwith
f = 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+endwith
f = 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。如同預(yù)想的那樣,測試沒有通過:

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_endwiths
self.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.055s

FAILED (failures=1)
Destroying test database for alias 'default'...

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

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.060s

OK
Destroying test database for alias 'default'...

測試通過,并且通過單元測試,我們發(fā)現(xiàn)并解決了一個bug。

 

相關(guān)文章

  • Python BS4庫的安裝與使用詳解

    Python BS4庫的安裝與使用詳解

    這篇文章主要介紹了Python BS4庫的安裝與使用詳解,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-08-08
  • Pygame實戰(zhàn)練習(xí)之推箱子游戲

    Pygame實戰(zhàn)練習(xí)之推箱子游戲

    推箱子想必是很多人童年時期的經(jīng)典游戲,我們依舊能記得抱個老人機娛樂的場景,下面這篇文章主要給大家介紹了關(guān)于如何利用python寫一個簡單的推箱子小游戲的相關(guān)資料,需要的朋友可以參考下
    2021-09-09
  • Scrapy爬蟲框架集成selenium及全面詳細講解

    Scrapy爬蟲框架集成selenium及全面詳細講解

    這篇文章主要為大家介紹了Scrapy集成selenium,以及scarpy爬蟲框架全面講解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步早日升職加薪
    2022-04-04
  • 教你如何使用Python快速爬取需要的數(shù)據(jù)

    教你如何使用Python快速爬取需要的數(shù)據(jù)

    學(xué)點數(shù)據(jù)爬蟲基礎(chǔ)能讓繁瑣的數(shù)據(jù)CV工作(Ctrl+C,Ctrl+V)成為自動化就足夠了.作為一名數(shù)據(jù)分析師而并非開發(fā)工程師,需要掌握的爬蟲必備的知識內(nèi)容,能獲取需要的數(shù)據(jù)即可 ,需要的朋友可以參考下
    2021-06-06
  • 選擇Python寫網(wǎng)絡(luò)爬蟲的優(yōu)勢和理由

    選擇Python寫網(wǎng)絡(luò)爬蟲的優(yōu)勢和理由

    在本篇文章里小編給各位整理了一篇關(guān)于選擇Python寫網(wǎng)絡(luò)爬蟲的優(yōu)勢和理由以及相關(guān)代碼實例,有興趣的朋友們閱讀下吧。
    2019-07-07
  • Anaconda多環(huán)境多版本python配置操作方法

    Anaconda多環(huán)境多版本python配置操作方法

    下面小編就為大家?guī)硪黄狝naconda多環(huán)境多版本python配置操作方法。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-09-09
  • 磁盤垃圾文件清理器python代碼實現(xiàn)

    磁盤垃圾文件清理器python代碼實現(xiàn)

    幾行Python代碼打造自己的磁盤垃圾文件清理器,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-03-03
  • 詳解如何使用SQLAlchemy連接數(shù)據(jù)庫

    詳解如何使用SQLAlchemy連接數(shù)據(jù)庫

    這篇文章主要為大家詳細介紹了如何使用 SQLAlchemy 連接數(shù)據(jù)庫、建立模型、操作表、以及查詢操作表數(shù)據(jù)等內(nèi)容,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2023-11-11
  • windows下安裝Python和pip終極圖文教程

    windows下安裝Python和pip終極圖文教程

    本文希望提供傻瓜式的教程,能夠令讀者成功安裝Python和pip,需要的朋友可以參考下
    2017-03-03
  • 如何修復(fù)使用 Python ORM 工具 SQLAlchemy 時的常見陷阱

    如何修復(fù)使用 Python ORM 工具 SQLAlchemy 時的常見陷阱

    SQLAlchemy 是一個 Python ORM 工具包,它提供使用 Python 訪問 SQL 數(shù)據(jù)庫的功能。這篇文章主要介紹了如何修復(fù)使用 Python ORM 工具 SQLAlchemy 時的常見陷阱,需要的朋友可以參考下
    2019-11-11

最新評論

闽侯县| 宜川县| 屏山县| 大同市| 元江| 浦北县| 莱州市| 樟树市| 松潘县| 临漳县| 改则县| 大悟县| 巧家县| 城市| 衡山县| 赤壁市| 纳雍县| 绥棱县| 克什克腾旗| 固镇县| 昂仁县| 永川市| 连山| 紫云| 呼伦贝尔市| 龙泉市| 石家庄市| 根河市| 眉山市| 宜阳县| 阿克苏市| 东乌珠穆沁旗| 晴隆县| 巴彦淖尔市| 贡嘎县| 高平市| 桐乡市| 库车县| 建阳市| 象州县| 喀喇|