python这10个接口自动化的装饰器

在Python接口自动化测试中,装饰器可以用于增强测试函数的功能或改变其行为。以下是一些可能使用的装饰器示例:

设置和清理环境

@setup:用于在测试开始前初始化环境或配置。

复制代码
  1. class CustomTestRunner:

  2. def __init__(self):

  3. self.setup_done = False

  4. def setup(self):

  5. print("Setting up environment...")

  6. # 初始化环境或配置的代码...

  7. self.setup_done = True

  8. def teardown(self):

  9. if self.setup_done:

  10. print("Tearing down environment...")

  11. # 清理环境或资源的代码...

  12. def setup(func):

  13. def wrapper(test_runner, *args, **kwargs):

  14. if not test_runner.setup_done:

  15. test_runner.setup()

  16. return func(test_runner, *args, **kwargs)

  17. return wrapper

  18. class MyTestCase:

  19. def __init__(self):

  20. self.test_runner = CustomTestRunner()

  21. @setup

  22. def test_my_api(self):

  23. assert self.test_runner.setup_done, "Setup should have been called"

  24. # 实现你的接口测试代码...

  25. # 使用示例

  26. test_case = MyTestCase()

  27. test_case.test_my_api()

在这个例子中,我们创建了一个名为CustomTestRunner的类,其中包含了一个setup方法用于初始化环境或配置。我们还定义了一个名为setup的装饰器,它会在调用被装饰的测试函数之前检查是否已经完成了设置,并在必要时调用setup方法。

在MyTestCase类中,我们使用@setup装饰器装饰了test_my_api方法。当我们创建一个MyTestCase实例并调用其test_my_api方法时,装饰器会确保在测试开始前调用了setup方法。

请注意,这个示例使用了一个自定义的测试运行器类(CustomTestRunner)和装饰器(@setup)。在实际项目中,你可能需要根据所使用的测试框架(如unittest、pytest等)来调整实现方式。例如,在unittest框架中,可以使用setUp和tearDown方法代替自定义的setup和teardown方法。

@teardown:用于在测试结束后清理环境或资源。

复制代码
  1. class CustomTestRunner:

  2. def __init__(self):

  3. self.setup_done = False

  4. def setup(self):

  5. print("Setting up environment...")

  6. # 初始化环境或配置的代码...

  7. self.setup_done = True

  8. def teardown(self):

  9. if self.setup_done:

  10. print("Tearing down environment...")

  11. # 清理环境或资源的代码...

  12. def teardown(func):

  13. def wrapper(test_runner, *args, **kwargs):

  14. result = func(test_runner, *args, **kwargs)

  15. test_runner.teardown()

  16. return result

  17. return wrapper

  18. class MyTestCase:

  19. def __init__(self):

  20. self.test_runner = CustomTestRunner()

  21. @teardown

  22. def test_my_api(self):

  23. assert self.test_runner.setup_done, "Setup should have been called"

  24. # 实现你的接口测试代码...

  25. # 使用示例

  26. test_case = MyTestCase()

  27. test_case.test_my_api()

在这个例子中,我们创建了一个名为CustomTestRunner的类,其中包含了一个teardown方法用于清理环境或资源。我们还定义了一个名为teardown的装饰器,它会在被装饰的测试函数执行完毕后调用teardown方法。

在MyTestCase类中,我们使用@teardown装饰器装饰了test_my_api方法。当我们创建一个MyTestCase实例并调用其test_my_api方法时,装饰器会确保在测试结束后调用了teardown方法。

请注意,这个示例使用了一个自定义的测试运行器类(CustomTestRunner)和装饰器(@teardown)。在实际项目中,你可能需要根据所使用的测试框架(如unittest、pytest等)来调整实现方式。例如,在unittest框架中,可以使用setUp和tearDown方法代替自定义的setup和teardown方法。在pytest框架中,可以使用yield语句和fixture功能来实现类似的效果。

数据驱动测试

使用ddt库提供的装饰器,如@data、@unpack等,来实现数据驱动的测试。

