为了验证旧COBOL批处理过程与其Java替代品之间的平衡,手动测试人员必须针对相同的输入数据集运行两个系统,并逐字段进行对账。该方法涉及对记录的分层抽样——优先考虑高价值交易、边界日期(例如,2月29日、年末转移)和浮点边缘案例——而不是进行全面比较。测试人员应将输出导出为中立格式(如CSV),并利用差异工具,同时手动检查关键财务字段的舍入差异。特别注意必须关注儒略日期转换和打包十进制(COMP-3)算术行为与IEEE 754浮点实现之间的差异。最后,对整个输出文件的校验和验证和哈希比较作为详细字段分析开始前的烟雾测试。
在一家跨国银行,我负责验证将夜间利息累积批处理作业从IBM大型机 COBOL系统迁移到在Linux上运行的Spring Boot微服务。旧系统在几十年内处理了数十亿的交易,使用的是COMP-3打包十进制算术和儒略日期(YYDDD)格式,而新的Java应用程序使用的是BigDecimal和标准公历。核心问题是确保位wise相同的输出;即使在数百万个账户中,有一分的差异也会构成一个严重的财务缺陷,舍入模式或闰年计算的细微差异可能引发重要的变异。
考虑的一种解决方案是对所有输出记录进行强制文件比较。这种方法提供了全面覆盖和每个字节匹配的绝对保证。然而,利大于弊:数据集包含超过五千万条记录,在夜间批处理窗口内人工比较几乎是不可能的,并且来自预计元数据差异(如时间戳)的噪声将掩盖实际数据缺陷。
另一个选项是简单随机抽样固定百分比的记录,例如百分之一。虽然这提供了统计上显著的概述并且执行起来迅速,但对财务审计来说,这种缺点是不可接受的:随机抽样很容易遗漏高影响的异常值,例如某种特定帐户类型具有独特的舍入规则或在2024年2月29日发生的交易,这在历史上触发了儒略日转换逻辑中的错误。
选定的解决方案是结合自动化差异脚本进行手动验证的分层抽样策略。我们按照风险级别对记录进行分类:第一类包括所有余额超过一百万美元的账户以及所有在边界日期(月底、年末、闰日)上的交易,而第二类则涵盖来自不同产品类型的随机样本。这个方法被选中,因为它在高风险交易的绝对确定性需求和手动测试时间的实际限制之间取得了平衡。
对于第一类,我们使用Beyond Compare和自定义Python脚本进行100%的字段级手动对账,以突出差异,而对于第二类,我们验证汇总校验和并随机抽检单独字段。结果发现了一个关键缺陷:COBOL在每个计算步骤中以五个小数位截断中间计算结果,而Java的默认BigDecimal除法在保持小数位方面不稳定,导致高利息账户上的$0.01差异。一旦识别出这一点,我们将Java的舍入模式调整为HALF_UP并设置明确的小数位,实现了完美匹配。
在验证从EBCDIC迁移到ASCII的固定宽度文件时,您如何检测编码损坏?
许多测试人员在文本编辑器中直观检查数据,忽视了COBOL大型机通常使用EBCDIC代码页CP037,而Java系统使用UTF-8。特殊字符如货币符号(€,£)或客户姓名中的重音字母可能会错误映射。为了验证,您必须在十六进制编辑器中打开文件,以比较字节级表示,确保COBOL中的尾随空格(通常为十六进制40)不会与Java中的空终止符(十六进制00)混淆,并且打包十进制(COMP-3)字段在解包时没有符号位损坏。
为什么在使用“十进制”类型的情况下,COBOL与Java的两个数学等价计算可能会得出不同结果?
候选人常常假设BigDecimal保证与COBOL的打包十进制相同的行为。但是,COBOL执行的基于10的算术具有由PIC子句(例如,PIC 9(9)V99)决定的固定精度,在每个操作步骤中根据业务规则截断中间结果。而Java的BigDecimal,在默认情况下,保持任意精度,除非您显式设置MathContext和RoundingMode。解决方案是在每一步操作中通过链式调用明确的setScale()和匹配旧版舍入模式(通常为HALF_UP或HALF_EVEN)来复制COBOL的截断逻辑,而不仅仅在最终结果上。
当旧系统忽略夏令时(DST),而新的Java应用程序使用UTC或具有DST感知的本地时间时,您如何验证时间的准确性?
由于测试人员表面上比较时间戳时常常被忽视。如果旧COBOL作业全年在EST(东部标准时间)运行,而Java服务使用America/New_York(它会切换到EDT),在三月的第二个星期日的早上2:00与3:00之间发生的交易将存在一个小时的偏移。为了解决这个问题,测试人员必须在手动验证期间将两个时间戳转换为规范格式(例如UTC纪元毫秒),确保“结束日”批处理截止参数(通常为“23:59:59”)被一致地解释,并确保由于春季缺失的小时或秋季多出的小时,日期边界逻辑(例如“月末最后一个工作日”)不会发生移动。