欧美性猛交xxxx免费看_牛牛在线视频国产免费_天堂草原电视剧在线观看免费_国产粉嫩高清在线观看_国产欧美日本亚洲精品一5区

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

深度剖析基于Python中的Mock

馬哥Linux運維 ? 2018-01-30 15:26 ? 次閱讀

Mock是什么

Mock這個詞在英語中有模擬的這個意思,因此我們可以猜測出這個庫的主要功能是模擬一些東西。準確的說,Mock是Python中一個用于支持單元測試的庫,它的主要功能是使用mock對象替代掉指定的Python對象,以達到模擬對象的行為。簡單的說,mock庫用于如下的場景:

假設(shè)你開發(fā)的項目叫a,里面包含了一個模塊b,模塊b中的一個函數(shù)c(也就是a.b.c)在工作的時候需要調(diào)用發(fā)送請求給特定的服務(wù)器來得到一個JSON返回值,然后根據(jù)這個返回值來做處理。如果要為a.b.c函數(shù)寫一個單元測試,該如何做?

一個簡單的辦法是搭建一個測試的服務(wù)器,在單元測試的時候,讓a.b.c函數(shù)和這個測試服務(wù)器交互。但是這種做法有兩個問題:

測試服務(wù)器可能很不好搭建,或者搭建效率很低。

你搭建的測試服務(wù)器可能無法返回所有可能的值,或者需要大量的工作才能達到這個目的。

那么如何在沒有測試服務(wù)器的情況下進行上面這種情況的單元測試呢?Mock模塊就是答案。上面已經(jīng)說過了,mock模塊可以替換Python對象。我們假設(shè)a.b.c的代碼如下:

import requests

defc(url):

resp = requests.get(url)

# further process with resp

如果利用mock模塊,那么就可以達到這樣的效果:使用一個mock對象替換掉上面的requests.get函數(shù),然后執(zhí)行函數(shù)c時,c調(diào)用requests.get的返回值就能夠由我們的mock對象來決定,而不需要服務(wù)器的參與。簡單的說,就是我們用一個mock對象替換掉c函數(shù)和服務(wù)器交互的過程。你一定很好奇這個功能是如何實現(xiàn)的,這個是mock模塊內(nèi)部的實現(xiàn)機制,不在本文的討論范圍。本文主要討論如何用mock模塊來解決上面提到的這種單元測試場景。

Mock的安裝和導(dǎo)入

在Python 3.3以前的版本中,需要另外安裝mock模塊,可以使用pip命令來安裝:

$sudo pip install mock

然后在代碼中就可以直接import進來:

import mock

從Python 3.3開始,mock模塊已經(jīng)被合并到標準庫中,被命為unittest.mock,可以直接import進來使用:

from unittest import mock

Mock對象

基本用法

Mock對象是mock模塊中最重要的概念。Mock對象就是mock模塊中的一個類的實例,這個類的實例可以用來替換其他的Python對象,來達到模擬的效果。Mock類的定義如下:

classMock(spec=None,side_effect=None,return_value=DEFAULT,wraps=None,name=None,spec_set=None, **kwargs)

這里給出這個定義只是要說明下Mock對象其實就是個Python類而已,當然,它內(nèi)部的實現(xiàn)是很巧妙的,有興趣的可以去看mock模塊的代碼。

Mock對象的一般用法是這樣的:

找到你要替換的對象,這個對象可以是一個類,或者是一個函數(shù),或者是一個類實例。

然后實例化Mock類得到一個mock對象,并且設(shè)置這個mock對象的行為,比如被調(diào)用的時候返回什么值,被訪問成員的時候返回什么值等。

使用這個mock對象替換掉我們想替換的對象,也就是步驟1中確定的對象。

之后就可以開始寫測試代碼,這個時候我們可以保證我們替換掉的對象在測試用例執(zhí)行的過程中行為和我們預(yù)設(shè)的一樣。

舉個例子來說:我們有一個簡單的客戶端實現(xiàn),用來訪問一個URL,當訪問正常時,需要返回狀態(tài)碼200,不正常時,需要返回狀態(tài)碼404。首先,我們的客戶端代碼實現(xiàn)如下:

#!/usr/bin/env python

# -*- coding: utf-8 -*-

import requests

def send_request(url):

r = requests.get(url)

returnr.status_code

def visit_ustack():

returnsend_request('http://www.ustack.com')

外部模塊調(diào)用visit_ustack()來訪問UnitedStack的官網(wǎng)。下面我們使用mock對象在單元測試中分別測試訪問正常和訪問不正常的情況。

#!/usr/bin/env python

# -*- coding: utf-8 -*-

import unittest

import mock

import client

classTestClient(unittest.TestCase):

def test_success_request(self):

success_send = mock.Mock(return_value='200')

client.send_request = success_send

self.assertEqual(client.visit_ustack(),'200')

def test_fail_request(self):

fail_send = mock.Mock(return_value='404')

client.send_request = fail_send

