Semakin komplek fungsi dan program yang dibuat, maka semakin banyak celah yang memungkinkan program terdapat kesalahan. Sebagai contoh, berikut ini adalah error-error yang pernah terjadi di saat menjalankan beberapa kode di module-module sebelumnya: Show
Di python, setidaknya ada 2 jenis error, yaitu syntax error dan exception.
Kedua jenis error tersebut termasuk yang mudah ditemukan dan diperbaiki, karena biasanya Python bisa menunjukkan lokasi error sebelum atau setelah program gagal dieksekusi. Ada jenis error yang lain yang paling sulit untuk ditemukan, yaitu logic error.
Error pada software juga biasa disebut sebagai bug. Dalam sejarah, bug pada software dapat menyebabkan hal yang sangat fatal, misalnya:
Oleh sebab itu, meskipun kita tidak sedang membuat program seperti contoh di atas, kehati-hatian dalam programming sangat penting. Bahkan walaupun kita yakin program yang kita buat sudah benar, namun pada saat dijalankan banyak situasi tidak ideal yang sebelumnya kita anggap tidak akan terjadi ternyata terjadi. Sebagai contoh kerusakan hardware, user yang mengakses program kita secara bersamaan terlalu banyak, user memasukkan input yang diluar dugaan, dan sebagainya, yang pada akhirnya membuat program kita menjadi error. Selanjutnya mari kita lihat bagaimana langkah-langkah dalam menghindari dan mengatasi bug pada program. Defensive ProgrammingDefensive programming adalah sebuah pendekatan dalam memprogram dimana programmer selalu berhati-hati dan memikirkan berbagai kondisi yang memungkinkan terjadinya kesalahan, serta berusaha mengantisipasinya. Mindset defensive programming juga mencari cara paling efektif membangun kode yang memudahkan pencarian dan perbaikan bug jika suatu saat terjadi, terutama bug yang terkait logic error. Berikut adalah beberapa langkah umum dalam defensive programming:
AssertionAssertion adalah suatu pengecekan untuk memastikan suatu kondisi harus benar untuk bisa melakukan proses berikutnya. Mirip seperti if-statement, namun bedanya, jika kondisi assert ,9, maka program akan dihentikan. Sehingga assertion digunakan hanya untuk pengecekan yang krusial, yang jika assert ,9 maka program sebaiknya dihentikan. Sebagai contoh ada sebuah fungsi untuk menghitung luas sebuah segi empat berdasarkan koordinat dua buah titik, yaitu titik pojok kiri bawah, dan titik pojok kanan atas. Berikut kira-kira fungsi menghitung luas tersebut. def luas_segiempat(x0, y0, x1, y1): """ Menghitung luas segi empat berdasarkan koordinat 2 titik: pojok kiri bawah (x0, y0), dan kanan atas (x1, y1). """ deltax = x1 - x0 deltay = y1 - y0 return deltax * deltay segi4_1 = luas_segiempat(1, 1, 3, 3) segi4_2 = luas_segiempat(2, 4, 3, 3) print(segi4_1 + segi4_2) Terlihat bahwa ketika kode di atas dijalankan, maka akan tertampil nilai 3 yang merupakan penjumlahan luas kedua segi. Sekilas tidak ada yang aneh, namun jika dilihat dengan teliti akan ditemukan logic error. def luas_segiempat(x0, y0, x1, y1): """ Menghitung luas segi empat berdasarkan koordinat 2 titik: pojok kiri bawah (x0, y0), dan kanan atas (x1, y1). """ # untuk memastikan koordinat input sudah sesuai asumsi assert x0 < x1 and y0 < y1, "koordinat tidak valid" deltax = x1 - x0 deltay = y1 - y0 return deltax * deltay segi4_1 = luas_segiempat(1, 1, 3, 3) segi4_2 = luas_segiempat(2, 4, 3, 3) print(segi4_1 + segi4_2)1 saja harusnya memiliki luas def luas_segiempat(x0, y0, x1, y1): """ Menghitung luas segi empat berdasarkan koordinat 2 titik: pojok kiri bawah (x0, y0), dan kanan atas (x1, y1). """ # untuk memastikan koordinat input sudah sesuai asumsi assert x0 < x1 and y0 < y1, "koordinat tidak valid" deltax = x1 - x0 deltay = y1 - y0 return deltax * deltay segi4_1 = luas_segiempat(1, 1, 3, 3) segi4_2 = luas_segiempat(2, 4, 3, 3) print(segi4_1 + segi4_2)2, karena panjangnya def luas_segiempat(x0, y0, x1, y1): """ Menghitung luas segi empat berdasarkan koordinat 2 titik: pojok kiri bawah (x0, y0), dan kanan atas (x1, y1). """ # untuk memastikan koordinat input sudah sesuai asumsi assert x0 < x1 and y0 < y1, "koordinat tidak valid" deltax = x1 - x0 deltay = y1 - y0 return deltax * deltay segi4_1 = luas_segiempat(1, 1, 3, 3) segi4_2 = luas_segiempat(2, 4, 3, 3) print(segi4_1 + segi4_2)3 dan lebarnya def luas_segiempat(x0, y0, x1, y1): """ Menghitung luas segi empat berdasarkan koordinat 2 titik: pojok kiri bawah (x0, y0), dan kanan atas (x1, y1). """ # untuk memastikan koordinat input sudah sesuai asumsi assert x0 < x1 and y0 < y1, "koordinat tidak valid" deltax = x1 - x0 deltay = y1 - y0 return deltax * deltay segi4_1 = luas_segiempat(1, 1, 3, 3) segi4_2 = luas_segiempat(2, 4, 3, 3) print(segi4_1 + segi4_2)3. Namun totalnya penjumlahan malah berkurang menjadi def luas_segiempat(x0, y0, x1, y1): """ Menghitung luas segi empat berdasarkan koordinat 2 titik: pojok kiri bawah (x0, y0), dan kanan atas (x1, y1). """ # untuk memastikan koordinat input sudah sesuai asumsi assert x0 < x1 and y0 < y1, "koordinat tidak valid" deltax = x1 - x0 deltay = y1 - y0 return deltax * deltay segi4_1 = luas_segiempat(1, 1, 3, 3) segi4_2 = luas_segiempat(2, 4, 3, 3) print(segi4_1 + segi4_2)5. Hal ini dikarenakan def luas_segiempat(x0, y0, x1, y1): """ Menghitung luas segi empat berdasarkan koordinat 2 titik: pojok kiri bawah (x0, y0), dan kanan atas (x1, y1). """ # untuk memastikan koordinat input sudah sesuai asumsi assert x0 < x1 and y0 < y1, "koordinat tidak valid" deltax = x1 - x0 deltay = y1 - y0 return deltax * deltay segi4_1 = luas_segiempat(1, 1, 3, 3) segi4_2 = luas_segiempat(2, 4, 3, 3) print(segi4_1 + segi4_2)6 ternyata bernilai def luas_segiempat(x0, y0, x1, y1): """ Menghitung luas segi empat berdasarkan koordinat 2 titik: pojok kiri bawah (x0, y0), dan kanan atas (x1, y1). """ # untuk memastikan koordinat input sudah sesuai asumsi assert x0 < x1 and y0 < y1, "koordinat tidak valid" deltax = x1 - x0 deltay = y1 - y0 return deltax * deltay segi4_1 = luas_segiempat(1, 1, 3, 3) segi4_2 = luas_segiempat(2, 4, 3, 3) print(segi4_1 + segi4_2)7, yang merupakan penyebab terjadinya logic error. Setelah diperhatikan lebih lanjut, penyebab sebenarnya adalah input yang tidak sesuai asumsi, def luas_segiempat(x0, y0, x1, y1): """ Menghitung luas segi empat berdasarkan koordinat 2 titik: pojok kiri bawah (x0, y0), dan kanan atas (x1, y1). """ # untuk memastikan koordinat input sudah sesuai asumsi assert x0 < x1 and y0 < y1, "koordinat tidak valid" deltax = x1 - x0 deltay = y1 - y0 return deltax * deltay segi4_1 = luas_segiempat(1, 1, 3, 3) segi4_2 = luas_segiempat(2, 4, 3, 3) print(segi4_1 + segi4_2)8 ternyata lebih besar dari def luas_segiempat(x0, y0, x1, y1): """ Menghitung luas segi empat berdasarkan koordinat 2 titik: pojok kiri bawah (x0, y0), dan kanan atas (x1, y1). """ # untuk memastikan koordinat input sudah sesuai asumsi assert x0 < x1 and y0 < y1, "koordinat tidak valid" deltax = x1 - x0 deltay = y1 - y0 return deltax * deltay segi4_1 = luas_segiempat(1, 1, 3, 3) segi4_2 = luas_segiempat(2, 4, 3, 3) print(segi4_1 + segi4_2)9, sehingga titik --------------------------------------------------------------------------- AssertionError Traceback (most recent call last) in () 11 12 segi4_1 = luas_segiempat(1, 1, 3, 3) ---> 13 segi4_2 = luas_segiempat(2, 4, 3, 3) 14 print(segi4_1 + segi4_2) 15 in luas_segiempat(x0, y0, x1, y1) 4 5 # untuk memastikan koordinat input sudah sesuai asumsi ----> 6 assert x0 < x1 and y0 < y1, "koordinat tidak valid" 7 8 deltax = x1 - x0 AssertionError: koordinat tidak valid0 bukanlah titik pojok kiri bawah, melainkan kiri atas. Opsi Solusi Mari kita bahas beberapa opsi yang bisa digunakan untuk menghindari hal tersebut.
x0 = 2 y0 = 4 x1 = 3 y1 = 3 # cek (x0, y0) kiri bawah, dan (x1, y1) kanan atas if x0 < x1 and y0 < y1: # panggil fungsi else: # jangan panggil fungsi, keluarkan info ke user nilai salah Meskipun bisa dilakukan, tetapi tentu hal ini bukanlah solusi terbaik, karena orang kita sendiri atau orang lain mungkin saja lupa untuk menambahkan pengecekan tersebut, dan akhirnya berakibat fatal.
def luas_segiempat(x0, y0, x1, y1): """ Menghitung luas segi empat berdasarkan koordinat 2 titik: pojok kiri bawah (x0, y0), dan kanan atas (x1, y1). """ # cek (x0, y0) kiri bawah, dan (x1, y1) kanan atas if x0 < x1 and y0 < y1: deltax = x1 - x0 deltay = y1 - y0 return deltax * deltay segi4_1 = luas_segiempat(1, 1, 3, 3) segi4_2 = luas_segiempat(2, 4, 3, 3) print(segi4_1 + segi4_2) --------------------------------------------------------------------------- TypeError Traceback (most recent call last) in () 11 segi4_1 = luas_segiempat(1, 1, 3, 3) 12 segi4_2 = luas_segiempat(2, 4, 3, 3) ---> 13 print(segi4_1 + segi4_2) TypeError: unsupported operand type(s) for +: 'int' and 'NoneType' Ketika kondisi salah, maka fungsi luas_segiempat tidak mengeksekusi --------------------------------------------------------------------------- AssertionError Traceback (most recent call last) in () 11 12 segi4_1 = luas_segiempat(1, 1, 3, 3) ---> 13 segi4_2 = luas_segiempat(2, 4, 3, 3) 14 print(segi4_1 + segi4_2) 15 in luas_segiempat(x0, y0, x1, y1) 4 5 # untuk memastikan koordinat input sudah sesuai asumsi ----> 6 assert x0 < x1 and y0 < y1, "koordinat tidak valid" 7 8 deltax = x1 - x0 AssertionError: koordinat tidak valid1, sehingga nilai defaultnya adalah --------------------------------------------------------------------------- AssertionError Traceback (most recent call last) in () 11 12 segi4_1 = luas_segiempat(1, 1, 3, 3) ---> 13 segi4_2 = luas_segiempat(2, 4, 3, 3) 14 print(segi4_1 + segi4_2) 15 in luas_segiempat(x0, y0, x1, y1) 4 5 # untuk memastikan koordinat input sudah sesuai asumsi ----> 6 assert x0 < x1 and y0 < y1, "koordinat tidak valid" 7 8 deltax = x1 - x0 AssertionError: koordinat tidak valid2. Hal ini menyebabkan error saat ditambahkan dengan integer. Error ini akan menyulitkan kita atau orang lain, karena penyebab sebenarnya belum terlihat, yaitu koordinat tidak valid. Sehingga untuk memperbaikinya perlu penelusuran yang lebih lanjut, dan ini adalah salah satu hal yang coba dihindari pada prinsip defensive programming. Mengeset --------------------------------------------------------------------------- AssertionError Traceback (most recent call last) in () 11 12 segi4_1 = luas_segiempat(1, 1, 3, 3) ---> 13 segi4_2 = luas_segiempat(2, 4, 3, 3) 14 print(segi4_1 + segi4_2) 15 in luas_segiempat(x0, y0, x1, y1) 4 5 # untuk memastikan koordinat input sudah sesuai asumsi ----> 6 assert x0 < x1 and y0 < y1, "koordinat tidak valid" 7 8 deltax = x1 - x0 AssertionError: koordinat tidak valid1 dengan 0 tentu saja bisa menghindari TypeError tersebut, tapi malah menimbulkan error yang lebih berbahaya, yaitu LogicError seperti sebelumnya. Penggunaan Assertion Salah satu solusi yang lebih baik adalah menggunakan assertion. Sebelumnya kita lihat dulu bentuk statement assertion pada python berikut ini: assert ,
Mari kita lihat penggunaannya pada fungsi. def luas_segiempat(x0, y0, x1, y1): """ Menghitung luas segi empat berdasarkan koordinat 2 titik: pojok kiri bawah (x0, y0), dan kanan atas (x1, y1). """ # untuk memastikan koordinat input sudah sesuai asumsi assert x0 < x1 and y0 < y1, "koordinat tidak valid" deltax = x1 - x0 deltay = y1 - y0 return deltax * deltay segi4_1 = luas_segiempat(1, 1, 3, 3) segi4_2 = luas_segiempat(2, 4, 3, 3) print(segi4_1 + segi4_2) --------------------------------------------------------------------------- AssertionError Traceback (most recent call last) in () 11 12 segi4_1 = luas_segiempat(1, 1, 3, 3) ---> 13 segi4_2 = luas_segiempat(2, 4, 3, 3) 14 print(segi4_1 + segi4_2) 15 in luas_segiempat(x0, y0, x1, y1) 4 5 # untuk memastikan koordinat input sudah sesuai asumsi ----> 6 assert x0 < x1 and y0 < y1, "koordinat tidak valid" 7 8 deltax = x1 - x0 AssertionError: koordinat tidak valid Terlihat bahwa program akan memunculkan Assertion Error beserta pesannya. Dengan demikian maka siapapun yang menggunakan fungsi tersebut akan segera menyadari adanya kesalahan dan tau secara persis di mana letak kesalahan tersebut. Sekali lagi perlu diperhatikan, Assertion akan membuat program berhenti, untuk itu pastikan hanya menggunakan assertion di saat tidak ada opsi lain yang lebih baik tanpa harus membuat program berhenti. Exception HandlingSebelumnya kita telah membahas tentang perbedaan syntax error dengan exception, dimana exception muncul saat program sedang dieksekusi. Ada banyak jenis exception bawaan Python (built-in exception), di antaranya:
Untuk lengkapnya bisa dilihat pada: https://docs.python.org/3/library/exceptions.html Dalam membuat program, selain correctness (seperti yang ditekankan pada penggunaan assertion) kita juga perlu memperhatikan aspek robustness atau ketangguhan. Program yang robust artinya tidak mudah crash atau terhenti walau terjadi error. Sekilas kedua prinsip tersebut terasa bertentangan, namun sebenarnya, masing-masing dapat diterapkan pada kondisi yang tepat. Sebagai contoh, anggaplah kita membuat program yang meminta inputan user berupa 4 buah integer sebagai representasi 2 koordinat titik pojok (kiri bawah dan kanan atas) pada segi empat, yaitu x0, y0, x1, y1. x0 = int(input("Koordinat x0:")) y0 = int(input("Koordinat y0:")) x1 = int(input("Koordinat x1:")) y1 = int(input("Koordinat y1:")) luas = luas_segiempat(x0, y0, x1, y1) print("Luas segi empat adalah:", luas) --------------------------------------------------------------------------- ValueError Traceback (most recent call last) in () ----> 1 x0 = int(input("Koordinat x0:")) 2 y0 = int(input("Koordinat y0:")) 3 x1 = int(input("Koordinat x1:")) 4 y1 = int(input("Koordinat y1:")) 5 ValueError: invalid literal for int() with base 10: '' Ternyata, saat dijalankan user yang niat awalnya memasukkan nilai x0 = int(input("Koordinat x0:")) y0 = int(input("Koordinat y0:")) x1 = int(input("Koordinat x1:")) y1 = int(input("Koordinat y1:")) luas = luas_segiempat(x0, y0, x1, y1) print("Luas segi empat adalah:", luas)0 ternyata tidak sengaja memasukkan x0 = int(input("Koordinat x0:")) y0 = int(input("Koordinat y0:")) x1 = int(input("Koordinat x1:")) y1 = int(input("Koordinat y1:")) luas = luas_segiempat(x0, y0, x1, y1) print("Luas segi empat adalah:", luas)1, sehingga akan muncul exception berupa x0 = int(input("Koordinat x0:")) y0 = int(input("Koordinat y0:")) x1 = int(input("Koordinat x1:")) y1 = int(input("Koordinat y1:")) luas = luas_segiempat(x0, y0, x1, y1) print("Luas segi empat adalah:", luas)2. Kesalahan user seperti ini sangat mungkin terjadi, baik disengaja maupun tidak disengaja. Oleh karena itu, akan lebih baik jika kesalahan ini bisa ditangani sehingga program tidak langsung terhenti, melainkan dapat tetap berjalan dengan memberikan informasi kepada user untuk memperbaikinya. Penanganan exception, agar program tidak terhenti biasa disebut dengan exception handling. Penggunaan Exception Handling try: # kode yang mungkin menimbulkan exception except: # apa yang dilakukan jika terjadi exception else: # dijalankan jika kode pada try tidak menimbulkan exception
Berikut ini contoh penggunaan x0 = int(input("Koordinat x0:")) y0 = int(input("Koordinat y0:")) x1 = int(input("Koordinat x1:")) y1 = int(input("Koordinat y1:")) luas = luas_segiempat(x0, y0, x1, y1) print("Luas segi empat adalah:", luas)6 untuk menghindari error akibat kesalahan input. x0 = 2 y0 = 4 x1 = 3 y1 = 3 # cek (x0, y0) kiri bawah, dan (x1, y1) kanan atas if x0 < x1 and y0 < y1: # panggil fungsi else: # jangan panggil fungsi, keluarkan info ke user nilai salah0 x0 = 2 y0 = 4 x1 = 3 y1 = 3 # cek (x0, y0) kiri bawah, dan (x1, y1) kanan atas if x0 < x1 and y0 < y1: # panggil fungsi else: # jangan panggil fungsi, keluarkan info ke user nilai salah1 x0 = 2 y0 = 4 x1 = 3 y1 = 3 # cek (x0, y0) kiri bawah, dan (x1, y1) kanan atas if x0 < x1 and y0 < y1: # panggil fungsi else: # jangan panggil fungsi, keluarkan info ke user nilai salah2 Terlihat bahwa jika diinputkan seperti sebelumnya, yaitu x0 = int(input("Koordinat x0:")) y0 = int(input("Koordinat y0:")) x1 = int(input("Koordinat x1:")) y1 = int(input("Koordinat y1:")) luas = luas_segiempat(x0, y0, x1, y1) print("Luas segi empat adalah:", luas)1 maka program tetap akan terhenti, namun sekarang program berhenti bukan saat mengeksekusi statement assignment --------------------------------------------------------------------------- ValueError Traceback (most recent call last) in () ----> 1 x0 = int(input("Koordinat x0:")) 2 y0 = int(input("Koordinat y0:")) 3 x1 = int(input("Koordinat x1:")) 4 y1 = int(input("Koordinat y1:")) 5 ValueError: invalid literal for int() with base 10: ''5 yang diberikan input tidak valid berupa --------------------------------------------------------------------------- ValueError Traceback (most recent call last) in () ----> 1 x0 = int(input("Koordinat x0:")) 2 y0 = int(input("Koordinat y0:")) 3 x1 = int(input("Koordinat x1:")) 4 y1 = int(input("Koordinat y1:")) 5 ValueError: invalid literal for int() with base 10: ''6. Hal ini menunjukkan bahwa exception yang timbul pada bagian tersebut sudah bisa ditangani oleh x0 = int(input("Koordinat x0:")) y0 = int(input("Koordinat y0:")) x1 = int(input("Koordinat x1:")) y1 = int(input("Koordinat y1:")) luas = luas_segiempat(x0, y0, x1, y1) print("Luas segi empat adalah:", luas)6. Error yang terjadi sekarang yaitu dikarenakan saat memanggil fungsi --------------------------------------------------------------------------- ValueError Traceback (most recent call last) in () ----> 1 x0 = int(input("Koordinat x0:")) 2 y0 = int(input("Koordinat y0:")) 3 x1 = int(input("Koordinat x1:")) 4 y1 = int(input("Koordinat y1:")) 5 ValueError: invalid literal for int() with base 10: ''8, argument --------------------------------------------------------------------------- ValueError Traceback (most recent call last) in () ----> 1 x0 = int(input("Koordinat x0:")) 2 y0 = int(input("Koordinat y0:")) 3 x1 = int(input("Koordinat x1:")) 4 y1 = int(input("Koordinat y1:")) 5 ValueError: invalid literal for int() with base 10: ''5 tidak memiliki nilai. Hal ini dikarenakan statement assignment --------------------------------------------------------------------------- ValueError Traceback (most recent call last) in () ----> 1 x0 = int(input("Koordinat x0:")) 2 y0 = int(input("Koordinat y0:")) 3 x1 = int(input("Koordinat x1:")) 4 y1 = int(input("Koordinat y1:")) 5 ValueError: invalid literal for int() with base 10: ''5 tidak berhasil dieksekusi, walau program tidak berhenti saat itu. Salah satu solusinya, kita bisa menggunakan x0 = int(input("Koordinat x0:")) y0 = int(input("Koordinat y0:")) x1 = int(input("Koordinat x1:")) y1 = int(input("Koordinat y1:")) luas = luas_segiempat(x0, y0, x1, y1) print("Luas segi empat adalah:", luas)5 agar pemanggilan fungsi dan print luas hanya dilakukan jika kode x0 = int(input("Koordinat x0:")) y0 = int(input("Koordinat y0:")) x1 = int(input("Koordinat x1:")) y1 = int(input("Koordinat y1:")) luas = luas_segiempat(x0, y0, x1, y1) print("Luas segi empat adalah:", luas)3 dapat dieksekusi dengan sempurna. x0 = 2 y0 = 4 x1 = 3 y1 = 3 # cek (x0, y0) kiri bawah, dan (x1, y1) kanan atas if x0 < x1 and y0 < y1: # panggil fungsi else: # jangan panggil fungsi, keluarkan info ke user nilai salah3 x0 = 2 y0 = 4 x1 = 3 y1 = 3 # cek (x0, y0) kiri bawah, dan (x1, y1) kanan atas if x0 < x1 and y0 < y1: # panggil fungsi else: # jangan panggil fungsi, keluarkan info ke user nilai salah1 Program di atas jika diberikan input yang tidak valid maka tidak akan mengeluarkan error. Sebagai tambahan, bagaimana jika kita ingin memberikan kesempatan kepada user untuk mengulangi input maksimal sebanyak 3 kali? Anda bisa menggunakan contoh kode di bawah ini. x0 = 2 y0 = 4 x1 = 3 y1 = 3 # cek (x0, y0) kiri bawah, dan (x1, y1) kanan atas if x0 < x1 and y0 < y1: # panggil fungsi else: # jangan panggil fungsi, keluarkan info ke user nilai salah5 x0 = 2 y0 = 4 x1 = 3 y1 = 3 # cek (x0, y0) kiri bawah, dan (x1, y1) kanan atas if x0 < x1 and y0 < y1: # panggil fungsi else: # jangan panggil fungsi, keluarkan info ke user nilai salah6 Ketika anda selesai membuat sebuah fungsi atau program, dan sudah melakukan prinsip-prinsip defensive programming di atas, maka langkah selanjutnya adalah menguji kebenaran fungsi atau program tersebut dengan berbagai kemungkinan input. Pada umumnya, pengujian dilakukan dengan tahapan berikut:
Ada 2 pendekatan dalam melakukan testing:
Black box testingMari kita lihat contoh spesifikasi fungsi yang akan dilakukan pengetesan. x0 = 2 y0 = 4 x1 = 3 y1 = 3 # cek (x0, y0) kiri bawah, dan (x1, y1) kanan atas if x0 < x1 and y0 < y1: # panggil fungsi else: # jangan panggil fungsi, keluarkan info ke user nilai salah7 Sebelum menguji, maka kita perlu membuat test-case berdasarkan spesifikasi fungsi di atas. Beberapa panduan dalam menyusun test-cases menggunakan black-box testing adalah:
Berdasarkan panduan tersebut, maka dari spesifikasi fungsi di atas, kita dapat menemukan partisi input yang memberikan hasil berbeda, yaitu 50 dan 80. Sementara kita juga perlu mengecek nilai ekstrim, yaitu 0 dan 100, serta nilai yang tidak valid. Berikut contoh test-cases yang bisa digunakan untuk menguji fungsi try: # kode yang mungkin menimbulkan exception except: # apa yang dilakukan jika terjadi exception else: # dijalankan jika kode pada try tidak menimbulkan exception3. no case nilai return 1 perbatasan 80 “B” 2 perbatasan 80.01 “A” 3 perbatasan 50 “E” 4 perbatasan 50.01 “B” 5 ekstrim 100 “A” 6 ekstrim 0 “E” 7 invalid 100.01 Error 8 invalid -1 Error Menjalankan testingBerikut ini adalah implementasi fungsi try: # kode yang mungkin menimbulkan exception except: # apa yang dilakukan jika terjadi exception else: # dijalankan jika kode pada try tidak menimbulkan exception3 yang akan di-test. x0 = 2 y0 = 4 x1 = 3 y1 = 3 # cek (x0, y0) kiri bawah, dan (x1, y1) kanan atas if x0 < x1 and y0 < y1: # panggil fungsi else: # jangan panggil fungsi, keluarkan info ke user nilai salah8 Setelah menyusun test-case, langkah selanjutnya adalah menjalankan proses testing. Ada berbagai cara untuk melakukan ini, namun kita bisa mulai dengan yang paling sederhana, yaitu dengan print perbandingan output fungsi dengan output pada test-case seperti di bawah ini. x0 = 2 y0 = 4 x1 = 3 y1 = 3 # cek (x0, y0) kiri bawah, dan (x1, y1) kanan atas if x0 < x1 and y0 < y1: # panggil fungsi else: # jangan panggil fungsi, keluarkan info ke user nilai salah9 def luas_segiempat(x0, y0, x1, y1): """ Menghitung luas segi empat berdasarkan koordinat 2 titik: pojok kiri bawah (x0, y0), dan kanan atas (x1, y1). """ # cek (x0, y0) kiri bawah, dan (x1, y1) kanan atas if x0 < x1 and y0 < y1: deltax = x1 - x0 deltay = y1 - y0 return deltax * deltay segi4_1 = luas_segiempat(1, 1, 3, 3) segi4_2 = luas_segiempat(2, 4, 3, 3) print(segi4_1 + segi4_2)0 Ternyata dari 8 test case yang kita ajukan, ada 4 yang gagal. Coba anda temukan letak kesalahannya, dan perbaiki agar bisa lulus di semua test case tersebut. Berikut versi fungsi try: # kode yang mungkin menimbulkan exception except: # apa yang dilakukan jika terjadi exception else: # dijalankan jika kode pada try tidak menimbulkan exception3 yang sudah diperbaiki. def luas_segiempat(x0, y0, x1, y1): """ Menghitung luas segi empat berdasarkan koordinat 2 titik: pojok kiri bawah (x0, y0), dan kanan atas (x1, y1). """ # cek (x0, y0) kiri bawah, dan (x1, y1) kanan atas if x0 < x1 and y0 < y1: deltax = x1 - x0 deltay = y1 - y0 return deltax * deltay segi4_1 = luas_segiempat(1, 1, 3, 3) segi4_2 = luas_segiempat(2, 4, 3, 3) print(segi4_1 + segi4_2)1 x0 = 2 y0 = 4 x1 = 3 y1 = 3 # cek (x0, y0) kiri bawah, dan (x1, y1) kanan atas if x0 < x1 and y0 < y1: # panggil fungsi else: # jangan panggil fungsi, keluarkan info ke user nilai salah9 def luas_segiempat(x0, y0, x1, y1): """ Menghitung luas segi empat berdasarkan koordinat 2 titik: pojok kiri bawah (x0, y0), dan kanan atas (x1, y1). """ # cek (x0, y0) kiri bawah, dan (x1, y1) kanan atas if x0 < x1 and y0 < y1: deltax = x1 - x0 deltay = y1 - y0 return deltax * deltay segi4_1 = luas_segiempat(1, 1, 3, 3) segi4_2 = luas_segiempat(2, 4, 3, 3) print(segi4_1 + segi4_2)3 Cara lainnya kita bisa menggunakan assertion dan fungsi, serta membuat file khusus yang berisi semua testing. Misalnya kita membuat file baru bernama my_test.py yang isinya adalah sebagai berikut: def luas_segiempat(x0, y0, x1, y1): """ Menghitung luas segi empat berdasarkan koordinat 2 titik: pojok kiri bawah (x0, y0), dan kanan atas (x1, y1). """ # cek (x0, y0) kiri bawah, dan (x1, y1) kanan atas if x0 < x1 and y0 < y1: deltax = x1 - x0 deltay = y1 - y0 return deltax * deltay segi4_1 = luas_segiempat(1, 1, 3, 3) segi4_2 = luas_segiempat(2, 4, 3, 3) print(segi4_1 + segi4_2)4 def luas_segiempat(x0, y0, x1, y1): """ Menghitung luas segi empat berdasarkan koordinat 2 titik: pojok kiri bawah (x0, y0), dan kanan atas (x1, y1). """ # cek (x0, y0) kiri bawah, dan (x1, y1) kanan atas if x0 < x1 and y0 < y1: deltax = x1 - x0 deltay = y1 - y0 return deltax * deltay segi4_1 = luas_segiempat(1, 1, 3, 3) segi4_2 = luas_segiempat(2, 4, 3, 3) print(segi4_1 + segi4_2)5 Glass box testingPembuatan test-case pada glass box testing dilakukan berdasarkan kode program. Tujuannya adalah memastikan bahwa setiap jalur yang ada pada kode pernah dieksekusi minimal satu kali. Beberapa panduan antara lain:
x0 = 2 y0 = 4 x1 = 3 y1 = 3 # cek (x0, y0) kiri bawah, dan (x1, y1) kanan atas if x0 < x1 and y0 < y1: # panggil fungsi else: # jangan panggil fungsi, keluarkan info ke user nilai salah8 Berdasarkan fungsi konversi_nilai asli di atas, maka beberapa test-case yang bisa dibuat adalah: no case nilai return 1 if nilai >= 80 85 “A” 2 elif nilai >= 50 60 “B” 3 else 30 “E” Kita sudah melihat bahwa, jika test-case tersebut diberikan pada fungsi try: # kode yang mungkin menimbulkan exception except: # apa yang dilakukan jika terjadi exception else: # dijalankan jika kode pada try tidak menimbulkan exception3 yang masih salah di atas, maka akan terlihat semua baik-baik saja, tanpa terlihat adanya bug. Hal ini dikarenakan kita tidak memasukkan nilai-nilai perbatasan pada test-case seperti yang dilakukan pada Black box testing. Ini adalah kelemahan pada glass box testing, yaitu meskipun semua kemungkinan jalur eksekusi sudah tercover, kita masih mungkin melewatkan beberapa bug. Di sisi lain, dengan Black box testing saja terkadang kita kesulitan untuk membuat test-case yang meng-cover semua kemungkinan jalur eksekusi, terutama untuk program yang komplek yang melibatkan looping dan kondisional. Untuk itu, sebaiknya dalam membuat test-case, kedua cara tersebut dipertimbangkan. Testing vs Debugging Testing dan debugging sama-sama terkait dengan usaha agar kode kita tidak memiliki bug, namun keduanya adalah proses yang berbeda. Berikut perbedaannya:
Cara-cara dalam melakukan debugging:
Debugging dengan PrintPertama-tama, mari kita lihat contoh program di bawah ini. Fungsi try: # kode yang mungkin menimbulkan exception except: # apa yang dilakukan jika terjadi exception else: # dijalankan jika kode pada try tidak menimbulkan exception7 manerima sebuah input non-negatif integer try: # kode yang mungkin menimbulkan exception except: # apa yang dilakukan jika terjadi exception else: # dijalankan jika kode pada try tidak menimbulkan exception8, lalu akan mengembalikan dua buah nilai, yaitu jumlah bilangan ganjil yang terdapat pada deret 1 sampai n, dan jumlah bilangan genapnya. def luas_segiempat(x0, y0, x1, y1): """ Menghitung luas segi empat berdasarkan koordinat 2 titik: pojok kiri bawah (x0, y0), dan kanan atas (x1, y1). """ # cek (x0, y0) kiri bawah, dan (x1, y1) kanan atas if x0 < x1 and y0 < y1: deltax = x1 - x0 deltay = y1 - y0 return deltax * deltay segi4_1 = luas_segiempat(1, 1, 3, 3) segi4_2 = luas_segiempat(2, 4, 3, 3) print(segi4_1 + segi4_2)7 Pertama-tama, mari kita buat beberapa test-case untuk menguji fungsi tersebut. no case n return 1 perbatasan 0 (0, 0) 2 perbatasan 1 (1, 0) 3 perbatasan 2 (1, 2) 4 random 5 (9, 6) 5 random 6 (9, 12) def luas_segiempat(x0, y0, x1, y1): """ Menghitung luas segi empat berdasarkan koordinat 2 titik: pojok kiri bawah (x0, y0), dan kanan atas (x1, y1). """ # cek (x0, y0) kiri bawah, dan (x1, y1) kanan atas if x0 < x1 and y0 < y1: deltax = x1 - x0 deltay = y1 - y0 return deltax * deltay segi4_1 = luas_segiempat(1, 1, 3, 3) segi4_2 = luas_segiempat(2, 4, 3, 3) print(segi4_1 + segi4_2)8 def luas_segiempat(x0, y0, x1, y1): """ Menghitung luas segi empat berdasarkan koordinat 2 titik: pojok kiri bawah (x0, y0), dan kanan atas (x1, y1). """ # cek (x0, y0) kiri bawah, dan (x1, y1) kanan atas if x0 < x1 and y0 < y1: deltax = x1 - x0 deltay = y1 - y0 return deltax * deltay segi4_1 = luas_segiempat(1, 1, 3, 3) segi4_2 = luas_segiempat(2, 4, 3, 3) print(segi4_1 + segi4_2)9 Terlihat bahwa masih terdapat bug pada fungsi tersebut sehingga dari 5 test-case hanya 1 yang benar. Mari kita coba debug menggunakan fungsi try: # kode yang mungkin menimbulkan exception except: # apa yang dilakukan jika terjadi exception else: # dijalankan jika kode pada try tidak menimbulkan exception9. Pertama-tama, mari kita lihat output fungsi terhadap salah satu test-case, misalnya x0 = 2 y0 = 4 x1 = 3 y1 = 3 # cek (x0, y0) kiri bawah, dan (x1, y1) kanan atas if x0 < x1 and y0 < y1: # panggil fungsi else: # jangan panggil fungsi, keluarkan info ke user nilai salah00. --------------------------------------------------------------------------- TypeError Traceback (most recent call last) in () 11 segi4_1 = luas_segiempat(1, 1, 3, 3) 12 segi4_2 = luas_segiempat(2, 4, 3, 3) ---> 13 print(segi4_1 + segi4_2) TypeError: unsupported operand type(s) for +: 'int' and 'NoneType'0 Saat x0 = 2 y0 = 4 x1 = 3 y1 = 3 # cek (x0, y0) kiri bawah, dan (x1, y1) kanan atas if x0 < x1 and y0 < y1: # panggil fungsi else: # jangan panggil fungsi, keluarkan info ke user nilai salah00 output fungsi adalah x0 = 2 y0 = 4 x1 = 3 y1 = 3 # cek (x0, y0) kiri bawah, dan (x1, y1) kanan atas if x0 < x1 and y0 < y1: # panggil fungsi else: # jangan panggil fungsi, keluarkan info ke user nilai salah02, padahal seharusnya x0 = 2 y0 = 4 x1 = 3 y1 = 3 # cek (x0, y0) kiri bawah, dan (x1, y1) kanan atas if x0 < x1 and y0 < y1: # panggil fungsi else: # jangan panggil fungsi, keluarkan info ke user nilai salah03. Maka terdapat bug pada penjumlahan bilangan ganjil. Mari kita inspeksi menggunakan try: # kode yang mungkin menimbulkan exception except: # apa yang dilakukan jika terjadi exception else: # dijalankan jika kode pada try tidak menimbulkan exception9. Kita bisa tambahkan beberapa statement try: # kode yang mungkin menimbulkan exception except: # apa yang dilakukan jika terjadi exception else: # dijalankan jika kode pada try tidak menimbulkan exception9 untuk mengoutputkan nilai variable yang mungkin ada kaitannya dengan kesalahan. Dalam hal ini, kesalahan jelas terjadi pada variable x0 = 2 y0 = 4 x1 = 3 y1 = 3 # cek (x0, y0) kiri bawah, dan (x1, y1) kanan atas if x0 < x1 and y0 < y1: # panggil fungsi else: # jangan panggil fungsi, keluarkan info ke user nilai salah06 yang menyimpan jumlah ganjil. Agar lebih detil melihat waktu eksekusi x0 = 2 y0 = 4 x1 = 3 y1 = 3 # cek (x0, y0) kiri bawah, dan (x1, y1) kanan atas if x0 < x1 and y0 < y1: # panggil fungsi else: # jangan panggil fungsi, keluarkan info ke user nilai salah06, maka kita tambahkan statement try: # kode yang mungkin menimbulkan exception except: # apa yang dilakukan jika terjadi exception else: # dijalankan jika kode pada try tidak menimbulkan exception9 setelah perubahan pada x0 = 2 y0 = 4 x1 = 3 y1 = 3 # cek (x0, y0) kiri bawah, dan (x1, y1) kanan atas if x0 < x1 and y0 < y1: # panggil fungsi else: # jangan panggil fungsi, keluarkan info ke user nilai salah06. Selain itu kita juga perlu curigai jumlah perulangan, apakah sudah sesuai atau tidak, sehingga variable x0 = 2 y0 = 4 x1 = 3 y1 = 3 # cek (x0, y0) kiri bawah, dan (x1, y1) kanan atas if x0 < x1 and y0 < y1: # panggil fungsi else: # jangan panggil fungsi, keluarkan info ke user nilai salah10 juga perlu dioutputkan. Hasilnya adalah seperti berikut ini: --------------------------------------------------------------------------- TypeError Traceback (most recent call last) in () 11 segi4_1 = luas_segiempat(1, 1, 3, 3) 12 segi4_2 = luas_segiempat(2, 4, 3, 3) ---> 13 print(segi4_1 + segi4_2) TypeError: unsupported operand type(s) for +: 'int' and 'NoneType'1 --------------------------------------------------------------------------- TypeError Traceback (most recent call last) in () 11 segi4_1 = luas_segiempat(1, 1, 3, 3) 12 segi4_2 = luas_segiempat(2, 4, 3, 3) ---> 13 print(segi4_1 + segi4_2) TypeError: unsupported operand type(s) for +: 'int' and 'NoneType'0 --------------------------------------------------------------------------- TypeError Traceback (most recent call last) in () 11 segi4_1 = luas_segiempat(1, 1, 3, 3) 12 segi4_2 = luas_segiempat(2, 4, 3, 3) ---> 13 print(segi4_1 + segi4_2) TypeError: unsupported operand type(s) for +: 'int' and 'NoneType'3 Dari output di atas, kita bisa melihat beberapa kesalahan.
Berikut adalah fungsi yang telah diperbaiki: --------------------------------------------------------------------------- TypeError Traceback (most recent call last) in () 11 segi4_1 = luas_segiempat(1, 1, 3, 3) 12 segi4_2 = luas_segiempat(2, 4, 3, 3) ---> 13 print(segi4_1 + segi4_2) TypeError: unsupported operand type(s) for +: 'int' and 'NoneType'4 Mari kita lakukan testing kembali. --------------------------------------------------------------------------- TypeError Traceback (most recent call last) in () 11 segi4_1 = luas_segiempat(1, 1, 3, 3) 12 segi4_2 = luas_segiempat(2, 4, 3, 3) ---> 13 print(segi4_1 + segi4_2) TypeError: unsupported operand type(s) for +: 'int' and 'NoneType'5 Terkadang error terjadi karena hal yang sepele, misalnya karena typo. Namun jika kita tidak menggunakan cara yang tepat dalam mendebug, misalnya hanya dengan membaca kembali kode, mungkin kita akan kesulitan menemukan kesalahannya. Debugger pada IDLEFitur standard sebuah debugger:
Mengaktifkan Debugger
Menu Debug Control IDLE
Menjalankan Debug Program
Terlihat bahwa ada yang aneh saat program eksekusi baris x0 = 2 y0 = 4 x1 = 3 y1 = 3 # cek (x0, y0) kiri bawah, dan (x1, y1) kanan atas if x0 < x1 and y0 < y1: # panggil fungsi else: # jangan panggil fungsi, keluarkan info ke user nilai salah24, yaitu muncul variable tambahan yaitu x0 = 2 y0 = 4 x1 = 3 y1 = 3 # cek (x0, y0) kiri bawah, dan (x1, y1) kanan atas if x0 < x1 and y0 < y1: # panggil fungsi else: # jangan panggil fungsi, keluarkan info ke user nilai salah16. Sehingga hal ini bisa menyadarkan kita bahwa kita menggunakan nama variable yang salah. Jika diteruskan sampai akhir, akan terlihat juga bahwa nilai x0 = 2 y0 = 4 x1 = 3 y1 = 3 # cek (x0, y0) kiri bawah, dan (x1, y1) kanan atas if x0 < x1 and y0 < y1: # panggil fungsi else: # jangan panggil fungsi, keluarkan info ke user nilai salah10 terakhir adalah 4. Apa penyebab terjadinya suatu pengecualian exceptions di suatu program?Exception dipicu oleh runtime error, yaitu error atau kesalahan yang terjadi saat program dieksekusi oleh interpreter.
Di dalam statement try apa arti dari except?except untuk menangani error yang mungkin kita sendiri tidak mengetahuinya. Biasanya try.. except ini digunakan untuk menangani error saat penggunaan IO, operasi database, atau pengaksesan indeks suatu list atau dictionary, dan berbagai kasus lainnya.
Apa itu Exception pada python?Exception adalah objek Python yang mewakili kesalahan.
|