@data和@unpack是ddt(Data-Driven Tests)库提供的装饰器,用于实现数据驱动的测试。以下是一个使用@data和@unpack装饰器的示例:

首先,确保已经安装了ddt库:

复制代码
pip install ddt

然后,可以使用以下代码示例:

复制代码
  1. from ddt import ddt, data, unpack

  2. import unittest

  3. import requests

  4. class MyTestCase(unittest.TestCase):

  5. @classmethod

  6. def setUpClass(cls):

  7. cls.base_url = "http://example.com/api"

  8. @data(

  9. ("Alice", "password123", 200),

  10. ("Bob", "invalid_password", 401),

  11. ("", "", 400),

  12. (None, None, 400),

  13. )

  14. @unpack

  15. def test_login(self, username, password, expected_status_code):

  16. url = f"{self.base_url}/login"

  17. payload = {"username": username, "password": password}

  18. response = requests.post(url, json=payload)

  19. self.assertEqual(response.status_code, expected_status_code)

  20. if __name__ == "__main__":

  21. unittest.main()

在这个例子中:

我们使用@data装饰器定义了一个包含多个测试数据集的元组列表。每个元组代表一个特定的测试场景,包括用户名、密码和预期的HTTP状态码。

使用@unpack装饰器,我们可以将元组中的值直接解包并作为测试函数的参数。这样在测试函数内部,我们就可以直接使用这些变量名,而不需要通过索引来访问它们。

在test_login方法中,我们根据提供的用户名、密码和预期状态码发送登录请求,并验证响应的状态码是否与预期相符。

通过这种方式,我们可以使用@data和@unpack装饰器轻松地为同一个测试函数定义多个不同的测试场景,从而提高测试覆盖率和代码的可读性。

性能测试

@timer:测量测试函数的执行时间。

复制代码
  1. import time

  2. def timer(func):

  3. def wrapper(*args, **kwargs):

  4. start_time = time.time()

  5. result = func(*args, **kwargs)

  6. end_time = time.time()

  7. print(f"{func.__name__} executed in {end_time - start_time:.6f} seconds")

  8. return result

  9. return wrapper

  10. class MyTestCase(unittest.TestCase):

  11. @timer

  12. def test_my_api(self):

  13. # 实现你的接口测试代码...

  14. time.sleep(2) # 模拟耗时操作

  15. if __name__ == "__main__":

  16. unittest.main()

在这个例子中:

我们定义了一个名为timer的装饰器,它接受一个函数作为参数,并返回一个新的函数(即wrapper)。

在wrapper函数内部,我们首先记录开始时间,然后调用原始函数并获取其结果,最后记录结束时间。

我们计算并打印出被装饰的函数的执行时间。

在MyTestCase类中,我们使用@timer装饰器装饰了test_my_api方法。当我们运行这个测试用例时,装饰器会测量并打印出该方法的执行时间。

请注意,这个timer装饰器只是一个简单的示例,实际使用中可能需要根据具体需求进行调整。例如,你可能希望将执行时间记录到日志文件中,或者在测试报告中包含执行时间信息等。

@profile(使用cProfile库):进行CPU性能分析。

以下是一个使用@profile装饰器(配合cProfile库)进行CPU性能分析的简单示例:

首先,确保已经安装了cProfile库:

复制代码
pip install cProfile

然后,可以使用以下代码示例:

复制代码
  1. import cProfile

  2. from pstats import Stats

  3. import unittest

  4. import requests

  5. class MyTestCase(unittest.TestCase):

  6. @classmethod

  7. def setUpClass(cls):

  8. cls.base_url = "http://example.com/api"

  9. @profile

  10. def test_my_api(self):

  11. url = f"{self.base_url}/resource"

  12. response = requests.get(url)

  13. self.assertEqual(response.status_code, 200)

  14. if __name__ == "__main__":

  15. profiler = cProfile.Profile()

  16. test_case = MyTestCase()

  17. test_case.test_my_api()

  18. profiler.create_stats()

  19. stats = Stats(profiler)

  20. stats.sort_stats('cumulative')

  21. stats.print_stats()

