质量保证
适用于 ✅ 开源版 ✅ 专业版 ✅ 企业版
jOOQ 正在运行您最关键的逻辑:Java / Scala 应用程序和数据库之间的接口层。您可能出于以下任何原因选择了 jOOQ
- 为了避免 JDBC 因字符串连接和基于索引的变量绑定而导致的冗长和易出错
- 为您的内联 SQL 添加大量类型安全
- 在使用您最喜欢的 IDE 的自动完成功能编写内联 SQL 时提高生产力
由于 jOOQ 位于您的应用程序的核心,因此您需要确保可以信任 jOOQ。这就是为什么 jOOQ 经过了大量的单元和集成测试,并非常注重集成测试
单元测试
单元测试是针对使用模拟的虚拟 JDBC 接口执行的,包括我们自己的 JDBC 模拟抽象。这些测试验证了各种 org.jooq.QueryPart
实现是否正确呈现 SQL 并正确绑定变量。
除了上述之外,众多类型的单元测试还包括
- SQL 格式化测试
- JSON 和 XML 数据导入/导出测试
- 解析器测试
- 映射器和转换器测试
- SPI 测试
- SQL 转换测试
- 以及更多
集成测试
这是 jOOQ 测试套件中最重要的部分。目前针对标准集成测试数据库运行 10k+ 个查询,我们为此使用 testcontainers 和其他虚拟化实用程序。测试数据库和查询都被翻译成 30 多种受支持的 SQL 方言中的每一种,以确保不太可能将回归引入代码库中。
对于像 jOOQ 这样的库,集成测试比单元测试更具表现力,因为 SQL 方言中存在许多细微的差异。简单的模拟无法提供与实际数据库实例一样多的反馈。
jOOQ 集成测试运行最奇怪和最不真实的查询。作为这些广泛的集成测试套件的副作用,已经发现了 JDBC 驱动程序和/或开源数据库的许多极端情况错误,通过 jOOQ 提交了功能请求,并主要报告给 Derby、H2、HSQLDB。
代码生成测试
对于 30 多种受支持的集成测试数据库中的每一种,都会生成源代码,并且可以发现生成的源代码中的微小差异。如果生成的源代码中出现编译错误,则会添加新的测试表/视图/列,以避免此领域中的回归。
API 可用性测试和概念验证
jOOQ 在 jOOQ-meta 中用作概念验证。这包括复杂的查询,例如以下 Postgres 查询
Routines r1 = ROUTINES.as("r1"); Routines r2 = ROUTINES.as("r2"); for (Record record : create.select( r1.ROUTINE_SCHEMA, r1.ROUTINE_NAME, r1.SPECIFIC_NAME, // Ignore the data type when there is at least one out parameter DSL.when(exists( selectOne() .from(PARAMETERS) .where(PARAMETERS.SPECIFIC_SCHEMA.eq(r1.SPECIFIC_SCHEMA)) .and(PARAMETERS.SPECIFIC_NAME.eq(r1.SPECIFIC_NAME)) .and(upper(PARAMETERS.PARAMETER_MODE).ne("IN"))), val("void")) .else_(r1.DATA_TYPE).as("data_type"), r1.CHARACTER_MAXIMUM_LENGTH, r1.NUMERIC_PRECISION, r1.NUMERIC_SCALE, r1.TYPE_UDT_NAME, // Calculate overload index if applicable DSL.when( exists( selectOne() .from(r2) .where(r2.ROUTINE_SCHEMA.in(getInputSchemata())) .and(r2.ROUTINE_SCHEMA.eq(r1.ROUTINE_SCHEMA)) .and(r2.ROUTINE_NAME.eq(r1.ROUTINE_NAME)) .and(r2.SPECIFIC_NAME.ne(r1.SPECIFIC_NAME))), select(count()) .from(r2) .where(r2.ROUTINE_SCHEMA.in(getInputSchemata())) .and(r2.ROUTINE_SCHEMA.eq(r1.ROUTINE_SCHEMA)) .and(r2.ROUTINE_NAME.eq(r1.ROUTINE_NAME)) .and(r2.SPECIFIC_NAME.le(r1.SPECIFIC_NAME)).asField()) .as("overload")) .from(r1) .where(r1.ROUTINE_SCHEMA.in(getInputSchemata())) .orderBy( r1.ROUTINE_SCHEMA.asc(), r1.ROUTINE_NAME.asc()) .fetch()) { result.add(new PostgresRoutineDefinition(this, record)); }
与集成测试套件中相当简单且通常不真实的查询相比,这些相当复杂的查询表明 jOOQ API 适用于高级 SQL 用例。
清晰的 API 和实现。代码保持 DRY
作为整个 jOOQ 代码中的一般经验法则,一切都保持 DRY。一些例子
- 整个代码库中只有一个地方可以从 JDBC ResultSet 中获取值
- 整个代码库中只有一个地方可以将 jOOQ Records 转换为自定义 POJO
保持 DRY 会导致更长的堆栈跟踪,但反过来也会增加高度可重用代码块的相关性。jOOQ 代码库的某些部分被集成测试覆盖的几率显着降低。
反馈
您对此页面有任何反馈吗? 我们很乐意听到您的意见!