2016-01-07 24 views
1

我寫我的第一個Python包測試裝飾和我想寫以下裝飾單元測試:如何在Python包

class MaxTriesExceededError(Exception): 
    pass 

def tries(max_tries=3, error_message=os.strerror(errno.ETIME)): 
    def decorator(func): 
     try_count = 0 
     def wrapper(*args, **kwargs): 
      try_count+=1 
      try: 
       if try_count <= max_tries: 
        result = func(*args,**kwargs) 
        return result 
       else: 
        raise MaxTriesExceededError(error_message) 
      except: 
       if try_count <= max_tries: 
        wrapper(*args,**kwargs) 
       else: 
        raise Exception 

     return wraps(func)(wrapper) 

    return decorator 

裝飾的目的是拋出,如果出現錯誤函數的失敗次數超過max_tries,但是如果沒有超過最大嘗試次數,請嘗試重試並重試。說實話,我不確定代碼沒有錯誤。因此我的問題是雙重的,代碼是否正確,以及如何使用unittest爲它編寫單元測試?

+0

你應該確切指定*要在功能測試什麼:它究竟重試N次?只有在發生特定故障時才重試?如果失敗,它會引發特定的異常?你應該爲每個測試編寫一個單元測試,因此,你需要決定你想要的所有測試。 – shx2

回答

4

這裏是一個修正版本,單元測試:

class MaxTriesExceededError(Exception): 
    pass 

def tries(max_tries=3, error_message="failure"): 
    def decorator(func): 
     def wrapper(*args, **kwargs): 
      for try_count in range(max_tries): 
       try: 
       return func(*args,**kwargs) 
       except: 
       pass 
      raise MaxTriesExceededError(error_message) 
     return wrapper 
    return decorator 


import unittest 

class TestDecorator(unittest.TestCase): 

    def setUp(self): 
     self.count = 0 

    def test_success_single_try(self): 
     @tries(1) 
     def a(): 
      self.count += 1 
      return "expected_result" 
     self.assertEqual(a(), "expected_result") 
     self.assertEqual(self.count, 1) 

    def test_success_two_tries(self): 
     @tries(2) 
     def a(): 
      self.count += 1 
      return "expected_result" 
     self.assertEqual(a(), "expected_result") 
     self.assertEqual(self.count, 1) 

    def test_failure_two_tries(self): 
     @tries(2) 
     def a(): 
      self.count += 1 
      raise Exception() 
     try: 
     a() 
     self.fail() 
     except MaxTriesExceededError: 
     self.assertEqual(self.count,2) 

    def test_success_after_third_try(self): 
     @tries(5) 
     def a(): 
      self.count += 1 
      if self.count==3: 
      return "expected_result" 
      else: 
      raise Exception() 
     self.assertEqual(a(), "expected_result") 
     self.assertEqual(self.count, 3) 

if __name__ == '__main__': 
    unittest.main()