在这个例子中:

我们使用@profile装饰器装饰了test_my_api方法。当运行这个测试用例时,cProfile库会记录该方法的CPU性能数据。

在测试用例执行完毕后,我们创建了一个Stats对象,并将Profiler的统计数据传递给它。

我们调用sort_stats方法对统计数据进行排序。在这个例子中,我们选择了按累计时间排序。

最后,我们调用print_stats方法打印出性能分析结果。

请注意,这个示例只是一个基本的使用方式,实际使用中可能需要根据具体需求进行调整。例如,你可能希望将性能分析结果保存到文件中,或者使用更复杂的统计和过滤选项等。另外,cProfile库主要用于CPU性能分析,如果你需要进行内存或其他资源的性能分析,可能需要使用其他工具或库。

日志记录

@log_test:记录测试的开始和结束,以及测试结果。

复制代码
  1. import unittest

  2. class TestLogger:

  3. def log_start(self, test_name):

  4. print(f"Starting test: {test_name}")

  5. def log_end(self, test_name, result):

  6. print(f"Ending test: {test_name}")

  7. if result:

  8. print("Test passed.")

  9. else:

  10. print("Test failed.")

  11. def log_test(func):

  12. def wrapper(test_logger, *args, **kwargs):

  13. test_name = func.__name__

  14. test_logger.log_start(test_name)

  15. result = func(test_logger, *args, **kwargs)

  16. test_logger.log_end(test_name, result)

  17. return result

  18. return wrapper

  19. class MyTestCase(unittest.TestCase):

  20. @classmethod

  21. def setUpClass(cls):

  22. cls.test_logger = TestLogger()

  23. @log_test

  24. def test_my_api(self, test_logger):

  25. url = "http://example.com/api"

  26. response = requests.get(url)

  27. self.assertEqual(response.status_code, 200)

  28. if __name__ == "__main__":

  29. unittest.main()

在这个例子中:

我们定义了一个名为TestLogger的类,它包含两个方法:log_start和log_end,分别用于记录测试的开始和结束,以及测试结果。

我们定义了一个名为log_test的装饰器,它接受一个函数作为参数,并返回一个新的函数(即wrapper)。

在wrapper函数内部,我们首先获取被装饰的函数名,然后调用log_start方法记录测试的开始。

我们调用原始函数并获取其结果。

我们调用log_end方法记录测试的结束,并传递测试结果。

在MyTestCase类中,我们创建了一个TestLogger实例,并在setUpClass方法中设置为类变量。

我们使用@log_test装饰器装饰了test_my_api方法。当我们运行这个测试用例时,装饰器会记录测试的开始和结束,以及测试结果。

请注意,这个log_test装饰器只是一个简单的示例,实际使用中可能需要根据具体需求进行调整。例如,你可能希望将日志信息写入文件,或者使用更复杂的日志格式和级别等。另外,这个示例中的日志输出是简单的文本形式,如果你需要更丰富的日志功能,可以考虑使用Python的logging模块。

异常处理

@catch_exceptions:捕获并处理测试函数中可能抛出的异常。

复制代码
  1. import unittest

  2. def catch_exceptions(func):

  3. def wrapper(*args, **kwargs):

  4. try:

  5. return func(*args, **kwargs)

  6. except Exception as e:

  7. print(f"Exception caught during test: {e}")

  8. return False

  9. return wrapper

  10. class MyTestCase(unittest.TestCase):

  11. @classmethod

  12. def setUpClass(cls):

  13. cls.base_url = "http://example.com/api"

  14. @catch_exceptions

  15. def test_my_api(self):

  16. url = f"{self.base_url}/resource"

  17. response = requests.get(url)

  18. self.assertEqual(response.status_code, 200)

  19. if __name__ == "__main__":

  20. unittest.main()

'

运行

运行

在这个例子中:

我们定义了一个名为catch_exceptions的装饰器,它接受一个函数作为参数,并返回一个新的函数(即wrapper)。

