簡體   English   中英

單元測試文件修改

[英]Unit Testing File Modifications

我最近一直在研究的程序中的一個常見任務是以某種方式修改文本文件。 (嘿,我在Linux上。一切都是文件。我做大規模的系統管理員。)

但是代碼修改的文件可能不存在於我的桌面盒上。 如果它在我的桌面上,我可能不想修改它。

我已經閱讀了Dive Into Python中的單元測試,並且在測試將十進制轉換為羅馬數字的應用程序(DintoP中的示例)時,我非常清楚我想要做什么。 測試非常獨立。 您無需驗證程序PRINTS是否正確,您只需要驗證函數是否將正確的輸出返回給定輸入。

但是,在我的情況下,我們需要測試程序是否正確地修改了它的環境。 這是我想出的:

1)在標准位置創建“原始”文件,可能是/ tmp。

2)運行修改文件的函數,將路徑傳遞給/ tmp中的文件。

3)驗證/ tmp中的文件是否正確更改; 相應的通過/失敗單元測試。

這對我來說似乎很狡猾。 (如果你想驗證文件的備份副本是否正確創建等,甚至可以獲得kludgier。)有沒有人想出更好的方法?

你說的是一次測試太多了。 如果您開始嘗試通過說“讓我們驗證它正確地修改其環境”來攻擊測試問題,那么您注定要失敗。 環境有數十種甚至數百種可能的變化。

相反,請查看程序的各個部分(“單位”)。 例如,您是否有一個確定必須寫入文件的位置的函數? 該功能的輸入是什么? 也許是一個環境變量,也許從配置文件中讀取一些值? 測試該功能,並不實際做任何修改文件系統的事情。 不要傳遞“現實”值,傳遞易於驗證的值。 創建一個臨時目錄,用test的setUp方法中的文件填充它。

然后測試寫入文件的代碼。 只要確保它正在編寫正確的內容文件內容。 甚至不寫入真正的文件系統! 你不需要為此制作“假的”文件對象,只需使用Python的方便的StringIO模塊; 它們是“文件”界面的“真實”實現,它們不是您的程序實際要寫入的那些。

最終,您將不得不測試最終的,實際上是實際連接的頂級函數,它傳遞真實的環境變量和真實的配置文件並將所有內容放在一起。 但是不要擔心要開始。 首先,當您為較小的函數編寫單獨的測試時,您將開始學習技巧,並且創建測試模擬,假貨和存根將成為您的第二天性。 另一方面:即使你不能完全弄清楚如何測試一個函數調用,你也會非常自信地認為它調用的所有東西都能完美運行。 此外,您會注意到測試驅動的開發會迫使您使API更清晰,更靈活。 例如:測試在某個抽象的對象上調用open()方法的東西os.open在傳遞它的字符串上測試os.open東西要os.open open方法靈活; 它可以是偽造的,它可以以不同的方式實現,但字符串是一個字符串, os.open不會給你任何余地來捕捉它上面調用的方法。

您還可以構建測試工具,以便輕松完成重復性任務。 例如,twisted提供了用於創建臨時文件的工具,用於在其測試工具中內置的測試 使用自己的測試庫測試工具或更大的項目來獲得這樣的功能並不罕見。

你有兩個級別的測試。

  1. 過濾和修改內容。 這些是“低級”操作,實際上並不需要物理文件I / O. 這些是測試,決策,替代等。應用程序的“邏輯”。

  2. 文件系統操作。 創建,復制,重命名,刪除,備份。 抱歉,這些都是正確的文件系統操作 - 很好 - 需要一個適當的文件系統進行測試。

對於這種測試,我們經常使用“模擬”對象。 您可以設計一個“FileSystemOperations”類,它包含各種文件系統操作。 你測試它以確保它做基本的讀,寫,復制,重命名等。這里沒有真正的邏輯。 只是調用文件系統操作的方法。

然后,您可以創建一個模擬各種操作的MockFileSystem。 您可以使用此Mock對象來測試其他類。

在某些情況下,所有文件系統操作都在os模塊中。 如果是這種情況,您可以創建一個MockOS模塊,其中包含您實際使用的操作的模擬版本。

將MockOS模塊放在PYTHONPATH ,您可以隱藏真實的OS模塊。

對於生產操作,您可以使用經過良好測試的“邏輯”類和FileSystemOperations類(或真正的OS模塊)。

對於后來只想要一種方法來測試代碼寫入文件的讀者是否正常工作,這里有一個“fake_open”,用於修補模塊的開放內置以使用StringIO。 fake_open返回打開文件的dict,可以在單元測試或doctest中檢查,所有這些都不需要真正的文件系統。

def fake_open(module):
    """Patch module's `open` builtin so that it returns StringIOs instead of
    creating real files, which is useful for testing. Returns a dict that maps
    opened file names to StringIO objects."""
    from contextlib import closing
    from StringIO import StringIO
    streams = {}
    def fakeopen(filename,mode):
        stream = StringIO()
        stream.close = lambda: None
        streams[filename] = stream
        return closing(stream)
    module.open = fakeopen
    return streams

當我在我的代碼中觸摸文件時,我傾向於模擬文件的實際讀取和寫入...因此,我可以在測試中為我的類提供我想要的確切內容,然后聲明測試正在寫回我希望的內容。

我在Java中完成了這個,我想它在Python中非常簡單......但它可能需要設計你的類/函數,以便模擬實際文件的使用是很容易的。

為此,您可以嘗試傳入流,然后只傳入一個不會寫入文件的簡單字符串輸入/輸出流,或者具有實際“將此字符串寫入文件”或“讀取此內容”的函數來自文件的字符串“,然后在測試中替換該函數。

我認為你走在正確的軌道上。 根據您的需要, chroot可以幫助您為您的scrpits設置一個“看起來”真實的環境,但不是。

如果這不起作用,那么您可以編寫腳本以將“根”路徑作為參數。

在生產運行中,根路徑只是/。 為了測試,在/ tmp / test下創建一個陰影環境,然后使用/ tmp / test的根路徑運行腳本。

您可能想要設置測試以便它在chroot jail中運行,因此您擁有測試所需的所有環境,即使路徑和文件位置在代碼中是硬編碼的[這不是一個很好的做法,但有時會得到文件來自其他地方的位置...]然后通過退出代碼檢查結果。

暫無
暫無

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

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