测试实施全流程
1. 单元和集成测试
单元和集成测试是以最快速度发现代码方面的问题。
测试是证实Protobuf契约,做法是直接使用你项目开发语言对应的gRPC库和测试框架,编写代码来调用服务、测试结果。
使用gRPC Mock工具来模拟未就绪的下游服务,可以在不启动整个微服务集群的情况下完成对单个服务的隔离测试提高测试的稳定性和速度。
项目使用Go语言,能提供一个内存级的网络连接,在测试代码中直接启动gRPC服务端,无需真实网络端口,测试效率很高。
2. 全面的功能测试
包括所有服务类型:
简单RPC (Unary):测试输入对应的输出是不是符合预期。
服务端流式RPC:客户端单次请求,服务端不断推送多条数据。测试能否完整接收流并拼接数据。
客户端流式RPC:客户端发送数据流,服务端返回单一确定。测试能否正确分段发送及服务端最后响应。
双向流式RPC:双方独立读写数据流。测试需模拟请求流和响应流实时交织,测试状态同步和顺序。
业务数据:grpcurl 这类命令行工具是调试时的利器,可以快速列出服务、方法和描述信息,无需编写代码即可完成单接口测试。
3. 负面测试
保证服务在异常情况不直接崩溃。
设计异常用例:尝试向服务端发送格式错误的 Protobuf 消息、包含过期或无效 Token 的请求、以及违反字段定义的数据(如超长的字符串)。
证实错误处理:检查服务端能否正确返回相应的 gRPC 错误状态码(如 INVALID_ARGUMENT、PERMISSION_DENIED),并且不会泄露内部实现细节等敏感信息。
4. 第四步:性能和压力测试
在保证功能正确后,需要证实服务的性能短板。
复杂性和重点:由于gRPC使用 HTTP/2,长连接和多路复用特性在提升性能的同时也引入了新的性能短板(如连接池、流控等),单连接并发过大时可能成为短板。
流程和工具:
脚本编写:以Gatling为例,你需要定义 GrpcProtocolBuilder,并编写模拟用户行为的测试情形,从 .proto 定义中创建请求消息。
执行和监控:按标准-负载-压力-稳定性的标准流程执行,重视延迟、吞吐量 (TPS)、错误率及服务端资源。
和功能测试的区别:性能测试为了测试极限容量、暴露短板;功能测试为了测试正确性。不要用并发流量来跑功能测试。
测试重点
测试契约而不是代码:始终以Protobuf定义为唯一真理。引入自动化工具(如 protolock)保证任何代码改动都必须通过兼容性检查,防止破坏性变更。
反射:对于开启了 gRPC 服务端反射的接口,grpcurl 等工具可以自动发现服务和消息类型,极大简化测试步骤。
结果可观测:监控 gRPC 特有的错误状态码(如 UNIMPLEMENTED, DEADLINE_EXCEEDED 等),结合请求和响应的元数据(Metadata),可以在复杂的微服务调用链中快速定位问题。