[英]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或硬盤。 所以也許更多的重構會讓它變得更容易。 嘲笑可以奏效; 或者實際上可以在測試函數中編寫一些長文件並將其讀入。
將模塊中的open
名稱綁定到模擬文件打開的函數。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.