在wrapper函数内部,我们使用try-except语句包裹原始函数的调用。如果在执行原始函数时抛出了异常,我们将捕获这个异常,并打印出异常信息。

如果捕获到异常,我们返回False,表示测试失败。否则,我们返回原始函数的返回值。

在MyTestCase类中,我们使用@catch_exceptions装饰器装饰了test_my_api方法。当我们运行这个测试用例时,装饰器会捕获并处理该方法中可能抛出的异常。

请注意,这个catch_exceptions装饰器只是一个简单的示例,实际使用中可能需要根据具体需求进行调整。例如,你可能希望对不同类型的异常进行不同的处理,或者在捕获异常后执行一些清理操作等。另外,虽然这个装饰器可以帮助我们在测试函数中捕获和处理异常,但在编写测试代码时,通常建议明确预期可能会抛出的异常,并使用assertRaises等断言来验证它们。这样可以提供更清晰的测试意图和更好的错误消息。

重试机制

@retry:在测试失败时自动重试指定次数。

复制代码
  1. import unittest

  2. def retry(attempts=3, delay=1):

  3. def decorator(func):

  4. def wrapper(*args, **kwargs):

  5. for i in range(attempts):

  6. try:

  7. return func(*args, **kwargs)

  8. except Exception as e:

  9. print(f"Test failed on attempt {i + 1}: {e}")

  10. if i < attempts - 1:

  11. time.sleep(delay)

  12. raise Exception(f"Test failed after {attempts} attempts")

  13. return wrapper

  14. return decorator

  15. class MyTestCase(unittest.TestCase):

  16. @classmethod

  17. def setUpClass(cls):

  18. cls.base_url = "http://example.com/api"

  19. @retry(attempts=3, delay=2)

  20. def test_my_api(self):

  21. url = f"{self.base_url}/resource"

  22. response = requests.get(url)

  23. self.assertEqual(response.status_code, 200)

  24. if __name__ == "__main__":

  25. unittest.main()

在这个例子中:

我们定义了一个名为retry的装饰器,它接受两个可选参数:attempts(重试次数,默认为3)和delay(每次重试之间的延迟时间,默认为1秒)。

retry装饰器内部定义了一个新的装饰器函数(即decorator),它接受一个函数作为参数,并返回一个新的函数(即wrapper)。

在wrapper函数内部,我们使用一个循环来尝试调用原始函数。如果在执行原始函数时抛出了异常,我们将捕获这个异常,并打印出异常信息。

如果捕获到异常并且还有剩余的重试次数,我们将暂停一段时间(由delay参数指定),然后再次尝试调用原始函数。

如果所有重试都失败了,我们将重新抛出最后一个捕获到的异常。

在MyTestCase类中,我们使用@retry装饰器装饰了test_my_api方法,并指定了重试次数和延迟时间。当我们运行这个测试用例时,装饰器会自动重试该方法,直到成功或达到最大重试次数。

请注意,这个retry装饰器只是一个简单的示例,实际使用中可能需要根据具体需求进行调整。例如,你可能希望对不同类型的异常进行不同的重试策略,或者在重试之间执行一些清理操作等。另外,虽然重试机制可以在某些情况下帮助处理临时性故障,但过度依赖重试可能会掩盖系统中的根本问题。因此,在使用重试机制时应谨慎考虑其适用性和可能的副作用。

权限和认证

@with_auth:为测试函数添加特定的认证信息或权限。

