Program yang ditulis sekaligus lalu diuji sekaligus menyembunyikan letak kesalahannya di tengah ratusan baris. Topik ini membangun program aging piutang dari cetak biru rancangan secara bertahap, dengan satu titik pemeriksaan pada setiap langkah yang keluarannya dapat dibandingkan dengan perhitungan manual. Berkas uji disiapkan lebih dahulu, tiga langkah pembangunan menambah kemampuan program sedikit demi sedikit, dan langkah pamungkas menguji penanganan status berkas pada kondisi tak normal.
Berkas uji piutang#
Pengujian bertahap memerlukan berkas uji yang tetap, yaitu berkas piutang sepuluh rekaman berukuran 34 karakter per baris sebagaimana rancangan. Sepuluh rekaman cukup kecil untuk dihitung ulang dengan tangan, tetapi cukup beragam untuk menguji setiap bucket. Nilai pokoknya sengaja memuat digit sen nonnol, dan tanggalnya memuat tiga kasus batas, yaitu umur tepat 30, 60, dan 90 hari dari tanggal proses 20261130.
F10001 ALI 20261115 012500050
F10002 BUDI 20261031 007500000
F10003 CITRA 20261025 022500075
F10004 DEWI 20261001 009800025
F10005 EKA 20260918 014500000
F10006 FAJAR 20260901 006000040
F10007 GITA 20260820 031000000
F10008 HANA 20260802 008755060
F10009 INDRA 20261122 001500000
F10010 JOKO 20260928 011500020Baris pertama dan kedua memuat umur 15 dan 30 hari, sedangkan baris keempat dan keenam memuat umur 60 dan 90 hari. Rekaman dengan umur 102 dan 120 hari menguji bucket keempat. Susunan ini membuat setiap aturan rancangan memiliki bukti pada berkas uji, dan setiap angka pada keluaran nanti dapat ditelusuri kembali ke baris sumbernya. Berkas uji disertakan sebagai aset pada bundle topik, sehingga seluruh keluaran pada topik ini dapat direproduksi tanpa mengetik ulang datanya. Penempatan rekaman yang sengaja tidak berurutan menurut bucket-nya, misalnya F10009 pada baris kesembilan yang umurnya paling pendek, juga menguji bahwa program tidak bergantung pada urutan masukan.
Langkah 1: membaca dan menghitung rekaman#
Langkah pertama hanya membaca berkas dari awal sampai akhir sambil menghitung rekamannya. Program sederhana ini menjadi titik pemeriksaan pertama karena keberhasilannya membuktikan tiga hal sekaligus, yaitu nama berkas benar, lebar rekaman sesuai deskripsi FD, dan perulangan berhenti pada akhir berkas.
IDENTIFICATION DIVISION.
PROGRAM-ID. LANGKAH1.
*> Titik pemeriksaan 1: menghitung jumlah rekaman piutang.
ENVIRONMENT DIVISION.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
SELECT PIUTANG-INPUT ASSIGN TO "piutang.dat"
ORGANIZATION IS LINE SEQUENTIAL
FILE STATUS IS WS-STATUS.
DATA DIVISION.
FILE SECTION.
FD PIUTANG-INPUT.
01 REK-PIUTANG.
05 RP-FAKTUR PIC X(6).
05 FILLER PIC X.
05 RP-NAMA PIC X(8).
05 FILLER PIC X.
05 RP-TGL PIC 9(8).
05 FILLER PIC X.
05 RP-NILAI PIC 9(7)V99.
WORKING-STORAGE SECTION.
01 WS-STATUS PIC XX VALUE "00".
01 WS-EOL PIC X VALUE "N".
88 SELESAI VALUE "Y".
01 WS-JML-REC PIC 9(3) VALUE 0.
01 WS-JML-REC-ED PIC ZZ9.
PROCEDURE DIVISION.
UTAMA.
OPEN INPUT PIUTANG-INPUT
IF WS-STATUS NOT = "00"
DISPLAY "OPEN gagal, status " WS-STATUS
STOP RUN
END-IF
PERFORM UNTIL SELESAI
READ PIUTANG-INPUT
AT END MOVE "Y" TO WS-EOL
NOT AT END ADD 1 TO WS-JML-REC
END-READ
END-PERFORM
DISPLAY "Status READ terakhir : " WS-STATUS
MOVE WS-JML-REC TO WS-JML-REC-ED
DISPLAY "Jumlah rekaman dibaca : " WS-JML-REC-ED
CLOSE PIUTANG-INPUT
STOP RUN.Status READ terakhir : 10
Jumlah rekaman dibaca : 10Angka 10 sama dengan jumlah baris berkas uji yang dapat dihitung secara manual, dan status READ terakhir 10 menandakan kondisi at end yang normal. Pembacaan hanya terjadi pada satu tempat, yaitu di dalam perulangan PERFORM UNTIL SELESAI, sehingga tidak ada rekaman yang terlewat atau terbaca dua kali. Klausa NOT AT END memisahkan pekerjaan per rekaman dari penanganan akhir berkas, sehingga penghitung hanya bertambah pada rekaman yang benar-benar terbaca. Pengujian status pada OPEN juga sudah dipasang sejak langkah ini, sehingga program berhenti dengan pesan apabila berkas gagal dibuka. Kompilasi program dengan perintah berikut, kemudian jalankan ./langkah1.
# kompilasi program langkah 1
cobc -x langkah1.cblLangkah 2: menghitung umur dan bucket#
Langkah kedua menambahkan penghitungan umur dan penentuan bucket untuk setiap rekaman, lalu mencetak rinciannya. Empat variabel kerja baru ditambahkan pada langkah ini, yaitu WS-TGL-PROSES sebagai tanggal proses, WS-UMUR untuk menyimpan selisih hari, WS-UMUR-ED untuk hasil edit umur, dan WS-BUCKET untuk menyimpan nomor bucket hasil pemilihan. Seluruh perhitungan ditempatkan pada paragraf PROSES-REKAMAN yang dipanggil dari klausa NOT AT END, sehingga struktur program siap menampung akumulasi pada langkah berikutnya. Pencetakan rincian per rekaman menjadi inti titik pemeriksaan ini, karena setiap baris keluarannya dapat dibandingkan langsung dengan perhitungan kalender manual.
IDENTIFICATION DIVISION.
PROGRAM-ID. LANGKAH2.
*> Titik pemeriksaan 2: umur dan bucket untuk setiap rekaman.
ENVIRONMENT DIVISION.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
SELECT PIUTANG-INPUT ASSIGN TO "piutang.dat"
ORGANIZATION IS LINE SEQUENTIAL
FILE STATUS IS WS-STATUS.
DATA DIVISION.
FILE SECTION.
FD PIUTANG-INPUT.
01 REK-PIUTANG.
05 RP-FAKTUR PIC X(6).
05 FILLER PIC X.
05 RP-NAMA PIC X(8).
05 FILLER PIC X.
05 RP-TGL PIC 9(8).
05 FILLER PIC X.
05 RP-NILAI PIC 9(7)V99.
WORKING-STORAGE SECTION.
01 WS-STATUS PIC XX VALUE "00".
01 WS-EOL PIC X VALUE "N".
88 SELESAI VALUE "Y".
01 WS-JML-REC PIC 9(3) VALUE 0.
01 WS-JML-REC-ED PIC ZZ9.
01 WS-TGL-PROSES PIC 9(8) VALUE 20261130.
01 WS-UMUR PIC 9(3) VALUE 0.
01 WS-UMUR-ED PIC ZZ9.
01 WS-BUCKET PIC 9 VALUE 0.
PROCEDURE DIVISION.
UTAMA.
OPEN INPUT PIUTANG-INPUT
IF WS-STATUS NOT = "00"
DISPLAY "OPEN gagal, status " WS-STATUS
STOP RUN
END-IF
DISPLAY "FAKTUR NAMA TANGGAL UMUR BUCKET"
PERFORM UNTIL SELESAI
READ PIUTANG-INPUT
AT END MOVE "Y" TO WS-EOL
NOT AT END ADD 1 TO WS-JML-REC
PERFORM PROSES-REKAMAN
END-READ
END-PERFORM
MOVE WS-JML-REC TO WS-JML-REC-ED
DISPLAY "Jumlah rekaman dibaca : " WS-JML-REC-ED
CLOSE PIUTANG-INPUT
STOP RUN.
PROSES-REKAMAN.
COMPUTE WS-UMUR = FUNCTION INTEGER-OF-DATE(WS-TGL-PROSES)
- FUNCTION INTEGER-OF-DATE(RP-TGL)
EVALUATE TRUE
WHEN WS-UMUR <= 30
MOVE 1 TO WS-BUCKET
WHEN WS-UMUR <= 60
MOVE 2 TO WS-BUCKET
WHEN WS-UMUR <= 90
MOVE 3 TO WS-BUCKET
WHEN OTHER
MOVE 4 TO WS-BUCKET
END-EVALUATE
MOVE WS-UMUR TO WS-UMUR-ED
DISPLAY RP-FAKTUR " " RP-NAMA " " RP-TGL
" " WS-UMUR-ED " " WS-BUCKET.FAKTUR NAMA TANGGAL UMUR BUCKET
F10001 ALI 20261115 15 1
F10002 BUDI 20261031 30 1
F10003 CITRA 20261025 36 2
F10004 DEWI 20261001 60 2
F10005 EKA 20260918 73 3
F10006 FAJAR 20260901 90 3
F10007 GITA 20260820 102 4
F10008 HANA 20260802 120 4
F10009 INDRA 20261122 8 1
F10010 JOKO 20260928 63 3
Jumlah rekaman dibaca : 10Batas atas setiap bucket terbaca pada keluaran, yaitu F10002 dengan umur 30 masuk bucket 1, F10004 dengan umur 60 masuk bucket 2, dan F10006 dengan umur 90 masuk bucket 3. Rekaman F10007 dan F10008 dengan umur di atas 90 jatuh ke bucket 4 melalui WHEN OTHER. Selisih INTEGER-OF-DATE juga terbukti menangani panjang bulan dengan benar, misalnya umur F10006 yang fakturanya bertanggal 1 September 2026, tepat 90 hari sebelum tanggal proses 30 November 2026. Kompilasi dengan perintah berikut, kemudian jalankan ./langkah2.
# kompilasi program langkah 2
cobc -x langkah2.cblLangkah 3: laporan akhir dengan total kontrol#
Langkah ketiga menyempurnakan program menjadi laporan akhir. Setiap rekaman kini juga diakumulasikan ke tabel jumlah rekaman per bucket dan tabel jumlah nilai per bucket, sedangkan total nilai keseluruhan bertambah pula. Setelah berkas habis, program mencetak rekap per bucket melalui PERFORM VARYING, kemudian menjumlahkan keempat bucket dan membandingkannya dengan total sebelum mencetak hasil pemeriksaan kontrol.
IDENTIFICATION DIVISION.
PROGRAM-ID. AGING-PIUTANG.
*> Laporan aging piutang dengan rekap bucket dan total kontrol.
ENVIRONMENT DIVISION.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
SELECT PIUTANG-INPUT ASSIGN TO "piutang.dat"
ORGANIZATION IS LINE SEQUENTIAL
FILE STATUS IS WS-STATUS.
DATA DIVISION.
FILE SECTION.
FD PIUTANG-INPUT.
01 REK-PIUTANG.
05 RP-FAKTUR PIC X(6).
05 FILLER PIC X.
05 RP-NAMA PIC X(8).
05 FILLER PIC X.
05 RP-TGL PIC 9(8).
05 FILLER PIC X.
05 RP-NILAI PIC 9(7)V99.
WORKING-STORAGE SECTION.
01 WS-STATUS PIC XX VALUE "00".
01 WS-EOL PIC X VALUE "N".
88 SELESAI VALUE "Y".
01 WS-TGL-PROSES PIC 9(8) VALUE 20261130.
01 WS-UMUR PIC 9(3) VALUE 0.
01 WS-BUCKET PIC 9 VALUE 0.
01 WS-IDX PIC 9 VALUE 0.
01 WS-JML-REC PIC 9(3) VALUE 0.
01 WS-REK-BUCKET PIC 9(3) VALUE 0 OCCURS 4 TIMES.
01 WS-NILAI-BUCKET PIC 9(9)V99 VALUE 0 OCCURS 4 TIMES.
01 WS-TOTAL PIC 9(9)V99 VALUE 0.
01 WS-JUMLAH-BUCKET PIC 9(9)V99 VALUE 0.
01 WS-JUMLAH-REC-BKT PIC 9(3) VALUE 0.
01 WS-LABEL-BKT PIC X(12).
01 WS-UMUR-ED PIC ZZ9.
01 WS-REC-ED PIC ZZ9.
01 WS-NILAI-ED PIC Z,ZZZ,ZZ9.99.
01 WS-VAL-B-ED PIC Z,ZZZ,ZZZ,ZZ9.99.
PROCEDURE DIVISION.
UTAMA.
OPEN INPUT PIUTANG-INPUT
IF WS-STATUS NOT = "00"
DISPLAY "OPEN gagal, status " WS-STATUS
STOP RUN
END-IF
DISPLAY "LAPORAN AGING PIUTANG"
DISPLAY "Tanggal proses : " WS-TGL-PROSES
DISPLAY "--------------------------------------------"
DISPLAY "FAKTUR NAMA TANGGAL UMUR NILAI POKOK"
PERFORM UNTIL SELESAI
READ PIUTANG-INPUT
AT END MOVE "Y" TO WS-EOL
NOT AT END ADD 1 TO WS-JML-REC
PERFORM PROSES-REKAMAN
END-READ
END-PERFORM
CLOSE PIUTANG-INPUT
PERFORM CETAK-REKAP
PERFORM CETAK-KONTROL
STOP RUN.
PROSES-REKAMAN.
COMPUTE WS-UMUR = FUNCTION INTEGER-OF-DATE(WS-TGL-PROSES)
- FUNCTION INTEGER-OF-DATE(RP-TGL)
EVALUATE TRUE
WHEN WS-UMUR <= 30
MOVE 1 TO WS-BUCKET
WHEN WS-UMUR <= 60
MOVE 2 TO WS-BUCKET
WHEN WS-UMUR <= 90
MOVE 3 TO WS-BUCKET
WHEN OTHER
MOVE 4 TO WS-BUCKET
END-EVALUATE
ADD 1 TO WS-REK-BUCKET(WS-BUCKET)
ADD RP-NILAI TO WS-NILAI-BUCKET(WS-BUCKET)
ADD RP-NILAI TO WS-TOTAL
MOVE WS-UMUR TO WS-UMUR-ED
MOVE RP-NILAI TO WS-NILAI-ED
DISPLAY RP-FAKTUR " " RP-NAMA " " RP-TGL
" " WS-UMUR-ED " " WS-NILAI-ED.
CETAK-REKAP.
DISPLAY "--------------------------------------------"
DISPLAY "REKAP PER BUCKET UMUR"
PERFORM CETAK-SATU-BUCKET
VARYING WS-IDX FROM 1 BY 1 UNTIL WS-IDX > 4.
CETAK-SATU-BUCKET.
EVALUATE WS-IDX
WHEN 1 MOVE " 0-30 hari" TO WS-LABEL-BKT
WHEN 2 MOVE " 31-60 hari" TO WS-LABEL-BKT
WHEN 3 MOVE " 61-90 hari" TO WS-LABEL-BKT
WHEN 4 MOVE " >90 hari " TO WS-LABEL-BKT
END-EVALUATE
MOVE WS-REK-BUCKET(WS-IDX) TO WS-REC-ED
MOVE WS-NILAI-BUCKET(WS-IDX) TO WS-VAL-B-ED
DISPLAY WS-LABEL-BKT " : " WS-REC-ED " rekaman "
WS-VAL-B-ED.
CETAK-KONTROL.
COMPUTE WS-JUMLAH-BUCKET = WS-NILAI-BUCKET(1)
+ WS-NILAI-BUCKET(2) + WS-NILAI-BUCKET(3)
+ WS-NILAI-BUCKET(4)
COMPUTE WS-JUMLAH-REC-BKT = WS-REK-BUCKET(1)
+ WS-REK-BUCKET(2) + WS-REK-BUCKET(3)
+ WS-REK-BUCKET(4)
DISPLAY "--------------------------------------------"
DISPLAY "TOTAL KONTROL"
MOVE WS-JML-REC TO WS-REC-ED
DISPLAY "Rekaman dibaca : " WS-REC-ED
MOVE WS-JUMLAH-REC-BKT TO WS-REC-ED
DISPLAY "Rekaman empat bucket : " WS-REC-ED
MOVE WS-TOTAL TO WS-VAL-B-ED
DISPLAY "Total nilai masukan : " WS-VAL-B-ED
MOVE WS-JUMLAH-BUCKET TO WS-VAL-B-ED
DISPLAY "Jumlah nilai bucket : " WS-VAL-B-ED
IF WS-JUMLAH-BUCKET = WS-TOTAL
AND WS-JUMLAH-REC-BKT = WS-JML-REC
DISPLAY "Pemeriksaan kontrol : COCOK"
ELSE
DISPLAY "Pemeriksaan kontrol : TIDAK COCOK"
END-IF.LAPORAN AGING PIUTANG
Tanggal proses : 20261130
--------------------------------------------
FAKTUR NAMA TANGGAL UMUR NILAI POKOK
F10001 ALI 20261115 15 125,000.50
F10002 BUDI 20261031 30 75,000.00
F10003 CITRA 20261025 36 225,000.75
F10004 DEWI 20261001 60 98,000.25
F10005 EKA 20260918 73 145,000.00
F10006 FAJAR 20260901 90 60,000.40
F10007 GITA 20260820 102 310,000.00
F10008 HANA 20260802 120 87,550.60
F10009 INDRA 20261122 8 15,000.00
F10010 JOKO 20260928 63 115,000.20
--------------------------------------------
REKAP PER BUCKET UMUR
0-30 hari : 3 rekaman 215,000.50
31-60 hari : 2 rekaman 323,001.00
61-90 hari : 3 rekaman 320,000.60
>90 hari : 2 rekaman 397,550.60
--------------------------------------------
TOTAL KONTROL
Rekaman dibaca : 10
Rekaman empat bucket : 10
Total nilai masukan : 1,255,552.70
Jumlah nilai bucket : 1,255,552.70
Pemeriksaan kontrol : COCOKPemeriksaan kontrol menyatakan COCOK pada keluaran. Jumlah rekaman yang dibaca, yaitu 10, sama dengan jumlah rekaman keempat bucket, dan total nilai masukan 1,255,552.70 sama dengan jumlah nilai keempat bucket. Kedua kecocokan itu bukan kebetulan, melainkan bukti bahwa tidak ada rekaman yang terlewat atau terhitung dua kali. Setiap rekap juga dapat dihitung ulang dari detail, misalnya bucket pertama yang berjumlah 215,000.50 merupakan penjumlahan nilai F10001, F10002, dan F10009. Kompilasi program akhir dengan perintah berikut, kemudian jalankan ./aging.
# kompilasi program laporan aging utuh
cobc -x aging.cblLangkah 4: menguji status berkas dan berkas kosong#
Langkah pamungkas tidak menambah kemampuan laporan, melainkan menguji program pada kondisi tak normal. Program uji berikut menerima nama berkas dari argumen command line, membukanya dengan FILE STATUS, lalu membaca satu rekaman perdana. Tiga kondisi diuji, yaitu berkas berisi, berkas tidak ada, dan berkas kosong.
IDENTIFICATION DIVISION.
PROGRAM-ID. UJI-STATUS.
*> Menguji FILE STATUS pada berkas yang disebut di argumen.
ENVIRONMENT DIVISION.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
SELECT PIUTANG-INPUT ASSIGN TO WS-NAMA-BERKAS
ORGANIZATION IS LINE SEQUENTIAL
FILE STATUS IS WS-STATUS.
DATA DIVISION.
FILE SECTION.
FD PIUTANG-INPUT.
01 REK-PIUTANG PIC X(34).
WORKING-STORAGE SECTION.
01 WS-NAMA-BERKAS PIC X(20).
01 WS-STATUS PIC XX VALUE "00".
01 WS-EOL PIC X VALUE "N".
88 SELESAI VALUE "Y".
PROCEDURE DIVISION.
UTAMA.
ACCEPT WS-NAMA-BERKAS FROM COMMAND-LINE
IF WS-NAMA-BERKAS = SPACES
DISPLAY "Pemakaian : ./uji-status nama-berkas"
STOP RUN
END-IF
OPEN INPUT PIUTANG-INPUT
DISPLAY "Status OPEN : " WS-STATUS
IF WS-STATUS NOT = "00"
DISPLAY "Berkas gagal dibuka, program dihentikan"
STOP RUN
END-IF
READ PIUTANG-INPUT
AT END MOVE "Y" TO WS-EOL
END-READ
DISPLAY "Status READ perdana : " WS-STATUS
IF SELESAI
DISPLAY "Berkas kosong, tidak ada rekaman diproses"
ELSE
DISPLAY "Berkas berisi, rekaman perdana terbaca"
END-IF
CLOSE PIUTANG-INPUT
STOP RUN.Jalankan ./uji-status piutang.dat. Status OPEN 00 dan status READ perdana 00 menandakan berkas berhasil dibuka dan berisi rekaman.
Status OPEN : 00
Status READ perdana : 00
Berkas berisi, rekaman perdana terbacaJalankan ./uji-status hilang.dat dengan nama berkas yang tidak ada di direktori. Status OPEN 35 merupakan error permanen, dan program berhenti sebelum satu rekaman pun dicoba dibaca.
Status OPEN : 35
Berkas gagal dibuka, program dihentikanBuat berkas kosong dengan perintah touch kosong.dat, jalankan ./uji-status kosong.dat, lalu hapus berkas uji tersebut. OPEN menghasilkan status 00 karena berkasnya ada, sedangkan READ perdana langsung menghasilkan status 10 karena tidak ada rekaman yang dapat dibaca.
Status OPEN : 00
Status READ perdana : 10
Berkas kosong, tidak ada rekaman diprosesProgram aging pada langkah ketiga menerapkan perlindungan yang sama, yaitu memeriksa status OPEN sebelum laporan dicetak, sehingga laporan tidak pernah dihasilkan dari berkas yang gagal dibuka. Program uji status dikompilasi dengan perintah berikut, dan keempat program pada topik ini menggunakan cara kompilasi yang sama.
# kompilasi program uji status berkas
cobc -x uji-status.cblKesalahan umum#
- Melompati titik pemeriksaan. Dua kemampuan ditambah sekaligus, laporan berubah di banyak tempat, dan sumber kesalahannya tidak terlacak. Tambahkan satu kemampuan, jalankan program, bandingkan keluarannya, kemudian lanjutkan ke langkah berikutnya.
- Berkas uji tanpa kasus batas. Umur tepat 30, 60, atau 90 hari tidak terwakili, sehingga kesalahan batas bucket lolos tanpa terlihat. Sertakan setiap batas rancangan pada berkas uji.
- Menganggap status 10 sebagai error. Percabangan memperlakukan at end sebagai kegagalan, padahal status itu adalah akhir normal berkas. Perlakukan status 10 sebagai penanda selesai, dan pastikan status 00 sebelum pekerjaan berlanjut.
Ringkasan#
- Pembangunan bertahap menambah satu kemampuan per langkah dan mengakhiri setiap langkah dengan titik pemeriksaan yang keluarannya dapat dibandingkan dengan perhitungan manual.
- Berkas uji sepuluh rekaman memuat digit sen nonnol dan ketiga batas bucket, sehingga setiap aturan rancangan teruji.
- Laporan akhir mengakumulasi rekaman dan nilai per bucket, lalu memverifikasi jumlah bucket terhadap total masukan dengan hasil COCOK.
- FILE STATUS menangani berkas tidak ada melalui status 35 dan berkas kosong melalui READ perdana berstatus 10.
Referensi#
- GnuCOBOL — Free Software Foundation — Situs proyek GnuCOBOL 3.2, compiler yang digunakan untuk mengompilasi dan menjalankan seluruh program pada topik ini.
- GnuCOBOL Manual — Free Software Foundation — Manual resmi GnuCOBOL yang merinci cobc, FILE STATUS, dan ACCEPT FROM COMMAND-LINE.
- IBM Enterprise COBOL for z/OS documentation — IBM — Dokumentasi resmi nilai FILE STATUS dan fungsi intrinsik tanggal pada COBOL komputer pusat.