Klara adalah alat analisis statis untuk menghasilkan uji kasus, berdasarkan solver SMT (Z3), dengan sistem inferensi tingkat AST yang kuat. Klara akan mengambil file python sebagai input dan menghasilkan file uji yang sesuai dalam format pytest, yang berupaya mencakup semua nilai pengembalian. Misalnya, fungsi berikut di file test.py
def triangle ( x : int , y : int , z : int ) -> str :
if x == y == z :
return "Equilateral triangle"
elif x == y or y == z or x == z :
return "Isosceles triangle"
else :
return "Scalene triangle"akan menghasilkan
import test
def test_triangle_0 ():
assert test . triangle ( 0 , 0 , 0 ) == 'Equilateral triangle'
assert test . triangle ( 0 , 0 , 1 ) == 'Isosceles triangle'
assert test . triangle ( 2 , 0 , 1 ) == 'Scalene triangle'Lihat dokumentasi Klara di https://klara-py.readthedocs.io
Catatan : Klara masih dalam tahap eksperimental awal, fitur yang hilang yang menonjol adalah Loop, pemahaman, impor modul, pengecualian dan banyak lagi. Lihat batasan untuk daftar lengkap. Mungkin tidak akan berjalan pada proyek dunia nyata, jadi yang terbaik adalah memilih beberapa fungsi menarik untuk menghasilkan test case yang sesuai.
Klara dapat diinstal melalui alat pip dengan menggunakan:
pip install klara
Kami dapat memohon klara pada file sumber Python apa pun, dan itu akan menghasilkan file uji Pytest yang sesuai.
$ cat source.py
def foo(x: int, y: int, z: str):
if x + y > 2:
return x + y + 12
elif x < y:
return x + y
elif (z + " me " ) == " some " :
return z + " thing "
else:
return x - y
$ klara source.py
$ cat test_source.py
import contract_test
def test_foo_0 ():
assert contract_test.foo(0, 3, '' ) == 15
assert contract_test.foo(0, 1, '' ) == 1
assert contract_test.foo(0, 0, ' so ' ) == ' sothing '
assert contract_test.foo(0, 0, '' ) == 0Konsultasikan dengan manual Mulai Cepat untuk lebih banyak contoh dan bimbingan. Untuk menggunakannya sebagai pustaka analisis statis, buka inferensi.
Klara bekerja pada level AST dan tidak menjalankan kode pengguna dengan cara apa pun, yang merupakan perbedaan yang sangat penting dibandingkan dengan alat serupa seperti Crosshair dan Pynguin yang memanfaatkan eksekusi simbolik konsolik yang membutuhkan eksekusi kode pengguna yang mungkin menyebabkan efek samping yang tidak diinginkan. Klara bekerja pada level AST, kombinasikan dengan analisis aliran data yang menggunakan grafik aliran kontrol (CFG), penugasan tunggal statis (SSA), rantai penggunaan-def, dll ... untuk membangun sistem inferensi python yang kuat yang memanfaatkan Z3-Solver untuk pemecahan kendala dan pemeriksaan kelayakan jalur. Karena itu, Klara dapat beroperasi pada kode sumber Python2/3 dengan bantuan typed_ast. Untuk menentukan kode sumber ada dalam argumen Python 2, lulus dalam -py 2 . Ini Python 3 secara default.
Klara juga dapat digunakan sebagai alat analisis statis, memungkinkan pengguna untuk mendefinisikan aturan khusus untuk mengidentifikasi bug pemrograman, kesalahan atau penegakan standar pengkodean. Dengan dukungan SMT Solver, analisis akan lebih akurat dan sangat mengurangi kasus positif palsu. Misalnya
import klara
tree = klara . parse ( """
def foo(v1: int):
if v1 > 4:
if v1 < 3:
z = 1
else:
z = 2
else:
z = 3
s = z
""" )
with klara . MANAGER . initialize_z3_var_from_func ( tree . body [ 0 ]):
print ( list ( tree . body [ 0 ]. body [ - 1 ]. value . infer ()))Akan mencetak:
[2, 3]
Karena z = 1 tidak dimungkinkan karena v1 > 4 dan v1 < 3 tidak memuaskan
Arsitektur dan API sistem inferensi sebagian besar terinspirasi oleh Astroid, perpustakaan inferensi statis yang digunakan oleh Pylint.
Klara menggunakan sistem inferensi untuk menghasilkan case uji, dengan kata lain, ini menghasilkan test case untuk semua nilai pengembalian yang mungkin dari fungsi , alih -alih menghasilkan test case untuk semua jalur kontrol fungsi.
Untuk mengilustrasikan poinnya, pertimbangkan fungsi di bawah ini, dengan divide by zero kerentanan di baris 3
def foo ( v1 : int , v2 : float ):
if v1 > 10000 :
s = v1 / 0 # unused statement
if v1 > v2 :
s = v1
else :
s = v2
return sKlara akan menghasilkan input uji di bawah ini
import contract_test
def test_foo_0 ():
assert contract_test . foo ( 0 , - 1.0 ) == 0
assert contract_test . foo ( 0 , 0.0 ) == 0.0 Itu tidak menghasilkan input v1 > 10000 , sehingga test case tidak akan dapat mengetahui pengecualian. Ini karena s pada jalur 3 tidak digunakan dalam nilai pengembalian.
Jika kami memodifikasi pernyataan IF kedua untuk elif , yang kami akan dapat mengembalikan [s] {. Judul-ref} di baris 3, Klara akan menghasilkan input uji yang mencakup case v1 > 10000 .
Ini adalah perbedaan penting dengan pembuatan kasus uji otomatis lainnya yang tersedia sekarang, karena dengan hanya menghasilkan test case untuk nilai pengembalian, kita dapat menghasilkan case uji minimal, dan lebih mudah untuk menyesuaikan bagaimana Klara menutupi fungsi.
Misalnya, katakanlah kami sedang menyusun sistem yang kompleks
def main ( number : int , cm : int , dc : int , wn : int ):
mc = 0
if wn > 2 :
if number > 2 and number > 2 or number > 2 :
if number > 0 :
if wn > 2 or wn > 2 :
mc = 2
else :
mc = 5
else :
mc = 100
else :
mc = 1
nnn = number * cm
if cm <= 4 :
num_incr = 4
else :
num_incr = cm
n_num_incr = nnn / num_incr
nnn_left = dc * num_incr * ( n_num_incr / 2 + n_num_incr % 2 )
nnn_right = nnn - nnn_left
is_flag = nnn_right
if is_flag :
cell = Component ( nnn_right , options = [ mc ])
else :
cell = Component ( nnn_right )
return cellTidak segera jelas bagi kami berapa banyak nilai pengembalian yang mungkin ada. Tapi kami dapat menggunakan KLARA untuk menghasilkan input secara instan, di bawah ini adalah tes yang dihasilkan
import contract_test
def test_main_0 ():
assert contract_test . main ( 2 , 4 , 1 , 3 ) is not None
assert contract_test . main ( 2 , 4 , - 1 , 6 ) is not None
assert contract_test . main ( 2 , 4 , 1 , 4 ) is not None
assert contract_test . main ( - 2 , 4 , 3 , 4 ) is not None
assert contract_test . main ( - 1 , - 1 , - 1 , 2 ) is not None
assert contract_test . main ( 0 , 0 , 0 , 3 ) is not None
assert contract_test . main ( 0 , 0 , 0 , 6 ) is not None
assert contract_test . main ( 0 , 0 , 0 , 4 ) is not None
assert contract_test . main ( - 2 , 0 , 0 , 4 ) is not None
assert contract_test . main ( 0 , 0 , 0 , 0 ) is not None Di atas menghasilkan 10 hasil total, yang merupakan produk dari nnn_right yang memiliki 2 kemungkinan dan mc yang memiliki 5 kemungkinan.
Misalkan 10 tes input terlalu banyak, dan kami telah menentukan bahwa argumen options untuk Component berlebihan untuk diuji, kami dapat menggunakan plugin khusus Klara untuk secara selektif menentukan bagian mana yang harus diabaikan dalam pembuatan tes. Pergi untuk menyesuaikan strategi cakupan untuk informasi lebih lanjut.
Setelah kami mengatur plugin, Klara akan menghasilkan tes berikut
import contract_test
def test_main_0 ():
assert contract_test . main ( 1 , 3 , 0 , 0 ) is not None
assert contract_test . main ( 0 , 0 , 0 , 0 ) is not None Yang hanya 2 kombinasi nnn_right
Karena Klara tidak dapat secara dinamis menjalankan kode, itu akan memberikan ekstensi untuk menentukan cara menyimpulkan simpul AST spesifik atau tipe yang ditentukan pengguna untuk membuat Klara 'lebih pintar'. Ini dijelaskan dalam memperluas, memperluas jenis pengguna dan menyesuaikan strategi cakupan.
Kami menggunakan puisi untuk mengelola dependensi. Setelah puisi diinstal, jalankan:
$ poetry shell
$ poetry install
Untuk menjalankan test case, lakukan:
$ poetry run pytest test
Proyek ini dilisensikan berdasarkan ketentuan Lisensi Publik Umum GNU yang lebih rendah.