python读取json文件时的TypeError:‘dict‘ object is not callable错误解决方法

本文详细解析了在Python中遇到'dict' object is not callable错误,当你尝试调用字典对象时,如何通过排查和实例来修复这个问题,适合新手和进阶开发者参考。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

根据: from _ast import operator from typing import Callable, Any import jsonpath from unit_tools.exceptions import AssertTypeError class Assertions: """ 接口断言模式封装 1) 状态码断言 2) 包含模式断言 3) 相等断言 4) 不相等断言 """ @classmethod def status_code_assert(cls, expected_result, status_code): """ 接口的响应状态码断言 :param expected_result: (int)yaml文件code模式中的预期状态码 :param status_code: (int)接口实际返回的状态码 :return: """ # 断言状态标识,0 表示成功,其他表示失败 failure_count = 0 if not isinstance(expected_result, int): expected_result = int(expected_result) if expected_result == status_code: print(f'状态吗断言成功:接口实际返回状态码{status_code} == {expected_result}') else: print(f'断言失败:接口实际返回状态码{status_code} != {expected_result}') failure_count += 1 return failure_count @classmethod def contain_assert(cls, expected_result, response): """ 字符串包含模式,断言预期结果字符串是否包含在接口的实际响应返回信息中 :param expected_result:dict)yaml文件里面contain模式的数据 :param response:dict)接口的实际响应信息 :return: """ # 断言状态标识,0 表示成功,其他表示失败 failure_count = 0 for assert_key, assert_value in expected_result.items(): response_list = jsonpath.jsonpath(response, f'$..{assert_key}') if response_list and isinstance(response_list[0], str): response_str = ''.join(response_list) success_message = f"包含模式断言成功:预期结果【{assert_value}】存在于实际结果【{response_str}】中" failure_message = f"包含模式断言失败:预期结果【{assert_value}】未在实际结果【{response_str}】中找到" if assert_value in response_str: print(success_message) else: failure_count = failure_count + 1 print(failure_message) return failure_count @classmethod def equal_assert(cls, expected_result, response): """ 相等断言,根据yaml里面的validation关键词下面的ne模式数据去跟接口实际响应信息对比 :param expected_result:dict)yaml里面的eq值 :param response:dict)接口实际响应结果 :return: """ failure_count = 0 if isinstance(response, dict) and isinstance(expected_result, dict): # 找出实际结果与预期结果共同的key值 common_key = list(expected_result.keys() & response.keys()) if common_key: # 找出实际结果与预期结果共同的key值 common_key = common_key[0] new_actual_result = {common_key: response[common_key]} eq_assert = operator.__eq__(new_actual_result, expected_result) if eq_assert: print(f"相等断言成功:接口实际结果{new_actual_result} == 预期结果:{expected_result}") else: failure_count += 1 print(f"相等断言失败:接口实际结果{new_actual_result} != 预期结果:{expected_result}") else: failure_count += 1 print('相等断言失败,请检查yaml文件eq模式的预期结果或接口返回值是否正确') return failure_count @classmethod def assert_result(cls, expected_result, response, status_code): """ 断言主函数,通过all_flag标记,如all_flag == 0表示测试成功,否则为失败 :param expected_result: (list)yaml文件validation关键词下面的预期结果 :param response:dict)接口的实际响应信息 :param status_code: (int)接口的实际响应状态码 :return: """ all_flag = 0 # 通过字典映射方式管理不同的断言方式 assert_methods = { 'code': cls.status_code_assert, 'contain': cls.contain_assert, 'eq': cls.equal_assert # 'ne': cls.not_equal_assert, } try: for yq in expected_result: for assert_mode, assert_value in yq.items(): # 表示assert_method是一个接受两个参数,类型为Any表示可以是任意类型,并返回整数的可调用对象 assert_method: Callable[[Any, Any], int] = assert_methods.get(assert_mode) if assert_method: # 调用对应的断言方法,传递适当的参数 if assert_mode in ['code']: flag = assert_method(assert_value, status_code) else: flag = assert_method(assert_value, response) all_flag += flag else: raise AssertTypeError(f'不支持{assert_mode}该断言模式') except Exception as exceptions: raise exceptions assert all_flag == 0, '测试失败' print('测试成功') 解决以下问题: PS D:\a\b\PythonProject1> pytest -s ========================================================================= test session starts ========================================================================= platform win32 -- Python 3.11.9, pytest-7.4.0, pluggy-1.6.0 rootdir: D:\a\b\PythonProject1 configfile: pytest.ini testpaths: test_test/ plugins: metadata-3.1.1, parallel-0.1.1, repeat-0.9.4, testreport-1.1.6, xdist-3.8.0 collecting ... D:\a\b\PythonProject1 {'api_name': '用户登录', 'url': 'https://10.121.177.71/itf/session', 'method': 'post', 'verify': 'verify', 'headers': {'Content-Type': 'application/x-www-form-urlencoded'}} collected 3 items test_test\test_api.py 请求头参数: {'Content-Type': 'application/x-www-form-urlencoded'} 参数类型:data 请求参数:{"username": "admin", "password": "admin"} 接口返回值: { "ResidueDay": 255, "ok": 0, "privilege": 4, "user_id": 2, "extendedpriv": 383, "racsession_id": 48, "remote_addr": "10.121.178.218", "server_name": "10.1 .71", "server_addr": "10.121.177.71", "HTTPSEnabled": 1, "CSRFToken": "SN3nPzFG", "channel": 1, "passwordStatus": 0, "encrypt_flag": 0, "SelfSetPriv": 1, "InfoQue e ryPriv": 1, "DebugPriv": 1, "PowerConPriv": 1, "SecuConPriv": 1, "RemoteMediaPriv": 1, "RemoteKVMPriv": 1, "CommConfigPriv": 1, "UserConfigPriv": 1, "group_name": "Administrator", "ChangePasswordAlert": 0 } 状态吗断言成功:接口实际返回状态码200 == 200 测试成功 . 请求头参数: {'Content-Type': 'application/x-www-form-urlencoded'} 参数类型:data 请求参数:{"username": "admin", "password": "admin"} 接口返回值: { "ResidueDay": 255, "ok": 0, "privilege": 4, "user_id": 2, "extendedpriv": 383, "racsession_id": 49, "remote_addr": "10.121.178.218", "server_name": "10.1 21.177.71", "server_addr": "10.121.177.71", "HTTPSEnabled": 1, "CSRFToken": "uRz7lMlP", "channel": 1, "passwordStatus": 0, "encrypt_flag": 0, "SelfSetPriv": 1, "InfoQue ryPriv": 1, "DebugPriv": 1, "PowerConPriv": 1, "SecuConPriv": 1, "RemoteMediaPriv": 1, "RemoteKVMPriv": 1, "CommConfigPriv": 1, "UserConfigPriv": 1, "group_name": "Administrator", "ChangePasswordAlert": 0 } 出现异常,--'NoneType' object is not iterable F 请求头参数: {'Content-Type': 'application/x-www-form-urlencoded'} 参数类型:data 请求参数:{"username": "admin", "password": "admin"} 接口返回值: { "ResidueDay": 255, "ok": 0, "privilege": 4, "user_id": 2, "extendedpriv": 383, "racsession_id": 50, "remote_addr": "10.121.178.218", "server_name": "10.1 21.177.71", "server_addr": "10.121.177.71", "HTTPSEnabled": 1, "CSRFToken": "s4fPh5ra", "channel": 1, "passwordStatus": 0, "encrypt_flag": 0, "SelfSetPriv": 1, "InfoQue ryPriv": 1, "DebugPriv": 1, "PowerConPriv": 1, "SecuConPriv": 1, "RemoteMediaPriv": 1, "RemoteKVMPriv": 1, "CommConfigPriv": 1, "UserConfigPriv": 1, "group_name": "Administrator", "ChangePasswordAlert": 0 } 出现异常,--'NoneType' object is not iterable F ============================================================================== FAILURES =============================================================================== ________________________________________________________ TestLogin.test_login_module[api_info0-testcase0-2-3] _________________________________________________________ self = <test_test.test_api.TestLogin object at 0x00000198BD875810> api_info = {'api_name': '用户登录', 'headers': {'Content-Type': 'application/x-www-form-urlencoded'}, 'method': 'post', 'url': 'https://10.121.177.71/itf/session', ...} testcase = {'data': {'password': 'admin', 'username': 'admin'}} @pytest.mark.passdef @pytest.mark.repeat(3) @pytest.mark.parametrize('api_info,testcase', YamlUtil().read_def_yaml('get_new.yaml')) def test_login_module(self, api_info, testcase): if 'case_name' not in testcase: testcase['case_name'] = f"默认用例_{id(testcase)}" # 用唯一标识避免重复 > RequestsBase().execute_test_cases(api_info, testcase) test_test\test_api.py:14: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ unit_tools\apiutils_single.py:121: in execute_test_cases raise e unit_tools\apiutils_single.py:117: in execute_test_cases self.asserts.assert_result(validation,response.json(),status_code) unit_tools\assertion_utils.py:124: in assert_result raise exceptions _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ cls = <class 'unit_tools.assertion_utils.Assertions'>, expected_result = None response = {'CSRFToken': 'uRz7lMlP', 'ChangePasswordAlert': 0, 'CommConfigPriv': 1, 'DebugPriv': 1, ...}, status_code = 200 @classmethod def assert_result(cls, expected_result, response, status_code): """ 断言主函数,通过all_flag标记,如all_flag == 0表示测试成功,否则为失败 :param expected_result: (list)yaml文件validation关键词下面的预期结果 :param response:dict)接口的实际响应信息 :param status_code: (int)接口的实际响应状态码 :return: """ all_flag = 0 # 通过字典映射方式管理不同的断言方式 assert_methods = { 'code': cls.status_code_assert, 'contain': cls.contain_assert, 'eq': cls.equal_assert # 'ne': cls.not_equal_assert, } try: > for yq in expected_result: E TypeError: 'NoneType' object is not iterable unit_tools\assertion_utils.py:109: TypeError ________________________________________________________ TestLogin.test_login_module[api_info0-testcase0-3-3] _________________________________________________________ self = <test_test.test_api.TestLogin object at 0x00000198BD877F50> api_info = {'api_name': '用户登录', 'headers': {'Content-Type': 'application/x-www-form-urlencoded'}, 'method': 'post', 'url': 'https://10.121.177.71/itf/session', ...} testcase = {'data': {'password': 'admin', 'username': 'admin'}} @pytest.mark.passdef @pytest.mark.repeat(3) @pytest.mark.parametrize('api_info,testcase', YamlUtil().read_def_yaml('get_new.yaml')) def test_login_module(self, api_info, testcase): if 'case_name' not in testcase: testcase['case_name'] = f"默认用例_{id(testcase)}" # 用唯一标识避免重复 > RequestsBase().execute_test_cases(api_info, testcase) test_test\test_api.py:14: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ unit_tools\apiutils_single.py:121: in execute_test_cases raise e unit_tools\apiutils_single.py:117: in execute_test_cases self.asserts.assert_result(validation,response.json(),status_code) unit_tools\assertion_utils.py:124: in assert_result raise exceptions _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ cls = <class 'unit_tools.assertion_utils.Assertions'>, expected_result = None response = {'CSRFToken': 's4fPh5ra', 'ChangePasswordAlert': 0, 'CommConfigPriv': 1, 'DebugPriv': 1, ...}, status_code = 200 @classmethod def assert_result(cls, expected_result, response, status_code): """ 断言主函数,通过all_flag标记,如all_flag == 0表示测试成功,否则为失败 :param expected_result: (list)yaml文件validation关键词下面的预期结果 :param response:dict)接口的实际响应信息 :param status_code: (int)接口的实际响应状态码 :return: """ all_flag = 0 # 通过字典映射方式管理不同的断言方式 assert_methods = { 'code': cls.status_code_assert, 'contain': cls.contain_assert, 'eq': cls.equal_assert # 'ne': cls.not_equal_assert, } try: > for yq in expected_result: E TypeError: 'NoneType' object is not iterable unit_tools\assertion_utils.py:109: TypeError ========================================================================== warnings summary =========================================================================== test_test/test_api.py::TestLogin::test_login_module[api_info0-testcase0-1-3] test_test/test_api.py::TestLogin::test_login_module[api_info0-testcase0-2-3] test_test/test_api.py::TestLogin::test_login_module[api_info0-testcase0-3-3] D:\python\Lib\site-packages\urllib3\connectionpool.py:1097: InsecureRequestWarning: Unverified HTTPS request is being made to host '10.121.177.71'. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#tls-warnings warnings.warn( -- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html ======================================================================= short test summary info ======================================================================= FAILED test_test/test_api.py::TestLogin::test_login_module[api_info0-testcase0-2-3] - TypeError: 'NoneType' object is not iterable FAILED test_test/test_api.py::TestLogin::test_login_module[api_info0-testcase0-3-3] - TypeError: 'NoneType' object is not iterable =============================================================== 2 failed, 1 passed, 3 warnings in 2.34s ===============================================================
最新发布
08-06
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值