schema_validator.py 2.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. """
  2. Schema 校验工具
  3. 负责验证接口返回的数据是否符合文档约定。
  4. 这是"工具层"——没有大脑,只会严格地对照规则检查。
  5. """
  6. import jsonschema
  7. from jsonschema import ValidationError
  8. class SchemaValidator:
  9. """结果校验工具
  10. 用 JSON Schema 规则来检查接口响应:
  11. - 状态码是否符合预期
  12. - 响应体数据结构是否符合约定
  13. """
  14. def validate_status_code(self, actual, expected):
  15. """校验状态码是否符合预期
  16. Args:
  17. actual: 实际返回的状态码,如 200
  18. expected: 期望的状态码,如 200
  19. Returns:
  20. (是否通过, 错误信息) —— 通过时错误信息为 None
  21. """
  22. if actual == expected:
  23. return True, None
  24. return False, f"状态码不符:期望 {expected},实际 {actual}"
  25. def validate_body(self, body, schema):
  26. """校验响应体是否符合 JSON Schema
  27. Args:
  28. body: 实际返回的响应体(dict 或字符串)
  29. schema: JSON Schema 说明书(dict)
  30. Returns:
  31. (是否通过, 错误信息)
  32. """
  33. # 没有给 schema,就不校验(跳过)
  34. if schema is None:
  35. return True, None
  36. try:
  37. jsonschema.validate(body, schema)
  38. return True, None
  39. except ValidationError as e:
  40. # e.message 是 jsonschema 给的"哪里不符合"的说明
  41. return False, f"数据结构不符:{e.message}"
  42. def validate(self, result, expected_status=None, expected_schema=None):
  43. """综合校验一个请求结果
  44. Args:
  45. result: http_client 返回的标准化结果字典
  46. expected_status: 期望的状态码(可选)
  47. expected_schema: 期望的 JSON Schema(可选)
  48. Returns:
  49. 校验结果字典:
  50. {
  51. "success": bool, # 是否全部通过
  52. "errors": [str, ...] # 所有不通过的原因列表
  53. }
  54. """
  55. errors = []
  56. # 1. 请求本身是否成功(网络层)
  57. if not result["success"]:
  58. errors.append(f"请求失败:{result['error']}")
  59. # 请求都失败了,后面的状态码和结构检查没有意义,直接返回
  60. return {"success": False, "errors": errors}
  61. # 2. 状态码检查
  62. if expected_status is not None:
  63. ok, msg = self.validate_status_code(
  64. result["status_code"], expected_status
  65. )
  66. if not ok:
  67. errors.append(msg)
  68. # 3. 响应体结构检查
  69. if expected_schema is not None:
  70. ok, msg = self.validate_body(result["body"], expected_schema)
  71. if not ok:
  72. errors.append(msg)
  73. return {
  74. "success": len(errors) == 0,
  75. "errors": errors,
  76. }