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结合使用,以实现更灵活的测试报告功能。

 

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

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/903707.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【Spring】Cookie与Session

&#x1f490;个人主页&#xff1a;初晴~ &#x1f4da;相关专栏&#xff1a;计算机网络那些事 一、Cookie是什么&#xff1f; Cookie的存在主要是为了解决HTTP协议的无状态性问题&#xff0c;即协议本身无法记住用户之前的操作。 "⽆状态" 的含义指的是: 默认情况…

摄像头点击器常见问题——摄像头视窗打开慢

【嵌入式开发】可编程4k蓝牙摄像头点击器_能编程的摄像头-CSDN博客 拥有上述文章产品的朋友出现标题所述问题&#xff0c;可继续往下阅读 出现以上问题&#xff0c;摄像头画面打开较慢&#xff0c;可以按以下操作进行设置 在环境变量里设置一下这个参数&#xff0c;值设置为1&…

Springboot项目搭建的问题

1.第一次出现这个问题是在使用postgresql进行搭建项目的时候&#xff0c;但是配置文件中的驱动一致导入不了 最后发现是meaven中依赖导入不进来&#xff08;不知道为什么&#xff09;&#xff0c;于是手动的在meaven中央仓库下载了对应的jar进行配置 然后项目可以正常启动 2.…

Java-I/O框架06:常见字符编码、字符流抽象类

视频链接&#xff1a;16.16 字符流抽象类_哔哩哔哩_bilibilihttps://www.bilibili.com/video/BV1Tz4y1X7H7?spm_id_from333.788.videopod.episodes&vd_sourceb5775c3a4ea16a5306db9c7c1c1486b5&p16 1.常见字符编码 IOS-8859-1收录了除ASCII外&#xff0c;还包括西欧…

搜索引擎算法更新对网站优化的影响与应对策略

内容概要 随着互联网的不断发展&#xff0c;搜索引擎算法也在不断地进行更新和优化。了解这些算法更新的背景与意义&#xff0c;对于网站管理者和优化人员而言&#xff0c;具有重要的指导意义。不仅因为算法更新可能影响到网站的排名&#xff0c;还因为这些变化也可能为网站带…

CSS兼容处理

“前端开发兼容——CSS篇” 在前端开发中&#xff0c;CSS样式的兼容性问题常常让开发者感到棘手&#xff0c;尤其是当涉及到IE浏览器时。由于IE浏览器版本繁多&#xff0c;每个版本在CSS支持上还存在差异&#xff0c;这导致开发者在实现统一的视觉效果时&#xff0c;不得不编写…

动态规划之回文串问题

文章目录 回文子串最长回文子串分割回文串 IV分割回文串 II最长回文子序列让字符串成为回文串的最少插入次数 回文子串 题目&#xff1a;回文子串 思路 状态表示&#xff1a;dp[i][j]表示s字符串由i到j是否是回文子串状态转移方程&#xff1a; s[i] ! s[j]&#xff0c;则i到j一…

【HarmonyOS】鸿蒙应用低功耗蓝牙BLE的使用心得 (一)

【HarmonyOS】鸿蒙应用低功耗蓝牙BLE的使用心得&#xff08;一&#xff09; 一、前言 鸿蒙官网文档中蓝牙部分&#xff0c;对于之前没有开发过蓝牙的同学&#xff0c;使用和查阅起来不是很方便。因为只是API的调用说明。并没有蓝牙整个调用流程的讲解&#xff0c;所以看起来会…

一个简单的例子,说明Matrix类的妙用

在Android、前端或者别的平台的软件开发中&#xff0c;有时会遇到类似如下需求&#xff1a; 将某个图片显示到指定的区域&#xff1b;要求不改变图片本身的宽高比&#xff0c;进行缩放&#xff1b;要求最大限度的居中填充到显示区域。 以下示意图可以简单描绘该需求 以Androi…

蚁剑连接本地木马文件报错

项目场景&#xff1a; 本地搭建php和蚁剑环境&#xff0c;连接本地木马文件ma.php 问题描述 使用蚁剑连接localhost时报错 错误{ "address":"127.0.0.1" "code":"ECONNREFUSED", "errno":"ECONNREFUSED", &qu…

