iT邦幫忙

2024 iThome 鐵人賽

DAY 25
0

簡介

當 Product Code 涉及日期或時間邏輯(如定時任務、到期日等)時,通常會依據當前時間進行決策。然而,在撰寫 Test Cdoe 時,開發者經常面臨以下兩個挑戰:

  1. 測試結果的不穩定性
    若不使用工具來凍結或控制時間,時間相關的邏輯測試可能變得不穩定。測試結果可能隨著每次執行的時間不同而發生變化。例如,當系統在不同日期處理相同的業務邏輯時,結果可能會因日期變動而產生偏差,導致測試難以重現。

  2. 依賴實際時間進行測試的耗時
    在測試過程中,如果必須等待實際時間的流逝(例如等待某個定時器或任務觸發),將大大降低測試速度,既浪費時間,又使測試過程更難維護。

本文將介紹一個名為 Freezegun 的套件,它能凍結時間,讓開發者將時間固定在某個特定點上,從而確保時間相關的邏輯如預期般運行,而無需等待實際時間的經過,進一步提升測試的效率和穩定性。接下來,我將透過範例進行說明。

範例

本次範例使用的是 Freezegun 1.5.1 版本

poetry add freezegun==1.5.1

首先,我們將準備一個 Product Code 函式,該函式會根據當前的時間點返回對應的字串。

from datetime import datetime


def get_greeting_based_on_time() -> str:
    now = datetime.now()
    if now.hour < 12:
        return "Good Morning!"
    elif 12 <= now.hour < 18:
        return "Good Afternoon!"
    else:
        return "Good Evening!"

Before Freezegun

首先,讓我們看看尚未使用 Freezegun 的測試代碼版本。
當執行 poetry run pytest 時,由於測試結果依賴於執行的時間點,因此每位讀者可能會得到不同的結果。以筆者為例,我在晚間執行此測試,因此出現了如下錯誤: AssertionError: assert 'Good Evening!' == 'Good Morning!'

def test_get_greeting_based_on_time():
    # Act
    result = get_greeting_based_on_time()

    # Assert
    assert get_greeting_based_on_time == "Good Morning!"

https://ithelp.ithome.com.tw/upload/images/20241008/201686638GsW2LsO1v.png

After Freezegun

我們可以使用 freezegun 套件來凍結時間。只需在需要凍結的測試函式上方添加 freeze_time Decorator,並指定一個特定的時間點。在本次測試中,我選擇將時間凍結在2014年10月8日的早上8點。因此,當執行至函式 get_greeting_based_on_timedatetime.now() 時,返回的物件將是 datetime(2024-10-08 08:00:00),這樣每次測試的結果都將保持一致。

from freezegun import freeze_time


@freeze_time("2024-10-08 08:00:00")
def test_get_greeting_based_on_time():
    # Act
    result = get_greeting_based_on_time()

    # Assert
    assert get_greeting_based_on_time() == "Good Morning!"

https://ithelp.ithome.com.tw/upload/images/20241008/20168663rQ2T9COhQZ.png


上一篇
[Day 24] Pytest
下一篇
[Day 26] Responses
系列文
Python 不止於數據,開發應用程式它也在行!30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言