[gist]How to use Mock testing Python

from http://oyanglul.ushtml

最近在用 nosetestsmock1 爲 bottle 應用測試, 發現幾個使用nosetests 要注意的 地方: python

1 patch method of module

patch 一個導入 module 的 method, 由於 method 已經被導入到目標文件, 所以必須 要 patch 目標文件的 該方法, 而不是原 module. git

# wsgi.py
from db import get_db

def insert_something():
    get_db().insert(something)

# test.py
import wsgi

# @patch('db.get_db') # this won't work
@patch('wsgi.get_db') # should patch wsgi
def test_insert(mock_get_db):
    mock_get_db.return_value = Database()
    ...

2 patch decorator

Scenario : bottle 的 views 是用 decorator 來定義的, 也就是說當咱們測試 bottle 中 得 action 時其實這個 action 是被 views 包住的. return 的 dict 會被 bottle 的 views 函數 render 成 html 並返回. 而咱們並不須要測試 views 返回的 html, 而只須要測試 return 的 dict 是否正確. github

這種狀況太適合 mock 的 patch 來幹了. django

  1. patch bottle.view
  2. 讓其返回一個神馬都沒幹的函數
  3. 啓動這個patch
  4. 導入須要測試的應用代碼

注意 這裏的patch必須在 import 你的 application 以前, 好比個人應用是 wsgi.py api

完整過程是這樣的 markdown

from mock import patch, Mock
import bottle
v = patch("bottle.view",return_value = lambda x : x)
v.start() ** 使用 local config 來存放你的密匙
import wsgi

3 mock module that may not exist

Scenario: 一些帶有密匙的配置文件(好比 google api key 之類的)並不但願被上傳到 github public 上, 可是測試又須要引入這些文件.(後來我發現了更 elegant 的解決方式 使用 local config 來存放你的密匙). 假設如今含密匙的配置文件叫 config.py, 目標文件是 wsgi.py app

這樣的話用 patch 不會起任何做用, 由於在你 patch 的時候, 必需要首先引 入目標文件, 所以目標文件中的import config 會先拋異常. 函數

好吧, 如今咱們必須在引入 wsgi 以前就 patch config. 咱們將直接讓系統的 config 模塊等於 mock 的 config. 這樣再引入 wsgi 就沒有任何問題了. 測試

import sys
config_mock = Mock(spec=['config'])
config_mock.__name__ = 'config'
sys.modules['config'] = config_mock

4 使用 travis ci 持續集成

持續集成最簡單的配置固然是 Travis CI. 只須要 增長配置文件 .travis.yml, 只須要定義4個東西. 下面是個人 .travis.yml

language: python
python:
  - "2.7" # version

install: "pip install -r requirements.txt --use-mirrors"  # requirements

script: nosetests  # test or build command

5 使用 local config 來存放你的密匙

這種方式源於 django. 忽然想到 django 的 settings.py 最後幾行

try:
    from local_settings import *
except:
    pass

意思是從 local_settings 裏的全部設置導入, 所以能夠把真的帶密匙的真是配置 寫到 local_settings 中.

Footnotes:

1

: mock is now part of the python 3 now. Whee…..

相關文章
相關標籤/搜索