2017-10-08 70 views
7

我有一個專有的存儲庫格式,我試圖開發一個Python模塊來處理這些存儲庫。回覆格式如下:如何模擬os.listdir在Python中假裝文件和目錄?

/home/X/ 
     | 
     + alpha/ 
     | 
     + beta/ 
     | 
     + project.conf 

這裏,X是一個項目。 alphabeta是該項目中的文件夾,它們代表在此項目中。 A 是此回購的一個容器,它代表的與這個問題真的不相關。 repo X也有其根級別的文件; project.conf就是這樣一個文件的例子。

我有一個叫Project的類,它抽象出X這樣的項目。 Project類具有構建內存中表示的方法load()

class Project(object): 

    def load(self): 
     for entry in os.listdir(self.root): 
      path = os.path.join(self.root, entry) 
      if os.path.isdir(path): 
       group = Group(path) 
       self.groups.append(group) 
       group.load() 
      else: 
       # process files ... 

單元測試的load()方法通過嘲笑文件系統,我有:

import unittest 
from unittest import mock 
import Project 

class TestRepo(unittest.TestCase): 

    def test_load_project(self): 
     project = Project("X") 

     with mock.patch('os.listdir') as mocked_listdir: 
      mocked_listdir.return_value = ['alpha', 'beta', 'project.conf'] 
      project.load() 
      self.assertEqual(len(project.groups), 2) 

這確實模擬os.listdir成功。但我不能哄騙Python將mocked_listdir.return_value視爲由文件和目錄組成。

如何嘲笑在同一個測試要麼os.listdiros.path.isdir,使得測試將看到alphabeta的目錄和project.conf的文件?

+0

你對'os.listdir'所做的任何事情都不會讓其他函數認爲這些名稱命名爲真實文件和目錄。 'os.listdir'只是吐出一堆名字。 – user2357112

+0

我同意@ user2357112所說的。項目中是否有alpha和beta目錄?如果是這樣,你真的不需要模擬'os.path.isdir'。 –

+0

alpha和beta不是該項目的一部分。它們是虛擬目錄,用於解釋由此項目處理的存儲庫的結構。 – Upendra

回答

2

我設法達到預期的行爲嘲笑isdir對象。

import unittest 
from unittest import mock 
import Project 

class TestRepo(unittest.TestCase): 

    def test_load_project(self): 
     project = Project("X") 

     with mock.patch('os.listdir') as mocked_listdir: 
     with mock.patch('os.path.isdir') as mocked_isdir: 
      mocked_listdir.return_value = ['alpha', 'beta', 'project.conf'] 
      mocked_isdir.side_effect = [True, True, False] 
      project.load() 
      self.assertEqual(len(project.groups), 2) 

關鍵是mocked_isdir.side_effect = [True, True, False]一行。 iterable中的布爾值應該與傳遞給mocked_listdir.return_value屬性的目錄和文件條目的順序匹配。

0

這將取決於,當然,你用到底是哪os的功能,但它看起來像mock.patch.multipleos是你需要的東西。 (請注意,你可能不需要修補path;它的許多功能是詞彙,只和不關心實際filesytem。)通過傳遞一個迭代到的該side_effect屬性

7

您可以使用pyfakefs,這是一個非常方便的測試在假文件系統上運行的庫。

如果使用pytest,它有一個插件,所有的文件系統的功能已經得到了修補,你只需要使用它的fs夾具:

import os 

def test_foo(fs): 
    fs.CreateFile('/home/x/alpha/1') 
    fs.CreateFile('/home/x/beta/2') 
    fs.CreateFile('/home/x/p.conf')  
    assert os.listdir('/home/x/')) == ['alpha', 'beta', 'p.conf'] 

或者如果你喜歡unittest

import os 
import unittest 

from pyfakefs import fake_filesystem_unittest 

class TestRepo(fake_filesystem_unittest.TestCase): 

    def setUp(self): 
     self.setUpPyfakefs() 

    def test_foo(self): 
     os.makedirs('/home/x/alpha') 
     os.makedirs('/home/x/beta') 
     with open('/home/x/p.conf', 'w') as f: 
      f.write('foo') 
     self.assertEqual(os.listdir('/home/x/'), ['alpha', 'beta', 'p.conf']) 


if __name__ == "__main__": 
    unittest.main() 
相關問題