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

Python 單元測試(unittest)的使用小結(jié)

 更新時間:2018年11月14日 13:45:13   作者:騎士救兵  
Python中有一個自帶的單元測試框架是unittest模塊,用它來做單元測試,本篇文章主要介紹了Python 單元測試(unittest)的使用小結(jié),具有一定的參考價值,感興趣的小伙伴們可以參考一下

測試目錄

項(xiàng)目的整體結(jié)構(gòu)可以參考“軟件目錄開發(fā)規(guī)范”,這里單說測試目錄。一般都是在項(xiàng)目里單獨(dú)創(chuàng)建一個測試目錄,目錄名就是“tests”。

關(guān)于目錄的位置,一種建議是,在項(xiàng)目名(假設(shè)項(xiàng)目名是Foo)的一級子目錄下創(chuàng)建二級子目錄 “Foo/foo/tests” 。但是這樣可能是因?yàn)橛闷饋聿环奖?,有很多是按下面的做法。不過下面的示例我還是用這個方法來創(chuàng)建測試目錄。
還可以把測試目錄向上移一層,作為一級子目錄,直接創(chuàng)建在項(xiàng)目之下 “Foo/tests”。參考django、scrapy、flask都是這樣的做法。

測試函數(shù)

標(biāo)題的意思是對函數(shù)(def)進(jìn)行測試,相對于測試類(class)。

學(xué)習(xí)測試,得有要測試的代碼。下面是一個簡單的函數(shù),接收城市名和國家名,返回一個格式為“City, Country“這樣的字符串:

# UnitTest/unit_test/utils/city_functions.py
def get_city_info(city, country):
  city_info = "%s, %s" % (city, country)
  return city_info.title()

接下來就對上面的這個函數(shù)進(jìn)行測試。

手動測試

現(xiàn)在來寫一個使用這個函數(shù)的程序:

# UnitTest/unit_test/test/cities.py
try:
  from unit_test.utils.city_functions import get_city_info
except ModuleNotFoundError:
  import sys
  sys.path.append('../..')
  from unit_test.utils.city_functions import get_city_info

print("Enter 'q' at any time to quit.")
while True:
  city = input("city name: ")
  if city == 'q':
    break
  country = input("country name: ")
  if country == 'q':
    break
  fullname = get_city_info(city, country)
  print("\tcity info:", fullname)

然后運(yùn)行的結(jié)果:

Enter 'q' at any time to quit.
city name: shanghai
country name: china
    city info: Shanghai, China
city name: q

Process finished with exit code 0

上面這樣是手動測試,還是得有一種自動測試函數(shù)輸出的高效方式。如果能夠?qū)et_fullname()進(jìn)行自動測試,就能始終確信,給這個函數(shù)提供測試過的姓名后,它能返回正確的結(jié)果。尤其是在對函數(shù)進(jìn)行修改的前后。

模塊導(dǎo)入路徑的問題

PyCharm會自動把項(xiàng)目目錄加到環(huán)境變量里去,在PyCharm里執(zhí)行都沒問題。但是如果不用PyCharm而是單獨(dú)運(yùn)行,這個目錄結(jié)構(gòu)應(yīng)該會有點(diǎn)問題,會找不到需要測試的函數(shù)。簡單點(diǎn)就是把測試用例和被測試的函數(shù)放到同一個目錄里,然后改一下 from import 就可以正常運(yùn)行了。或者自己手動添加環(huán)境變量,就像例子里那樣。

單元測試-unittest

Python標(biāo)準(zhǔn)庫中的模塊unittest提供了代碼測試工具。

創(chuàng)建測試用例

為函數(shù)編寫測試用例,可先導(dǎo)入模塊unittest以及要測試的函數(shù),再創(chuàng)建一個繼承unittest.TestCase的類,并編寫一系列方法對函數(shù)行為的不同方面進(jìn)行測試。

下面是一個只包含一個方法的測試用例:

# UnitTest/unit_test/test/test_city_functions.py
import unittest
try:
  from unit_test.utils.city_functions import get_city_info
except ModuleNotFoundError:
  import sys
  sys.path.append('../..')
  from unit_test.utils.city_functions import get_city_info

class CitiesTestCase(unittest.TestCase):
  """測試city_functions.py"""
  def test_city_country(self):
    city_info = get_city_info('shanghai', 'china')
    self.assertEqual(city_info, 'Shanghai, China')

  def test_New_York(self):
    city_info = get_city_info('new york', 'America')
    self.assertEqual(city_info, 'New York, America')

if __name__ == '__main__':
  unittest.main()

命名的規(guī)則和建議:

  • 類名,可以任意起名,但是最好看起來和測試有關(guān)并包含Test字樣。
  • 方法名,名字必須以“test_”開頭,所有以“test_”開頭的方法,都會自動運(yùn)行

