簡體   English   中英

如何在python中模擬/單元測試以下代碼?

[英]How to mock / unit test following code in python?

我如何對以下單元進行單元測試?

def sigterm_handler(signum, frame):
    pid = os.getpid()  # type: int
    sys.exit(0)

signal.signal(signal.SIGTERM, sigterm_handler)

我應該嘲笑並確保調用mock嗎?

我會寫一個測試,在子進程中運行你的代碼,可以檢查你是否成功終止。

例如,假設您的問題代碼位於名為signals.py的模塊中。 您可以編寫一個如下所示的測試包裝器模塊:

test_signals_wrapper.py

from time import sleep
from sys import exit

# import this last to ensure it overrides any prior settings
import signals

while True:
    sleep(1)

exit(1)  # just in case the loop ends for other reasons

現在你可以編寫一個如下所示的單元測試:

test_signals.py

from subprocess import run, TimeoutExpired
from sys import executable

def test_sigterm_handler():
    try:
        status = run([executable, '-m', 'test_signals_wrapper'], timeout=30)
    except TimeoutExpired:
        assert False, 'Did not trigger assertion in 30 seconds'

    assert status.returncode == 0, f'Wrong return code: {status.returncode}'

這需要為您的測試提供一些額外的基礎架構,但它解決了測試此代碼時的所有問題。 通過在子sys.exit運行,您可以自由執行sys.exit並獲取返回值。 通過使用包裝器腳本,您可以控制代碼的加載和運行方式。 您不需要模擬任何東西,只需確保您的軟件包設置正確,並且您的測試運行器不會嘗試將包裝器腳本作為測試。

猴子修補處理程序並在測試時發送信號?

import os
import signal
import sys
import time

# your handler
def sigterm_handler(signum, frame):
    print("Handled")
    pid = os.getpid()  # type: int  FIXME: what's this for?
    sys.exit(0)

signal.signal(signal.SIGTERM, sigterm_handler)

# Mock out the existing sigterm_handler
_handled = False
def mocked_sigterm_handler(signum, frame):
    print("Mocked")
    _handled = True

# register the handler
signal.signal(signal.SIGTERM, mocked_sigterm_handler)

# test sending the signal
os.kill(os.getpid(), signal.SIGTERM)
print(f"done ({_handled})")

# reset your handler?
signal.signal(signal.SIGTERM, sigterm_handler)

如果你想測試你自己的處理程序,你可能不得不把這樣的代碼放在這個不太漂亮的處理程序中。

if _unittesting_sigterm_handler:
    _handled = True
else:
    sys.exit(0)

然后你可以直接調用處理程序(或在調用中傳遞測試標志)。

_unittesting_sigterm_handler = True
sigterm_handler(0, None)

您顯示的代碼行不適合進行單元測試,但應該進行集成測試。 原因是,您的代碼行僅包含與其他組件的交互(在本例中為signalsysos模塊)。

因此,您可能遇到的錯誤在於與這些其他組件的交互:您是否使用正確順序的參數的正確值調用正確的組件中的正確函數,並且是您期望它們的結果/反應是?

所有這些問題都無法在單元測試中得到解答,在單元測試中可以找到可以在隔離單元中找到的錯誤:如果你模擬signalsys和/或os依賴關系,那么你將編寫你的模擬,以便它們反映您對這些組件的(可能是錯誤的)理解。 因此,單元測試將成功,盡管集成系統中的代碼可能會失敗。 如果您的意圖是代碼在不同的系統上運行,您甚至可能會遇到代碼在一個集成(可能是Linux)中工作但在另一個集成中失敗的情況(可能是Windows)。

因此,對於像您這樣的代碼,單元測試和單元測試的模擬沒有多大價值。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM