2010-02-17 42 views
9

我有兩個函數 - 一個是構建一組文件的路徑,另一個是讀取文件的路徑。以下是兩個功能:訪問文件的單元測試函數

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 

單元測試這兩個函數的最佳方法是什麼?

回答

8

你有兩個單位這裏:

  • 一個生成文件路徑
  • 其次,上面寫着他們

因此應該有兩個單元測試情況下(即類測試)。首先將只測試文件路徑生成。其次,將測試從您在測試目錄的特殊子目錄中準備的預定義文件集中的讀取,它應該從第一個測試用例中單獨進行測試。

就你而言,你可能有非常短的日誌文件進行測試。在這種情況下,爲了獲得更好的可讀性和維護性,最好將它們嵌入測試代碼中。但在這種情況下,你必須提高你的閱讀功能了一點,所以它可以採取任意文件名類似文件的對象:

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 
+1

「...所以它可以採用文件名或類似文件的對象」我該怎麼做?檢查str(文件名)的實例,否則假設它是一個IO對象? – Symmitchry

1

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

+0

對不起全新這裏。我該如何去做呢?如嘲笑文件開放? –

+0

編寫一個類文件對象,實現代碼所需的各種'file'方法,然後從'fake_open()'函數返回一個實例。導入模塊然後執行'somemodule。打開= fake_open'。 –

2

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

對於每個測試案例(您希望文件存在的地方 - 記得也要測試失敗案例!),將一些已知的日誌寫入相應的命名文件中;然後調用待測試的函數並檢查結果。

2

我不是專家,但我給它一個去。首先進行一些重構:使其功能化(刪除所有類的東西),刪除不需要的東西。這應該使測試更容易。如果您真的想要在課堂上使用這些功能,您可以隨時讓課程調用這些功能。

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作品中,我們應該已經得到了第一個功能相當不錯的測試。雖然您可以隨時通過測試實際創建一些文件,然後撥打pass_file_name並撥打exists = os.path.isfile

第二個較難測試;我被告知最好的(單元)測試不會觸及網絡,數據庫,GUI或硬盤驅動器。所以也許更多的重構會讓它更容易。嘲笑開放可能會奏效;或將實際上可以寫在測試功能有些長文件和讀取它們。

How do I mock an open used in a with statement (using the Mock framework in Python)?