复制代码
  1. import unittest

  2. class AuthManager:

  3. def __init__(self, username, password):

  4. self.username = username

  5. self.password = password

  6. def authenticate(self):

  7. # 这里是实际的认证逻辑,例如发送HTTP请求获取访问令牌等

  8. pass

  9. def with_auth(username, password):

  10. def decorator(func):

  11. def wrapper(*args, **kwargs):

  12. auth_manager = AuthManager(username, password)

  13. auth_manager.authenticate()

  14. return func(auth_manager, *args, **kwargs)

  15. return wrapper

  16. return decorator

  17. class MyTestCase(unittest.TestCase):

  18. @classmethod

  19. def setUpClass(cls):

  20. cls.base_url = "http://example.com/api"

  21. @with_auth("test_user", "test_password")

  22. def test_my_api(self, auth_manager):

  23. url = f"{self.base_url}/resource"

  24. headers = {"Authorization": auth_manager.access_token} # 假设auth_manager对象有一个access_token属性

  25. response = requests.get(url, headers=headers)

  26. self.assertEqual(response.status_code, 200)

  27. if __name__ == "__main__":

  28. unittest.main()

在这个例子中:

我们定义了一个名为AuthManager的类,它用于管理认证信息和执行认证操作。

我们定义了一个名为with_auth的装饰器,它接受两个参数:username和password。

with_auth装饰器内部定义了一个新的装饰器函数(即decorator),它接受一个函数作为参数,并返回一个新的函数(即wrapper)。

在wrapper函数内部,我们创建了一个AuthManager实例,并使用提供的用户名和密码进行初始化。

我们调用authenticate方法对AuthManager实例进行认证。

我们将认证后的AuthManager实例传递给原始函数,并返回其结果。

在MyTestCase类中,我们使用@with_auth装饰器装饰了test_my_api方法,并提供了用户名和密码。当我们运行这个测试用例时,装饰器会先执行认证操作,然后将认证后的AuthManager实例传递给test_my_api方法。

请注意,这个with_auth装饰器只是一个简单的示例,实际使用中可能需要根据具体需求进行调整。例如,你可能需要处理更复杂的认证流程,或者支持多种不同的认证方式等。另外,这个示例中的AuthManager类和authenticate方法只是为了演示目的而编写的,实际使用时应替换为实际的认证逻辑和数据。

参数化测试

@parametrize(使用pytest库):为测试函数提供多个参数组合。

以下是一个使用@pytest.mark.parametrize装饰器(来自pytest库)为测试函数提供多个参数组合的简单示例:

首先,确保已经安装了pytest库:

复制代码
pip install pytest

然后,可以使用以下代码示例:

复制代码
  1. import pytest

  2. import requests

  3. class MyTestCase:

  4. @classmethod

  5. def setUpClass(cls):

  6. cls.base_url = "http://example.com/api"

  7. @pytest.mark.parametrize("username, password, expected_status_code", [

  8. ("Alice", "password123", 200),

  9. ("Bob", "invalid_password", 401),

  10. ("", "", 400),

  11. (None, None, 400),

  12. ])

  13. def test_login(self, username, password, expected_status_code):

  14. url = f"{self.base_url}/login"

  15. payload = {"username": username, "password": password}

  16. response = requests.post(url, json=payload)

  17. assert response.status_code == expected_status_code

  18. if __name__ == "__main__":

  19. pytest.main()

在这个例子中:

我们使用@pytest.mark.parametrize装饰器装饰了test_login方法。该装饰器接受两个参数:一个参数名列表和一个参数值列表。

参数名列表包含了被装饰的测试函数期望接收的参数名称。

参数值列表是一个包含多个元组的列表,每个元组代表一组特定的参数值组合。

当我们运行这个测试用例时,pytest会为test_login方法生成多个实例,每个实例使用一组不同的参数值。这样,我们可以用一种简洁的方式为同一个测试函数提供多个不同的输入和预期输出。

请注意,虽然这个例子中我们没有使用unittest.TestCase类,但你可以将这个测试用例与unittest.TestCase结合使用,只需要在测试类中继承unittest.TestCase,并使用unittest的断言方法即可。另外,pytest提供了许多其他功能和装饰器,可以根据需要进行探索和使用。

条件执行

@skip_if:在满足特定条件时跳过测试。

