2016-01-07 25 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()