レガシーのCOBOLバッチプロセスとそのJavaの交換の間での一致を検証するために、手動テスターは両方のシステムを同一の入力データセットに対して実行し、フィールドごとに調整を行う必要があります。この方法論は、取引の価値が高い記録、境界日(例:2月29日、年のロールオーバー)、および浮動小数点のエッジケースを優先する記録の層別サンプリングを含み、徹底的な比較ではなくなります。テスターは出力を中立的な形式(CSVなど)にエクスポートし、手動で財務の重要なフィールドを丸めの違いを確認しながら、差分ツールを使用する必要があります。ユリウス日の変換とパックデシマル(COMP-3)算術の動作をIEEE 754浮動小数点実装と比較することに特に注意を払わなければなりません。最後に、全出力ファイルのチェックサム検証やハッシュ比較は、詳細なフィールド分析が始まる前のスモークテストとして機能します。
私は多国籍銀行で、IBMメインフレーム COBOLシステムからLinux上で動作するSpring Bootマイクロサービスへの夜間利息累積バッチジョブの移行を検証する任務を与えられました。レガシーシステムは数十年にわたりCOMP-3パックデシマル算術およびユリウス日(YYDDD)形式を使用して数十億の取引を処理していましたが、新しいJavaアプリケーションはBigDecimalと標準のグレゴリオ暦を使用していました。核心的な問題は、ビット単位で同じ出力を確保することでした;わずかなセンの誤差でも数百万の口座にわたれば、重大な金融欠陥を構成し、丸めモードやうるう年計算における微妙な違いが重要な差異に波及する可能性がありました。
考慮された解決策の一つは、すべての出力記録のブラute-forceファイル比較でした。このアプローチは徹底的なカバレッジとすべてのバイトが一致するという絶対的な確実性を提供しました。しかし、利点は深刻な欠点に覆い隠されました:データセットには5000万を超える記録が含まれており、手動の比較は一晩のバッチウィンドウ内で人間には不可能であり、予想されるメタデータの違い(タイムスタンプなど)からのノイズが実際のデータ欠陥を隠すことができました。
別のオプションは、固定のパーセンテージの記録の単純なランダムサンプリング、例えば1パーセントでした。これは統計的に意味のある概要を提供し、実行も迅速でしたが、金融監査には受け入れがたい欠点がありました:ランダムサンプリングでは、高影響のアウトライヤーを簡単に見逃す可能性があり、特定の口座タイプの独自の丸めルールや2024年2月29日に発生する取引など、ユリウス日変換ロジックのバグを歴史的に引き起こす場合がありました。
選択された解決策は、自動化された差分スクリプトと手動検証を組み合わせた層別サンプリング戦略でした。私たちはリスク層に基づいて記録を分類しました:Tier 1には、一百万ドルを超える残高を持つすべての口座と、日付境界(月末、年末、うるう日)でのすべての取引が含まれ、Tier 2にはさまざまな製品タイプのランダムサンプルが含まれました。このアプローチは、高リスク取引での絶対的な確実性の必要性と、手動テスト時間の実際の制約をバランスさせるために選択されました。
Tier 1では、Beyond CompareとカスタムPythonスクリプトを使用してデルタを強調表示しながら、100%のフィールドレベル手動調整を行い、Tier 2では集計チェックサムを検証し、個々のフィールドをスポットチェックしました。その結果、COBOLが五桁で中間計算結果を切り捨てていたのに対し、JavaのデフォルトBigDecimalの除算が予測不可能にスケールを保持し、高利息口座で$0.01の差異を引き起こすという重大な欠陥を発見しました。特定された後、Javaの丸めモードをHALF_UPに明示的なスケールで調整し、完璧な一致を達成しました。
EBCDICからASCIIに移行された固定幅ファイルの検証時に、エンコーディングの損傷をどのように検出しますか?**
多くのテスターがテキストエディタでデータを視覚的に確認し、COBOLメインフレームがしばしばEBCDICコードページCP037を使用し、JavaシステムはUTF-8を使用していることを見逃しています。通貨記号(€、£)や顧客名におけるアクセント付き文字などの特殊文字は、誤ってマッピングされる可能性があります。確認するためには、ファイルを16進エディタで開いてバイトレベルの表現を比較し、COBOLのトレーリングスペース(しばしば16進数40)がJavaのヌル終端(16進数00)と混同されないようにし、パックデシマル(COMP-3)フィールドが符号ビットの損傷なしに正しくアンパックされることを確認する必要があります。
「なぜ二つの数学的に等しい計算がCOBOLとJavaで異なる結果をもたらすのか、どちらも「Decimal」型を使用している場合でも?」
候補者はしばしばBigDecimalがCOBOLのパックデシマルと同じ動作を保証すると仮定します。しかし、COBOLはPIC句(例:PIC 9(9)V99)によって決定された固定精度で10進算術を実行し、各操作ステップでビジネスルールに従って中間結果を切り捨てます。JavaのBigDecimalはデフォルトで任意の精度を保持しますが、明示的にMathContextとRoundingModeを設定しない限り、保持し続けます。解決策は、すべての中間ステップでレガシーの丸めモード(しばしばHALF_UPまたはHALF_EVEN)に一致させながら、明示的なsetScale()呼び出しを使用して、COBOLの切り捨てロジックを複製することです。
レガシーシステムが夏時間(DST)を無視しているのに対し、新しいJavaアプリケーションがDSTを考慮したUTCまたはローカル時間を使用する場合、タイムリーな精度をどのように検証しますか?
これは、テスターがタイムスタンプを表面的に比較するためによく見逃されます。レガシーのCOBOLジョブが年間を通じてEST(東部標準時間)で実行される一方、JavaサービスはAmerica/New_York(EDTにシフトします)を使用し、3月の第2日曜日の午前2時から午前3時の間に発生した取引には1時間のオフセットがあります。これを解決するために、テスターは手動検証中に両方のタイムスタンプを標準形式(例:UTCエポックミリ秒)に変換し、"日末"バッチカットオフパラメータ(通常は"23:59:59")が一貫して解釈されることを確認し、日付境界ロジック(例:"月の最終営業日")が春の欠落した1時間や秋の余分な1時間のためにシフトしないことを確認する必要があります。