网页上的视频怎么下载下来?三种方法

分享三个简单好用的网页视频下载工具&#xff0c;值得使用&#xff01; 1.IDM IDM 是一款可以提高下载速度达5倍的工具&#xff0c;同时具有恢复、调度和组织下载的功能。如果由于网络问题或意外的电源中断&#xff0c;程序将恢复未完成的下载。 IDM 还具有一个完全功能的站点…

使用 FastGPT 工作流实现 AI 赛博算卦,一键生成卦象图

最近那个男人写的汉语新解火遍了全网&#xff0c;那个男人叫李继刚&#xff0c;国内玩 AI 的同学如果不知道这个名字&#xff0c;可以去面壁思过了。 这个汉语新解的神奇之处就在于它只是一段几百字的提示词&#xff0c;效果却顶得上几千行代码写出来的应用程序。 这段提示词…

《虚拟现实的边界:探索虚拟世界的未来可能》

内容概要 在虚拟现实&#xff08;VR&#xff09;技术的浪潮中&#xff0c;我们见证了其从实验室的奇想逐渐走向日常生活的非凡旅程。技术发展的背后是不断突破的创新&#xff0c;早期的设备虽然笨重&#xff0c;但如今却趋向精致、轻巧&#xff0c;用户体验显著提升。想象一下…

无人机避障——4D毫米波雷达Octomap从点云建立三维栅格地图

Octomap安装 sudo apt-get install ros-melodic-octomap-ros sudo apt-get install ros-melodic-octomap-msgs sudo apt-get install ros-melodic-octomap-server sudo apt-get install ros-melodic-octomap-rviz-plugins # map_server安装 sudo apt-get install ros-melodic-…

推荐一个让线程池变的更简单的工具,轻量级的动态可监控线程池!(带私活源码)

背景 作为一个Java开发攻城狮&#xff0c;应用里少不了使用ThreadPoolExecutor 创建线程池&#xff0c;在使用的过程中你是否有以下痛点&#xff1a; 1、代码中创建了一个 ThreadPoolExecutor&#xff0c;但是不知道那几个核心参数设置多少比较合适 2、凭经验设置参数值&…

Fluent 后处理:动画制作

瞬态仿真中&#xff0c;动画制作是很重要的一个后处理步骤。Fluent中动画输出分为两步操作。 步骤 1&#xff1a;设置动画内容 在Fluent界面左侧树状菜单中的“solution animations”页面&#xff0c;设置动画内容。 其设置界面如下图所示。 1 合理设置动画帧的输出频率&…

机器人转人工时,开启实时质检(mod_cti基于FreeSWITCH)

文章目录 前言联系我们实现步骤1. 修改拨号方案2. 启用拨号方案 前言 在客户与机器人对话中&#xff0c;是不能开启质检功能的。因为机器人识别会与质检识别产生冲突。如果用户想通过机器人转接到人工时&#xff0c;开启质检功能&#xff0c;记录客户与人工之间的对话。应该如…

简记Vue3(二)—— computed、watch、watchEffect

个人简介 &#x1f440;个人主页&#xff1a; 前端杂货铺 &#x1f64b;‍♂️学习方向&#xff1a; 主攻前端方向&#xff0c;正逐渐往全干发展 &#x1f4c3;个人状态&#xff1a; 研发工程师&#xff0c;现效力于中国工业软件事业 &#x1f680;人生格言&#xff1a; 积跬步…

Linux字体更新 使用中文字体

问题描述&#xff0c;处理之前&#xff0c;中文乱码 处理后的结果 压缩需要上传的字体&#xff1a; 上传到LInux的字体目录&#xff0c;上传后解压出来 刷新字体&#xff1a; fc-cache -fv 测试是否正常 fc-list | grep "FontName"如果还不行 可以在代码里面指定字…

vivo 轩辕文件系统:AI 计算平台存储性能优化实践

在早期阶段&#xff0c;vivo AI 计算平台使用 GlusterFS 作为底层存储基座。随着数据规模的扩大和多种业务场景的接入&#xff0c;开始出现性能、维护等问题。为此&#xff0c;vivo 转而采用了自研的轩辕文件系统&#xff0c;该系统是基于 JuiceFS 开源版本开发的一款分布式文件…