Aby zweryfikować parzystość między procesem wsadowym COBOL a jego zamiennikiem w Java, tester manualny musi wykonać oba systemy w oparciu o identyczne zestawy danych wejściowych i przeprowadzić uzgodnienie pole po polu. Metodologia polega na stratyfikowanym próbkowaniu rekordów — priorytetując transakcje o wysokiej wartości, daty graniczne (np. 29 lutego, zmiany roku) i przypadki ekstremalne zmiennoprzecinkowe — zamiast na wyczerpujące porównanie. Testerzy powinni eksportować wyniki do neutralnych formatów (takich jak CSV) i wykorzystywać narzędzia do porównywania, jednocześnie ręcznie sprawdzając krytyczne pola finansowe pod kątem różnic w zaokrągleniach. Szczególną uwagę należy zwrócić na konwersje daty juliańskiej oraz zachowanie arytmetyki dziesiętnej pakowanej (COMP-3) w porównaniu do implementacji zmiennoprzecinkowych IEEE 754. Na koniec walidacja sum kontrolnych i porównania skrótów całych plików wyjściowych służy jako test dymny przed rozpoczęciem szczegółowej analizy pól.
W międzynarodowym banku zostałem poproszony o zweryfikowanie migracji nocnego zadania obliczania odsetek z systemu IBM Mainframe COBOL do mikroserwisu Spring Boot działającego na Linuxie. System legacy przetwarzał biliony transakcji przez dziesięciolecia, używając arytmetyki dziesiętnej pakowanej COMP-3 i formatów daty juliańskiej (YYDDD), podczas gdy nowa aplikacja Java wykorzystywała BigDecimal i standardowe kalendarze gregoriańskie. Głównym problemem było zapewnienie identycznego bitowo wyniku; nawet niewielka różnica centa w milionach kont stanowiłaby krytyczny błąd finansowy, a subtelne różnice w trybach zaokrąglania lub obliczeniach lat przestępnych mogłyby prowadzić do materialnych różnic.
Jednym z rozważanych rozwiązań było brutalne porównanie plików wszystkich rekordów wyjściowych. Podejście to oferowało wyczerpujące pokrycie i absolutną pewność, że każdy bajt zgadza się. Jednak zalety zostały przyćmione przez poważne wady: zestaw danych zawierał ponad pięćdziesiąt milionów rekordów, co czyniło manualne porównanie niemożliwym w nocy w czasie przetwarzania wsadowego, a ogromna ilość szumów z oczekiwanych różnic metadanych (np. znaczniki czasowe) zamaskowałaby rzeczywiste wady danych.
Inną opcją była prosta losowa próbka stałego procentu rekordów, na przykład jeden procent. Chociaż to zapewniało statystycznie znaczący przegląd i było szybkie do wykonania, wady były nieakceptowalne dla audytu finansowego: losowe próbkowanie mogło łatwo pominąć mające duży wpływ przypadki skrajne, takie jak specyficzny typ konta z unikalnymi zasadami zaokrąglania lub transakcje mające miejsce 29 lutego 2024, które historycznie wywołały błędy w logice konwersji dni juliańskich.
Wybrane rozwiązanie to strategia stratyfikowanego próbkowania połączona zautomatyzowanymi skryptami różnicowymi do manualnej walidacji. Skategoryzowaliśmy rekordy według poziomów ryzyka: Poziom 1 obejmował wszystkie konta z saldami przekraczającymi milion dolarów i wszystkie transakcje na granicach dat (koniec miesiąca, koniec roku, dni przestępne), podczas gdy Poziom 2 obejmował losowe próbki z różnych typów produktów. To podejście zostało wybrane, ponieważ równoważyło potrzebę absolutnej pewności w odniesieniu do transakcji wysokiego ryzyka z praktycznymi ograniczeniami czasu testowania manualnego.
Dla Poziomu 1 przeprowadziliśmy 100% manualnego uzgadniania na poziomie pola za pomocą Beyond Compare oraz niestandardowych skryptów Python do wyróżnienia delty, podczas gdy dla Poziomu 2 weryfikowaliśmy zestawienia kontrolne i sprawdzaliśmy przypadkowe pola. Rezultatem było odkrycie krytycznej wady, w której COBOL obcinał wyniki obliczeń pośrednich do pięciu miejsc po przecinku, podczas gdy domyślna dzielenie BigDecimal w Java nieprzewidywanie utrzymywało skalę, co powodowało różnicę na poziomie $0.01 na kontach o wysokich odsetkach. Po zidentyfikowaniu, dostosowaliśmy tryb zaokrąglania Java do HALF_UP z wyraźną skalą, osiągając doskonałą parzystość.
Jak wykrywasz korupcję kodowania, gdy walidujesz pliki o stałej szerokości przeniesione z EBCDIC do ASCII?
Wielu testerów wizualnie przegląda dane w edytorach tekstowych, nie zauważając, że systemy COBOL często używają kodu EBCDIC CP037, podczas gdy systemy Java używają UTF-8. Znaki specjalne, takie jak symbole walut (€, £) czy akcentowane litery w imionach klientów, mogą być błędnie mapowane. Aby to zweryfikować, musisz otworzyć pliki w edytorze heksadecymalnym, aby porównać reprezentacje na poziomie bajtów, upewniając się, że końcowe spacje w COBOL (często heks 40) nie są mylone z terminatorami null w Java (heks 00), a pola dziesiętne pakowane (COMP-3) są poprawnie odpakowywane bez korupcji bitów znaku.
Dlaczego dwie matematycznie równoważne obliczenia mogą przynieść różne wyniki w COBOL w porównaniu do Java, nawet jeśli obie używają typów "dziesiętnych"?
Kandydaci często zakładają, że BigDecimal gwarantuje identyczne działanie w porównaniu do pakowanego dziesiętnego w COBOL. Jednak COBOL wykonuje arytmetykę w systemie dziesiętnym z ustaloną precyzją określoną przez klauzulę PIC (np. PIC 9(9)V99), obcinając wyniki pośrednie na każdym kroku operacji zgodnie z zasadami biznesowymi. BigDecimal w Java, domyślnie, utrzymuje dowolną precyzję, chyba że wyraźnie ustawisz MathContext i RoundingMode. Rozwiązaniem jest powielenie logiki obcinania COBOL przez łączenie operacji z wyraźnymi wywołaniami setScale() oraz dopasowywanie dotychczasowego trybu zaokrąglania (często HALF_UP lub HALF_EVEN) na każdym kroku pośrednim, a nie tylko w końcowym wyniku.
Jak walidujesz dokładność temporalną, gdy system dziedziczony ignoruje czas letni (DST), podczas gdy nowa aplikacja Java używa UTC lub lokalnego czasu z uwzględnieniem DST?
Często jest to przeoczone, ponieważ testerzy porównują znaczniki czasowe powierzchownie. Jeśli zadanie wsadowe COBOL działa na EST (czas standardowy wschodni) przez cały rok, podczas gdy usługa Java używa America/New_York (która przechodzi na EDT), transakcje odbywające się między 2:00 a 3:00 w drugą niedzielę marca będą miały godzinowy offset. Aby to rozwiązać, testerzy muszą przekonwertować oba znaczniki czasowe na format kanoniczny (np. milisekundy epoki UTC) podczas walidacji manualnej, upewnić się, że parametry końcowego cięcia wsadu (często „23:59:59”) są interpretowane konsekwentnie oraz zapewnić, że logika granic dat (np. „ostatni dzień roboczy miesiąca”) nie przesuwa się z powodu brakującej godziny na wiosnę lub dodatkowej godziny jesienią.