在測試的方法的最后,使用了unittest類最有用的功能之一:一個斷言方法。來檢查得到的結(jié)果和我們預(yù)期的結(jié)果是否一致。

輸出的效果

最后一行 unittest.main() 讓Python運(yùn)行這個文件中的測試。執(zhí)行程序后得到如下的輸出:

.
----------------------------------------------------------------------
Ran 1 test in 0.000s

OK

運(yùn)行測試用例時,每完成一個單元測試,Python都打印一個字符:

  • 測試通過時打印一個句點(diǎn);
  • 測試引發(fā)錯誤時打印一個E;
  • 測試導(dǎo)致斷言失敗時打印一個F。

這就是你運(yùn)行測試用例時,在輸出的第一行中看到的句點(diǎn)和字符數(shù)量各不相同的原因。如果測試用例包含很多單元測試,需要運(yùn)行很長時間,就可通過觀察這些結(jié)果來獲悉有多少個測試通過了。

PyCharm對單元測試做了自己的優(yōu)化,輸出看不到上面的點(diǎn),而是有更加漂亮的展示方式。

測試不通過

現(xiàn)在看下測試不通過的效果。這里不修改測試用例,而是對get_city_info()函數(shù)做一個update,現(xiàn)在還要顯示城市的人口數(shù)量:

def get_city_info(city, country, population):
  city_info = "%s, %s - 人口: %d" % (city, country, population)
  return city_info.title()

這次再執(zhí)行測試用例,輸出如下:

E
======================================================================
ERROR: test_city_country (__main__.CitiesTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "test_city_functions.py", line 17, in test_city_country
    city_info = get_city_info('shanghai', 'china')
TypeError: get_city_info() missing 1 required positional argument: 'population'

----------------------------------------------------------------------
Ran 1 test in 0.001s

FAILED (errors=1)

這里看的是E而不是之前的點(diǎn),表示有一個錯誤。

測試未通過的處理

這里不要去修改之前的測試用例。假設(shè)update之前的函數(shù)已經(jīng)在項(xiàng)目內(nèi)使用起來了,現(xiàn)在測試不通過,表示之前調(diào)用這個函數(shù)的代碼都有問題。如果不想改項(xiàng)目里其它的代碼,這里先嘗試修改get_city_info()函數(shù),讓它能夠通過測試,也可以加上新的功能:

# UnitTest/unit_test/utils/city_functions.py
def get_city_info(city, country, population=None):
  if population:
    city_info = "%s, %s - 人口: %d" % (city, country, population)
  else:
    city_info = "%s, %s" % (city, country)
  return city_info.title()

現(xiàn)在的各個版本的update才是兼容舊版本的代碼,這次測試用例就可以通過了。

添加新測試

之前的測試用例只能驗(yàn)證就的功能,現(xiàn)在添加了新功能,是否沒問題,還得通過測試來進(jìn)行驗(yàn)證:

# UnitTest/unit_test/test/test_city_functions.py
class CitiesTestCase(unittest.TestCase):
  """測試city_functions.py"""
  def test_city_country(self):
    city_info = get_city_info('shanghai', 'china')
    self.assertEqual(city_info, 'Shanghai, China')

  def test_New_York_population(self):
    city_info = get_city_info('new york', 'America', 8537673)
    self.assertEqual(city_info, 'New York, America - 人口: 8537673')

現(xiàn)在新功能的測試用例也用了,并且2個測試都能通過。以后如果還需要對get_city_info()函數(shù)進(jìn)行修改,只要再運(yùn)行測試就可以知道新的代碼是否會對原有的項(xiàng)目有影響。

斷言方法

模塊在unittest.TestCase類中提供了很多斷言方法,之前已經(jīng)用一個了。下面是6個常用的斷言方法:

  • assertEqual(a, b) : 核實(shí)a == b
  • assertNotEqual(a, b) : 核實(shí)a != b
  • assertTrue(x) : 核實(shí)x為True
  • assertFalse(x) : 核實(shí)x為False
  • assertIn(item, list) : 核實(shí)item在list中
  • assertNotIn(item, list) : 核實(shí)item不在list中

你只能在繼承unittest.TestCase的類中使用這些方法。

測試類

前面的內(nèi)容只是對函數(shù)進(jìn)行測試。很多時候都會用到類,因?yàn)檫€需要能夠證明類也可以正常的運(yùn)行。類的測試與函數(shù)的測試相似,其中大部分工作都是測試類中方法的行為,但存在一些不同之處。

準(zhǔn)備要測試的類

先編寫一個類來進(jìn)行測試,這個類里存儲了一個課程名,以及學(xué)習(xí)該課程的學(xué)員:

