簡體   English   中英

單元測試訪問文件的功能

[英]Unit testing functions that access files

我有兩個函數 - 一個用於構建一組文件的路徑,另一個用於讀取文件。 以下是兩個功能:

def pass_file_name(self):
    self.log_files= []
    file_name = self.path+"\\access_"+self.appliacation+".log"
    if os.path.isfile(file_name):
        self.log_files.append(file_name)
    for i in xrange(7):
         file_name = self.path+"\\access_"+self.appliacation+".log"+"."+str(i+1)
         if os.path.isfile(file_name):
            self.log_files.append(file_name)
    return self.log_files


def read_log_files (self, log_file_names): 
    self.log_entrys = []
    self.log_line = []
    for i in log_file_names:
        self.f = open(i)
        for line in self.f:
            self.log_line = line.split(" ")
            #print self.log_line
            self.log_entrys.append(self.log_line)
    return self.log_entrys

對這兩個功能進行單元測試的最佳方法是什么?

你有兩個單位

  • 一個生成文件路徑
  • 第二個讀它們

因此應該有兩個單元測試用例(即帶測試的類)。 首先只測試文件路徑生成。 第二個是測試從您在tests目錄的特殊子目錄中准備的預定義文件集讀取,它應該與第一個測試用例隔離測試。

在您的情況下,您可能會有非常短的日志文件進行測試。 在這種情況下,為了更好的可讀性和維護,最好將它們嵌入測試代碼中。 但在這種情況下,你必須稍微提高你的閱讀功能,這樣它可以采用文件名文件類對象:

from cStringIO import StringIO

# ...
def test_some_log_reading_scenario(self):
    log1 = '\n'.join([
        'log line',
        'another log line'
    ])
    log2 = '\n'.join([
        'another log another line',
        'lala blah blah'
    ])
    # ...
    result = myobj.read_log_files([StringIO(log1), StringIO(log2)])
    # assert result

就個人而言,我會在測試這兩個函數之前構建一個測試工具來設置所需的文件。

對於每個測試用例(你希望文件存在的位置 - 記得也測試失敗的情況!),將一些已知的日志寫入適當命名的文件中; 然后調用測試中的函數並檢查結果。

我不是專家,但我會試一試。 首先進行一些重構:使它們起作用(刪除所有類的東西),刪除不需要的東西。 這應該使測試更容易。 如果你真的想在類中使用它,你總是可以讓類調用這些函數。

def pass_file_name(base_filename, exists):
    """return a list of filenames that exist
       based upon `base_filename`.
       use `os.path.isfile` for `exists`"""

    log_files = []
    if exists(base_filename):
        log_files.append(base_filename)
    for i in range(1, 8):
         filename = base_filename + "." + str(i)
         if exists(filename):
             log_files.append(filename)
    return log_files

def read_log_files (self, log_files):
    """read and parse each line from log_files
       use `pass_file_name` for `log_files`"""

    log_entrys = []
    for filename in log_files:
        with open(filename) as myfile:
            for line in myfile:
                log_entrys.append(line.split())
    return log_entrys

現在,我們可以通過將自定義函數傳遞給exists來輕松測試pass_file_name

class Test_pass_file_name(unittest.TestCase):
    def test_1(self):
        """assume every file exists
           make sure all logs file are there"""
        exists = lambda _: True
        log_files = pass_file_name("a", exists)
        self.assertEqual(log_files,
                    ["a", "a.1", "a.2", "a.3", 
                     "a.4", "a.5", "a.6", "a.7"])

    def test_2(self):
        """assume no files exists
           make sure nothing returned"""
        exists = lambda _: False
        log_files = pass_file_name("a", exists)
        self.assertEqual(log_files, [])

    # ...more tests here ...

正如我們假設os.path.isfile工作,我們應該對第一個函數進行了很好的測試。 雖然您可以始終讓測試實際創建一些文件,然后使用exists = os.path.isfile調用pass_file_name

第二個更難測試; 有人告訴我,最好的(單元)測試不會觸及網絡,數據庫,GUI或硬盤。 所以也許更多的重構會讓它變得更容易。 嘲笑可以奏效; 或者實際上可以在測試函數中編寫一些長文件並將其讀入。

如何模擬with語句中使用的open(使用Python中的Mock框架)?

將模塊中的open名稱綁定到模擬文件打開的函數。

暫無
暫無

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

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