Saya memiliki modul Python yang menggunakan perpustakaan argparse. Bagaimana cara menulis tes untuk bagian basis kode itu?
python
unit-testing
argparse
pydanny
sumber
sumber
foo()
disebut". Mengejeksys.argv
adalah jawabannya jika itu masalahnya. Lihatlah paket Python cli-test-helpers . Lihat juga stackoverflow.com/a/58594599/202834Jawaban:
Anda harus memperbaiki kode Anda dan memindahkan parsing ke fungsi:
Maka dalam
main
fungsi Anda, Anda harus menyebutnya dengan:(di mana elemen pertama
sys.argv
yang mewakili nama skrip dihapus untuk tidak mengirimkannya sebagai saklar tambahan selama operasi CLI.)Dalam pengujian Anda, Anda kemudian dapat memanggil fungsi parser dengan daftar argumen apa pun yang ingin Anda uji dengan:
Dengan cara ini Anda tidak perlu menjalankan kode aplikasi Anda hanya untuk menguji parser.
Jika Anda perlu mengubah dan / atau menambahkan opsi ke parser Anda nanti di aplikasi Anda, kemudian buat metode pabrik:
Anda kemudian dapat memanipulasi jika Anda mau, dan tes bisa terlihat seperti:
sumber
2
...argparse
tidak terlalu ramah uji karena langsung mencetak kesys.stderr
..."Bagian argparse" agak kabur sehingga jawaban ini berfokus pada satu bagian:
parse_args
metode. Ini adalah metode yang berinteraksi dengan baris perintah Anda dan mendapatkan semua nilai yang diteruskan. Pada dasarnya, Anda bisa mengejek apa yangparse_args
kembali sehingga tidak perlu benar-benar mendapatkan nilai dari baris perintah. Themock
paket dapat diinstal melalui pip untuk python versi 2,6-3,2. Ini bagian dari perpustakaan standarunittest.mock
sejak versi 3.3 dan seterusnya.Anda harus memasukkan semua argumen metode perintah Anda
Namespace
bahkan jika itu tidak lulus. Beri mereka nilai argsNone
. (lihat dokumen ) Gaya ini berguna untuk melakukan pengujian dengan cepat untuk kasus-kasus di mana nilai yang berbeda dilewatkan untuk setiap argumen metode. Jika Anda memilih untuk mengejekNamespace
diri sendiri untuk ketidakpercayaan argparse total dalam tes Anda, pastikan itu berperilaku serupa denganNamespace
kelas yang sebenarnya .Di bawah ini adalah contoh menggunakan potongan pertama dari perpustakaan argparse.
sumber
argparse
danNamespace
kelasnya. Anda harus mengejekNamespace
.from unittest import mock
sekarang merupakan metode impor yang benar - setidaknya untuk python3Namespace
kelas di sini adalah persis apa yang saya cari. Meskipun pengujian masih mengandalkanargparse
, itu tidak bergantung pada implementasi tertentuargparse
oleh kode yang diuji, yang penting untuk pengujian unit saya. Selain itu, mudah digunakanpytest
'sparametrize()
metode untuk cepat menguji berbagai kombinasi argumen dengan pura-pura templated yang mencakupreturn_value=argparse.Namespace(accumulate=accumulate, integers=integers)
.Jadikan
main()
fungsi Andaargv
sebagai argumen alih-alih membiarkannya membacasys.argv
seperti apa adanya secara default :Maka Anda dapat menguji secara normal.
sumber
sys.argv.append()
lalu panggilparse()
, periksa hasilnya dan ulangi.if __name__ == "__main__":
panggilan parse dan dump / evaluasi hasilnya kemudian uji ini dari file batch / bash.sumber
Saya tidak ingin memodifikasi skrip penayangan asli sehingga saya hanya mengejek
sys.argv
bagian dalam argparse.Ini rusak jika implementasi argparse berubah tetapi cukup untuk skrip pengujian cepat. Sensibilitas jauh lebih penting daripada spesifisitas dalam skrip tes.
sumber
Cara sederhana untuk menguji parser adalah:
Cara lain adalah memodifikasi
sys.argv
, dan meneleponargs = parser.parse_args()
Ada banyak contoh pengujian
argparse
dilib/test/test_argparse.py
sumber
parse_args
melemparSystemExit
dan mencetak ke stderr, Anda dapat menangkap keduanya:Anda memeriksa stderr (menggunakan
err.seek(0); err.read()
tetapi secara umum granularity tidak diperlukan.Sekarang Anda dapat menggunakan
assertTrue
atau pengujian apa pun yang Anda suka:Sebagai alternatif, Anda mungkin ingin menangkap dan memikirkan kembali kesalahan yang berbeda (bukan
SystemExit
):sumber
Saat meneruskan hasil dari
argparse.ArgumentParser.parse_args
ke suatu fungsi, saya terkadang menggunakan anamedtuple
untuk mengejek argumen untuk pengujian.sumber
Untuk menguji CLI (antarmuka baris perintah), dan bukan output perintah, saya melakukan sesuatu seperti ini
sumber