# UnitTest/unit_test/course.py
class CourseManage(object):

  def __init__(self, course):
    self.course = course
    self.students = []

  def show_course(self):
    print("課程:", self.course)

  def add_student(self, name):
    self.students.append(name)

  def show_students(self):
    print("所有學(xué)員:")
    for student in self.students:
      print('-', student)

為證明CourseManage類工作正常,再編寫一個使用它的程序:

from unit_test.course import CourseManage

course = CourseManage("Python")
course.show_course()
print("準(zhǔn)備錄入學(xué)員...")
print("Enter 'q' at any time to quit.\n")
while True:
  resp = input("Student's Name: ")
  if resp == 'q':
    break
  if resp:
    course.add_student(resp.title())
print("\n錄入完畢...")
course.show_students()

這段程序定義了一門課程,并使用課程名創(chuàng)建了一個CourseManage對象。接下來主要就是調(diào)用對象的add_student()方法來錄入學(xué)員名字。輸入完畢后,按q能退出。最后會打印所有的學(xué)員。
所有的輸入和輸出如下:

課程: Python
準(zhǔn)備錄入學(xué)員...
Enter 'q' at any time to quit.

Student's Name: oliver queen
Student's Name: barry allen
Student's Name: kara
Student's Name: sara lance
Student's Name: q

錄入完畢...
所有學(xué)員:
- Oliver Queen
- Barry Allen
- Kara
- Sara Lance

Process finished with exit code 0

編寫類的測試用例

下面來編寫一個測試,對CourseManage類的行為的一個方面進(jìn)行驗(yàn)證。如果用戶輸入了某個學(xué)員的名字,這個名字可以被存儲在self.students的列表里。所以,需要做的是在學(xué)員被錄入后,使用assertIn()這個斷言方法:

# UnitTest/unit_test/test/test_course.py
import unittest
from unit_test.course import CourseManage

class TestCourseManage(unittest.TestCase):

  def test_add_student(self):
    course = CourseManage("Python")
    name = 'snart'
    course.add_student(name.title())
    self.assertIn('Snart', course.students)

if __name__ == '__main__':
  unittest.main()

上面的方法只驗(yàn)證了錄入一個學(xué)員的情況,而大多數(shù)情況下都是有很多學(xué)員的。所以,還要添加一個方法,驗(yàn)證錄入多個學(xué)員是否正常:

class TestCourseManage(unittest.TestCase):

  def test_add_student(self):
    course = CourseManage("Python")
    name = 'snart'
    course.add_student(name.title())
    self.assertIn('Snart', course.students)

  def test_add_students(self):
    course = CourseManage("Python")
    name_list = ['oliver queen', 'barry allen', 'kara', 'sara lance']
    for name in name_list:
      course.add_student(name.title())
    for name in name_list:
      self.assertIn(name.title(), course.students)

setUp() 方法

在上面的例子里,每個測試方法中都創(chuàng)建了一個實(shí)例。但是還有一種需求是,我希望只創(chuàng)建一個實(shí)例,但是要在多個方法里對這個實(shí)例進(jìn)行操作來反復(fù)驗(yàn)證。在unittest.TestCase類包含方法setUp(),就可以只實(shí)例化一次,并可以在每個測試方法中使用。如果在TestCase類中包含了方法setUp(),Python會先運(yùn)行它,再運(yùn)行各個以test_打頭的方法。
簡單點(diǎn)說,setUp()方法就是在父類里預(yù)留的一個鉤子,會在其他測試方法運(yùn)行前先運(yùn)行:

import unittest
from unit_test.course import CourseManage

class TestCourseManage(unittest.TestCase):

  def setUp(self):
    self.course = CourseManage("Python")
    self.name_list = ['oliver queen', 'barry allen', 'kara', 'sara lance']

  def test_add_student(self):
    name = 'snart'
    self.course.add_student(name.title())
    self.assertIn('Snart', self.course.students)

  def test_add_students(self):
    for name in self.name_list:
      self.course.add_student(name.title())
    for name in self.name_list:
      self.assertIn(name.title(), self.course.students)

if __name__ == '__main__':
  unittest.main()

測試自己編寫的類時,使用setUp()方法會讓測試方法編寫起來更容易,下面是建議的做法:

在setUp()方法中創(chuàng)建一系列實(shí)例并設(shè)置它們的屬性,再在測試方法中直接使用這些實(shí)例。相比于在每個測試方法中都創(chuàng)建實(shí)例并設(shè)置其屬性,這要容易得多。

小結(jié)

如果你在項(xiàng)目中包含了初步測試,其他程序員將更敬佩你,他們將能夠更得心應(yīng)手地嘗試使用你編寫的代碼,也更愿意與你合作開發(fā)項(xiàng)目。如果你要跟其他程序員開發(fā)的項(xiàng)目共享代碼,就必須證明你編寫的代碼通過了既有測試,通常還需要為你添加的新行為編寫測試。