复制代码
  1. import unittest

  2. def skip_if(condition):

  3. def decorator(func):

  4. def wrapper(*args, **kwargs):

  5. if condition:

  6. print(f"Test skipped because condition is satisfied: {condition}")

  7. return

  8. return func(*args, **kwargs)

  9. return wrapper

  10. return decorator

  11. class MyTestCase(unittest.TestCase):

  12. @classmethod

  13. def setUpClass(cls):

  14. cls.base_url = "http://example.com/api"

  15. @skip_if(os.environ.get("SKIP_FLAKY_TESTS", False))

  16. def test_flaky_api(self):

  17. url = f"{self.base_url}/flaky-resource"

  18. response = requests.get(url)

  19. self.assertEqual(response.status_code, 200)

  20. if __name__ == "__main__":

  21. unittest.main()

在这个例子中:

我们定义了一个名为skip_if的装饰器,它接受一个参数:一个表示条件的表达式。

skip_if装饰器内部定义了一个新的装饰器函数(即decorator),它接受一个函数作为参数,并返回一个新的函数(即wrapper)。

在wrapper函数内部,我们检查提供的条件是否为真。如果条件为真,我们将打印一条消息并直接返回,从而跳过测试。否则,我们将调用原始函数并返回其结果。

在MyTestCase类中,我们使用@skip_if装饰器装饰了test_flaky_api方法,并提供了一个条件表达式。这个条件表达式检查环境变量"SKIP_FLAKY_TESTS"是否存在且值为True。如果我们设置了这个环境变量,那么这个测试将被跳过。

请注意,这个skip_if装饰器只是一个简单的示例,实际使用中可能需要根据具体需求进行调整。例如,你可能希望对不同类型的条件使用不同的装饰器,或者在跳过测试时执行一些清理操作等。另外,虽然跳过测试可以在某些情况下避免不必要的失败和复杂性,但过度依赖跳过机制可能会掩盖系统中的问题。因此,在使用跳过机制时应谨慎考虑其适用性和可能的副作用。

@run_only_if:在满足特定条件时执行测试。

复制代码
  1. import unittest

  2. def run_only_if(condition):

  3. def decorator(func):

  4. def wrapper(*args, **kwargs):

  5. if not condition:

  6. print(f"Test skipped because condition is not satisfied: {condition}")

  7. return

  8. return func(*args, **kwargs)

  9. return wrapper

  10. return decorator

  11. class MyTestCase(unittest.TestCase):

  12. @classmethod

  13. def setUpClass(cls):

  14. cls.base_url = "http://example.com/api"

  15. @run_only_if(os.environ.get("RUN_SPECIFIC_TESTS", False))

  16. def test_specific_api(self):

  17. url = f"{self.base_url}/specific-resource"

  18. response = requests.get(url)

  19. self.assertEqual(response.status_code, 200)

  20. if __name__ == "__main__":

  21. unittest.main()

在这个例子中:

我们定义了一个名为run_only_if的装饰器,它接受一个参数:一个表示条件的表达式。

run_only_if装饰器内部定义了一个新的装饰器函数(即decorator),它接受一个函数作为参数,并返回一个新的函数(即wrapper)。

在wrapper函数内部,我们检查提供的条件是否为真。如果条件为假,我们将打印一条消息并直接返回,从而跳过测试。否则,我们将调用原始函数并返回其结果。

在MyTestCase类中,我们使用@run_only_if装饰器装饰了test_specific_api方法,并提供了一个条件表达式。这个条件表达式检查环境变量"RUN_SPECIFIC_TESTS"是否存在且值为True。如果我们设置了这个环境变量,那么这个测试将被执行。

请注意,这个run_only_if装饰器只是一个简单的示例,实际使用中可能需要根据具体需求进行调整。例如,你可能希望对不同类型的条件使用不同的装饰器,或者在执行测试前执行一些初始化操作等。另外,虽然选择性地执行测试可以在某些情况下提高测试效率和针对性,但过度依赖这种机制可能会导致部分测试被忽视或遗漏。因此,在使用run_only_if装饰器时应谨慎考虑其适用性和可能的副作用。

报告和统计

@report_result:自定义测试结果的报告格式或统计数据。

