2017-10-08 30 views
7

Tôi có một định dạng kho lưu trữ độc quyền và tôi đang cố gắng phát triển một mô-đun Python để xử lý các kho lưu trữ này. Định dạng repo đi như sau:Làm thế nào để giả lập os.listdir để giả vờ các tập tin và thư mục bằng Python?

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

Ở đây, X là một dự án. alphabeta là các thư mục bên trong dự án này và chúng đại diện cho nhóm trong dự án này. Một nhóm là một vùng chứa trong repo này và những gì nó đại diện thực sự không liên quan cho câu hỏi này. Repo X cũng có các tệp ở cấp cơ sở của nó; project.conf là một ví dụ về tệp như vậy.

Tôi có một lớp được gọi là Project tóm tắt các dự án như X. Lớp Project có phương thức load() để xây dựng biểu diễn trong bộ nhớ.

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 ... 

Để kiểm tra đơn vị sự load() phương pháp chế giễu hệ thống tập tin, tôi có:

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) 

này làm giả os.listdir thành công. Nhưng tôi không thể lừa Python để xử lý mocked_listdir.return_value như bao gồm các tập tin và thư mục.

Làm thế nào để chế nhạo hoặc os.listdir hoặc os.path.isdir, trong cùng thử nghiệm, như vậy mà các bài kiểm tra sẽ thấy alphabeta như danh bạ và project.conf như một tập tin?

+0

Không có gì bạn làm với 'os.listdir' sẽ làm cho các chức năng khác nghĩ rằng những tên đó là các tập tin và thư mục thực. 'os.listdir' chỉ nhổ ra một loạt tên. – user2357112

+0

Tôi đồng ý với những gì @ user2357112 nói. Bạn có alpha & beta làm thư mục trong dự án không? Nếu vậy bạn thực sự không cần phải giả lập 'os.path.isdir'. –

+0

alpha và beta không phải là một phần của dự án.Chúng là những thư mục giả để giải thích cấu trúc của kho lưu trữ được xử lý bởi dự án này. – Upendra

Trả lời

2

Tôi đã đạt được hành vi mong muốn bằng cách chuyển một thuộc tính side_effect chế nhạo isdir đối tượng.

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) 

Khóa là mocked_isdir.side_effect = [True, True, False]. Các giá trị boolean trong iterable phải khớp với thứ tự của các mục nhập thư mục và tệp được chuyển đến thuộc tính mocked_listdir.return_value.

0

Tất nhiên, điều này phụ thuộc vào các chức năng của os mà bạn sử dụng, nhưng có vẻ như mock.patch.multiple trên os chỉ là những gì bạn cần. (Lưu ý rằng bạn có thể không cần phải vá lỗi path; nhiều chức năng của nó chỉ mang tính từ vựng và không quan tâm đến tệp thực tế.)

7

Bạn có thể sử dụng pyfakefs, đó là một lib rất tiện dụng để kiểm tra hoạt động trên hệ thống tệp giả.

nếu bạn sử dụng pytest, nó có một plugin, tất cả các chức năng hệ thống tập tin đã bị vá, bạn chỉ cần sử dụng fs cố định của nó:

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'] 

hoặc nếu bạn thích 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() 
Các vấn đề liên quan