self.assertEqual(client.visit_ustack(),'404')

找到要替換的對象:我們需要測試的是visit_ustack這個函數(shù),那么我們需要替換掉send_request這個函數(shù)。

實例化Mock類得到一個mock對象,并且設(shè)置這個mock對象的行為。在成功測試中,我們設(shè)置mock對象的返回值為字符串“200”,在失敗測試中,我們設(shè)置mock對象的返回值為字符串”404″。

使用這個mock對象替換掉我們想替換的對象。我們替換掉了client.send_request

寫測試代碼。我們調(diào)用client.visit_ustack(),并且期望它的返回值和我們預(yù)設(shè)的一樣。

上面這個就是使用mock對象的基本步驟了。在上面的例子中我們替換了自己寫的模塊的對象,其實也可以替換標準庫和第三方模塊的對象,方法是一樣的:先import進來,然后替換掉指定的對象就可以了。

稍微高級點的用法

class Mock的參數(shù)

上面講的是mock對象最基本的用法。下面來看看mock對象的稍微高級點的用法(并不是很高級啊,最完整最高級的直接去看mock的文檔即可,后面給出)。

先來看看Mock這個類的參數(shù),在上面看到的類定義中,我們知道它有好幾個參數(shù),這里介紹最主要的幾個:

name: 這個是用來命名一個mock對象,只是起到標識作用,當你print一個mock對象的時候,可以看到它的name。

return_value: 這個我們剛才使用過了,這個字段可以指定一個值(或者對象),當mock對象被調(diào)用時,如果side_effect函數(shù)返回的是DEFAULT,則對mock對象的調(diào)用會返回return_value指定的值。

side_effect: 這個參數(shù)指向一個可調(diào)用對象,一般就是函數(shù)。當mock對象被調(diào)用時,如果該函數(shù)返回值不是DEFAULT時,那么以該函數(shù)的返回值作為mock對象調(diào)用的返回值。

深度剖析基于Python中的Mock

其他的參數(shù)請參考官方文檔。

mock對象的自動創(chuàng)建

當訪問一個mock對象中不存在的屬性時,mock會自動建立一個子mock對象,并且把正在訪問的屬性指向它,這個功能對于實現(xiàn)多級屬性的mock很方便。

client = mock.Mock()

client.v2_client.get.return_value = '200'

這個時候,你就得到了一個mock過的client實例,調(diào)用該實例的v2_client.get()方法會得到的返回值是”200″。

從上面的例子中還可以看到,指定mock對象的return_value還可以使用屬性賦值的方法。

對方法調(diào)用進行檢查

mock對象有一些方法可以用來檢查該對象是否被調(diào)用過、被調(diào)用時的參數(shù)如何、被調(diào)用了幾次等。實現(xiàn)這些功能可以調(diào)用mock對象的方法,具體的可以查看mock的文檔。這里我們舉個例子。

還是使用上面的代碼,這次我們要檢查visit_ustack()函數(shù)調(diào)用send_request()函數(shù)時,傳遞的參數(shù)類型是否正確。我們可以像下面這樣使用mock對象。

classTestClient(unittest.TestCase):

def test_call_send_request_with_right_arguments(self):

client.send_request = mock.Mock()

client.visit_ustack()

self.assertEqual(client.send_request.called,True)

call_args = client.send_request.call_args

self.assertIsInstance(call_args[0][0],str)

Mock對象的called屬性表示該mock對象是否被調(diào)用過。

Mock對象的call_args表示該mock對象被調(diào)用的tuple,tuple的每個成員都是一個mock.call對象。mock.call這個對象代表了一次對mock對象的調(diào)用,其內(nèi)容是一個tuple,含有兩個元素,第一個元素是調(diào)用mock對象時的位置參數(shù)(*args),第二個元素是調(diào)用mock對象時的關(guān)鍵字參數(shù)(**kwargs)。

現(xiàn)在來分析下上面的用例,我們要檢查的項目有兩個:

visit_ustack()調(diào)用了send_request()

調(diào)用的參數(shù)是一個字符串

patch和patch.object

在了解了mock對象之后,我們來看兩個方便測試的函數(shù):patch和patch.object。這兩個函數(shù)都會返回一個mock內(nèi)部的類實例,這個類是class _patch。返回的這個類實例既可以作為函數(shù)的裝飾器,也可以作為類的裝飾器,也可以作為上下文管理器。使用patch或者patch.object的目的是為了控制mock的范圍,意思就是在一個函數(shù)范圍內(nèi),或者一個類的范圍內(nèi),或者with語句的范圍內(nèi)mock掉一個對象。我們看個代碼例子即可:

classTestClient(unittest.TestCase):

def test_success_request(self):

status_code = '200'

success_send = mock.Mock(return_value=status_code)

with mock.patch('client.send_request',success_send):

from client import visit_ustack

self.assertEqual(visit_ustack(),status_code)

def test_fail_request(self):

status_code = '404'