請通過多開展測試來熟悉代碼測試過程。對于自己編寫的函數(shù)和類,請編寫針對其重要行為的測試,但在項(xiàng)目早期,不要試圖去編寫全覆蓋的測試用例,除非有充分的理由這樣做。

pytest

這篇講的是Python內(nèi)置的單元測試模塊。作為初學(xué)者先用著熟悉起來就很不錯了。

pytest是Python最流程的單測框架之一。具體可以上GitHub參考下那些開源項(xiàng)目的單元測試,很多用的是這個。

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • 對Python協(xié)程之異步同步的區(qū)別詳解

    對Python協(xié)程之異步同步的區(qū)別詳解

    今天小編就為大家分享一篇對Python協(xié)程之異步同步的區(qū)別詳解,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2019-02-02
  • Python處理浮點(diǎn)數(shù)的實(shí)用技巧分享

    Python處理浮點(diǎn)數(shù)的實(shí)用技巧分享

    四舍五入是一種常見的數(shù)學(xué)操作,它用于將數(shù)字舍入到指定的精度,Python?提供了多種方法來實(shí)現(xiàn)四舍五入操作,本文將詳細(xì)介紹這些方法,希望對大家有所幫助
    2024-12-12
  • 簡單介紹Python中的round()方法

    簡單介紹Python中的round()方法

    這篇文章主要介紹了簡單介紹Python中的round()方法,是Python入門的基礎(chǔ)知識,需要的朋友可以參考下
    2015-05-05
  • Python中單元測試的快速入門指南

    Python中單元測試的快速入門指南

    在這篇文章中,我們會深入探討Python單元測試的各個方面,包括它的基本概念、基礎(chǔ)知識、實(shí)踐方法、高級話題,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2023-07-07
  • python利用蒙版摳圖(使用PIL.Image和cv2)輸出透明背景圖

    python利用蒙版摳圖(使用PIL.Image和cv2)輸出透明背景圖

    這篇文章主要介紹了python利用蒙版摳圖(使用PIL.Image和cv2)輸出透明背景圖,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-08-08
  • python 如何用 Hypothesis 來自動化單元測試

    python 如何用 Hypothesis 來自動化單元測試

    這篇文章主要介紹了python 如何用 Hypothesis 來自動化單元測試,幫助大家更好的理解和學(xué)習(xí)使用python,感興趣的朋友可以了解下
    2021-03-03
  • pandas時間序列之如何將int轉(zhuǎn)換成datetime格式

    pandas時間序列之如何將int轉(zhuǎn)換成datetime格式

    這篇文章主要介紹了pandas時間序列之如何將int轉(zhuǎn)換成datetime格式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-07-07
  • python+opencv3.4.0 實(shí)現(xiàn)HOG+SVM行人檢測的示例代碼

    python+opencv3.4.0 實(shí)現(xiàn)HOG+SVM行人檢測的示例代碼

    這篇文章主要介紹了python+opencv3.4.0 實(shí)現(xiàn)HOG+SVM行人檢測的示例代碼,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-01-01
  • Pandas實(shí)現(xiàn)兩個表的連接功能的方法詳解

    Pandas實(shí)現(xiàn)兩個表的連接功能的方法詳解

    這篇文章主要和大家一起說說pandas的兩個表的連接技能merge,也就是根據(jù)一個表的條件去匹配另一個表的內(nèi)容,感興趣的可以跟隨小編一起學(xué)習(xí)一下
    2022-09-09
  • Python調(diào)用C語言動態(tài)庫的方法小結(jié)

    Python調(diào)用C語言動態(tài)庫的方法小結(jié)

    這篇文章主要為大家詳細(xì)介紹了Python調(diào)用C語言動態(tài)庫的相關(guān)知識,文中的示例代碼講解詳細(xì),具有一定的借鑒價值,有需要的小伙伴可以參考一下
    2024-12-12

最新評論

莲花县| 中山市| 大邑县| 衢州市| 鄂伦春自治旗| 灯塔市| 曲阜市| 龙陵县| 延长县| 洛浦县| 高阳县| 柘荣县| 宁津县| 温州市| 山阴县| 朝阳县| 澄江县| 雷波县| 克山县| 习水县| 揭东县| 满洲里市| 宁武县| 云安县| 房产| 玛纳斯县| 乌拉特前旗| 威宁| 萨嘎县| 湘潭市| 鄱阳县| 伊金霍洛旗| 阿克陶县| 天津市| 布拖县| 南靖县| 永和县| 项城市| 高州市| 古浪县| 梧州市|