复制代码
  1. import unittest

  2. class CustomTestResult(unittest.TestResult):

  3. def __init__(self):

  4. super().__init__()

  5. self.success_count = 0

  6. self.failure_count = 0

  7. self.error_count = 0

  8. def addSuccess(self, test):

  9. super().addSuccess(test)

  10. self.success_count += 1

  11. def addFailure(self, test, err):

  12. super().addFailure(test, err)

  13. self.failure_count += 1

  14. def addError(self, test, err):

  15. super().addError(test, err)

  16. self.error_count += 1

  17. def report_result(func):

  18. def wrapper(*args, **kwargs):

  19. result = CustomTestResult()

  20. test_method = getattr(args[0], func.__name__)

  21. test_method(result)

  22. print(f"Test results: {result.success_count} successes, {result.failure_count} failures, {result.error_count} errors")

  23. return result

  24. return wrapper

  25. class MyTestCase(unittest.TestCase):

  26. @classmethod

  27. def setUpClass(cls):

  28. cls.base_url = "http://example.com/api"

  29. @report_result

  30. def test_my_api(self, result):

  31. url = f"{self.base_url}/resource"

  32. response = requests.get(url)

  33. self.assertEqual(response.status_code, 200)

  34. if __name__ == "__main__":

  35. suite = unittest.TestLoader().loadTestsFromTestCase(MyTestCase)

  36. runner = unittest.TextTestRunner()

  37. runner.run(suite)

在这个例子中:

我们定义了一个名为CustomTestResult的类,它继承自unittest.TestResult并添加了自定义的计数器属性。

我们重写了addSuccess、addFailure和addError方法,以便在测试成功、失败或出现错误时更新自定义计数器。

我们定义了一个名为report_result的装饰器,它接受一个函数作为参数,并返回一个新的函数(即wrapper)。

在wrapper函数内部,我们创建了一个CustomTestResult实例,并获取被装饰的测试方法。

我们调用测试方法并将CustomTestResult实例传递给它,以便收集测试结果。

我们打印出自定义的测试结果报告,包括成功、失败和错误的数量。

在MyTestCase类中,我们使用@report_result装饰器装饰了test_my_api方法。当我们运行这个测试用例时,装饰器会收集测试结果并打印出自定义的报告。

请注意,这个report_result装饰器只是一个简单的示例,实际使用中可能需要根据具体需求进行调整。例如,你可能希望生成更复杂的报告格式,或者将报告保存到文件或数据库等。另外,虽然这个例子中我们没有直接使用unittest.TextTestRunner来运行测试,但在实际项目中,你可以将自定义的CustomTestResult类与unittest.TextTestRunner结合使用,以实现更灵活的测试报告功能。

感谢每一个认真阅读我文章的人,礼尚往来总是要有的,虽然不是什么很值钱的东西,如果你用得到的话可以直接拿走:

这些资料,对于【软件测试】的朋友来说应该是最全面最完整的备战仓库,这个仓库也陪伴上万个测试工程师们走过最艰难的路程,希望也能帮助到你!有需要的小伙伴可以点击下方小卡片领取

相关推荐
数据智能老司机3 小时前
精通 Python 设计模式——分布式系统模式
python·设计模式·架构
数据智能老司机4 小时前
精通 Python 设计模式——并发与异步模式
python·设计模式·编程语言
数据智能老司机4 小时前
精通 Python 设计模式——测试模式
python·设计模式·架构
数据智能老司机4 小时前
精通 Python 设计模式——性能模式
python·设计模式·架构
c8i5 小时前
drf初步梳理
python·django
每日AI新事件5 小时前
python的异步函数
python
这里有鱼汤6 小时前
miniQMT下载历史行情数据太慢怎么办?一招提速10倍!
前端·python
databook15 小时前
Manim实现脉冲闪烁特效
后端·python·动效
程序设计实验室15 小时前
2025年了,在 Django 之外,Python Web 框架还能怎么选?
python
倔强青铜三17 小时前
苦练Python第46天:文件写入与上下文管理器
人工智能·python·面试