2017-10-08 1 views
7

나는 독점적 인 저장소 형식을 가지고 있으며이 저장소를 처리 할 Python 모듈을 개발하려고합니다. Repo 형식은 다음과 같습니다.os.listdir을 조롱하여 파이썬에서 파일과 디렉토리를 가장하는 방법은 무엇입니까?

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

여기에서 X은 프로젝트입니다. alphabeta은이 프로젝트의 폴더이며이 프로젝트에서는 그룹을 나타냅니다. A 그룹은이 레포의 컨테이너이며, 실제로이 질문과 관련이 없습니다. repo X에도 루트 수준의 파일이 있습니다. project.conf은 이러한 파일의 예입니다.

X과 같은 프로젝트를 추상화하는 Project 클래스가 있습니다. 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 않습니다. 하지만 파이썬이 파일과 디렉토리로 구성된 mocked_listdir.return_value을 취급하도록 속일 수는 없습니다.

어떻게 테스트 파일로 alphabeta 디렉토리 등과 project.conf을 볼 수 있도록, 동일한 테스트에서 하나 os.listdir 또는 os.path.isdir, 조롱합니까?

+0

을 'os.listdir'에 할 일이 없으면 다른 함수가 그 이름이 실제 파일과 디렉토리라고 생각하게 만들 것입니다. 'os.listdir'은 많은 이름을 뱉어냅니다. – user2357112

+0

나는 @ user2357112가 말한 것에 동의한다. 프로젝트의 디렉토리로 알파와 베타를 갖고 있습니까? 그렇다면'os.path.isdir'을 조롱 할 필요가 없습니다. –

+0

알파와 베타는 프로젝트의 일부가 아닙니다.이 디렉토리는이 프로젝트가 처리하는 저장소의 구조를 설명하는 더미 디렉토리입니다. – Upendra

답변

2

반복자를 side_effect 속성에 전달하여 원하는 동작을 달성 할 수있었습니다. 조롱 된 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.multiple (os)이 필요한 것일뿐입니다. (path에 패치 할 필요는 없으며 대부분의 기능은 어휘 전용이며 실제 파일 시스템에 대해서는 신경 쓰지 않습니다.)

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()