2010-02-17 7 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

    내가 전문가는 아니지만하지만 한번 풀어주지 . 먼저 약간의 리팩토링 (refactoring) : 기능적으로 (모든 클래스를 제거하고) 불필요한 것들을 제거합니다. 이렇게하면 훨씬 쉽게 테스트 할 수 있습니다. 정말로 클래스에 원한다면 클래스가 항상이 함수를 호출하도록 만들 수 있습니다.

    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을 테스트 할 수 있습니다. 우리가 os.path.isfile 작품을 가정으로

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

    우리는 첫 번째 함수의 꽤 좋은 테스트를 가지고 있어야합니다. 테스트를 실제로 수행 할 수 있지만 실제로 파일을 만들려면 pass_file_nameexists = os.path.isfile으로 호출하십시오.

    두 번째 테스트는 더 어렵습니다. 최고의 (유닛) 테스트가 네트워크, 데이터베이스, GUI 또는 하드 드라이브를 만지지 않는다는 말을 들었습니다. 어쩌면 좀 더 리팩토링하면 더 쉽게 만들 수 있습니다. 열려있는 조롱은 일할 수 있었다; 또는 실제로 테스트 기능의 일부 긴 파일을 작성하고 그들을 읽을 수있다. 완전히 새로운 죄송

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

    관련 문제