fail_send = mock.Mock(return_value=status_code)

with mock.patch('client.send_request',fail_send):

from client import visit_ustack

self.assertEqual(visit_ustack(),status_code)

這個測試類和我們剛才寫的第一個測試類一樣,包含兩個測試,只不過這次不是顯示創(chuàng)建一個mock對象并且進行替換,而是使用了patch函數(shù)(作為上下文管理器使用)。

patch.object和patch的效果是一樣的,只不過用法有點不同。舉例來說,同樣是上面這個例子,換成patch.object的話是這樣的:

def test_fail_request(self):

status_code = '404'

fail_send = mock.Mock(return_value=status_code)

with mock.patch.object(client,'send_request',fail_send):

from client import visit_ustack

self.assertEqual(visit_ustack(),status_code)

就是替換掉一個對象的指定名稱的屬性,用法和setattr類似。

如何學(xué)習(xí)使用mock?

你肯定很奇怪,本文不就是教人使用mock的么?其實不是的,我發(fā)現(xiàn)自己在學(xué)習(xí)mock的過程中遇到的主要困難是不清楚mock能做什么,而不是mock對象到底有哪些函數(shù)。因此寫這篇文章的主要目的是為了說明mock能做什么。

當你知道了mock能做什么之后,要如何學(xué)習(xí)并掌握mock呢?最好的方式就是查看閱讀官方文檔,并在自己的單元測試中使用。

最后,學(xué)習(xí)mock技能你應(yīng)該要能夠感受到一種控制的快感,就是你能享受控制外部服務(wù)的快樂。當你感受到這種快感的時候,你的mock應(yīng)該就達到熟練使用的水平了。

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • 模擬
    +關(guān)注

    關(guān)注

    7

    文章

    1430

    瀏覽量

    83993
  • python
    +關(guān)注

    關(guān)注

    56

    文章

    4811

    瀏覽量

    85081

原文標題:開發(fā)神技能 | Python Mock 的入門

文章出處:【微信號:magedu-Linux,微信公眾號:馬哥Linux運維】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。

收藏 人收藏

    評論

    相關(guān)推薦

    《C語言深度剖析》【超經(jīng)典書籍】

    本帖最后由 zgzzlt 于 2012-8-16 14:23 編輯 《C語言深度剖析》【超經(jīng)典書籍】
    發(fā)表于 08-02 08:59

    C語言深度剖析

    C語言深度剖析——一本關(guān)于C語言學(xué)習(xí)的教程,里面包含C語言編寫規(guī)范,各種變量指針用法等。以含金量勇敢挑戰(zhàn)國內(nèi)外同類書籍
    發(fā)表于 08-14 11:36

    c語言深度剖析

    c語言深度剖析
    發(fā)表于 04-02 09:12

    陳正沖《C語言深度剖析

    陳正沖編寫的《C語言深度剖析》,挺經(jīng)典,剛來論壇,多多指教~~
    發(fā)表于 08-17 12:06

    linux內(nèi)核深度剖析,另附有光盤資料

    linux內(nèi)核深度剖析,對于想學(xué)linux內(nèi)核的人來說,絕對值得一看,另附有光盤資料。
    發(fā)表于 01-15 21:25

    【資料分享】C語言深度剖析

    C語言深度剖析
    發(fā)表于 10-16 15:16

    C語言深度剖析

    C語言深度剖析
    發(fā)表于 08-25 09:08

    C語言深度剖析

    C語言深度剖析[完整版].pdfC語言深度剖析[完整版].pdf (919.58 KB )
    發(fā)表于 03-19 05:11

    Python深度學(xué)習(xí)的數(shù)學(xué)基礎(chǔ)

    算法工程師修仙之路:Python深度學(xué)習(xí)(八)
    發(fā)表于 04-02 13:03

    深度學(xué)習(xí)入門之基于python的理論與實現(xiàn)

    深度學(xué)習(xí)入門-基于python的理論與實現(xiàn)(2)
    發(fā)表于 06-19 11:22

    C語言深度剖析

    C語言深度剖析
    發(fā)表于 05-05 17:40 ?7次下載

    C語言深度剖析

    C語言深度剖析
    發(fā)表于 12-20 22:50 ?0次下載

    基于Python的理論與實現(xiàn)進行深度學(xué)習(xí)的入門教程

    本書是深度學(xué)習(xí)真正意義上的入門書,深入淺出地剖析深度學(xué)習(xí)的原理和相關(guān)技術(shù)。書中使用Python 3,盡量不依賴外部庫或工具,帶領(lǐng)讀者從零創(chuàng)建一個經(jīng)典的
    發(fā)表于 11-11 08:00 ?6次下載

    Python深度學(xué)習(xí)

    Python深度學(xué)習(xí)教材資料下載。
    發(fā)表于 06-01 14:40 ?41次下載

    C語言深度剖析.zip

    C語言深度剖析
    發(fā)表于 12-30 09:20 ?5次下載