Konteks:
Saat ini saya sedang mengerjakan proyek kecil dengan Python. Saya biasanya menyusun kelas saya dengan beberapa metode publik yang didokumentasikan tetapi terutama berkaitan dengan konsep tingkat tinggi (apa yang harus diketahui dan digunakan oleh pengguna kelas), dan banyak metode tersembunyi (dimulai dengan garis bawah) yang bertanggung jawab atas pemrosesan tingkat kompleks atau rendah.
Saya tahu bahwa tes sangat penting untuk memberikan kepercayaan pada kode dan untuk memastikan bahwa modifikasi selanjutnya tidak merusak perilaku sebelumnya.
Masalah:
Untuk membangun metode publik tingkat tinggi di atas dasar tepercaya, saya biasanya menguji metode pribadi. Saya merasa lebih mudah untuk menemukan apakah modifikasi kode telah memperkenalkan regresi dan di mana. Ini berarti bahwa tes internal tersebut dapat melanggar revisi kecil dan perlu diperbaiki / diganti
Tetapi saya juga tahu bahwa pengujian unit metode pribadi setidaknya merupakan konsep yang disengketakan atau lebih sering dianggap sebagai praktik yang buruk. Alasannya adalah: hanya perilaku publik yang harus diuji ( ref. )
Pertanyaan:
Saya peduli mengikuti praktik terbaik dan ingin memahami:
- mengapa menggunakan tes unit pada metode pribadi / tersembunyi buruk (apa risikonya)?
- apa praktik terbaik ketika metode publik dapat menggunakan pemrosesan tingkat rendah dan / atau kompleks?
Presisi:
- ini bukan pertanyaan bagaimana . Python tidak memiliki konsep privasi dan metode tersembunyi yang tidak didaftar tetapi dapat digunakan saat Anda mengetahui namanya
- Saya tidak pernah diajari aturan dan pola pemrograman: kelas terakhir saya berasal dari tahun 80-an ... Saya terutama belajar bahasa melalui percobaan dan kegagalan dan referensi di Internet (Stack Exchange menjadi favorit saya selama bertahun-tahun)
sumber
Jawaban:
Beberapa alasan:
Biasanya ketika Anda tergoda untuk menguji metode pribadi kelas, itu bau desain (kelas gunung es, komponen publik tidak cukup dapat digunakan kembali, dll). Hampir selalu ada masalah "lebih besar" yang sedang dimainkan.
Anda dapat mengujinya melalui antarmuka publik (yang merupakan cara Anda ingin mengujinya, karena itulah cara klien akan memanggil / menggunakannya). Anda bisa mendapatkan rasa aman yang salah dengan melihat lampu hijau pada semua tes yang lulus untuk metode pribadi Anda. Jauh lebih baik / aman untuk menguji kasus tepi pada fungsi pribadi Anda melalui antarmuka publik Anda.
Anda berisiko mengalami duplikasi tes berat (tes yang terlihat / terasa sangat mirip) dengan menguji metode pribadi. Ini memiliki konsekuensi besar ketika persyaratan berubah, karena lebih banyak tes dari yang diperlukan akan rusak. Itu juga dapat menempatkan Anda pada posisi di mana sulit untuk refactor karena test suite Anda ... yang merupakan ironi utama, karena test suite ada untuk membantu Anda mendesain ulang dan refactor dengan aman!
Kiat jika Anda masih tergoda untuk menguji bagian-bagian pribadi (jangan gunakan jika itu mengganggu Anda, dan YMMV, tetapi itu telah bekerja dengan baik untuk saya di masa lalu): Kadang-kadang menulis unit test untuk fungsi pribadi hanya untuk memastikan mereka bekerja persis bagaimana menurut Anda mereka bisa berharga (terutama jika Anda baru mengenal suatu bahasa). Namun, setelah Anda yakin mereka bekerja, hapus tes, dan selalu pastikan bahwa tes yang menghadap publik solid dan akan menangkap jika seseorang membuat perubahan yang mengerikan untuk fungsi pribadi tersebut.
Kapan menguji metode pribadi: Karena jawaban ini sudah (agak) populer, saya merasa berkewajiban untuk menyebutkan bahwa "praktik terbaik" selalu hanya itu: "praktik terbaik". Itu tidak berarti Anda harus melakukannya secara dogmatis atau buta. Jika Anda pikir Anda harus menguji metode pribadi Anda dan memiliki alasan yang sah (seperti Anda sedang menulis tes karakterisasi untuk aplikasi warisan), maka uji metode pribadi Anda . Keadaan khusus selalu mengalahkan aturan umum atau praktik terbaik. Sadarilah beberapa hal yang bisa salah (lihat di atas).
Saya punya jawaban yang membahas hal ini secara rinci pada SO yang tidak akan saya ulangi di sini: /programming/105007/should-i-test-private-methods-or-only-public-ones/ 47401015 # 47401015
sumber
bin_search(arr, item)
(publik) danbin_search(arr, item, low, hi)
(pribadi, ada banyak cara untuk melakukan pencarian bin), maka yang perlu Anda uji adalah yang menghadap publik (bin_search(arr, item)
)Mengingat bahwa salah satu tujuan utama pengujian unit adalah Anda dapat memperbaiki internal program Anda dan kemudian dapat memverifikasi bahwa Anda belum merusak fungsinya, itu kontraproduktif jika pengujian unit Anda beroperasi pada tingkat granularitas yang sangat halus sehingga setiap perubahan pada kode program mengharuskan Anda menulis ulang tes Anda.
sumber
Tes unit menulis untuk metode pribadi mengikat tes unit Anda dengan detail implementasi.
Tes unit harus menguji perilaku kelas di permukaan luar kelas (itu API publik). Tes unit seharusnya tidak perlu tahu apa-apa tentang jeroan kelas. Tes unit tulisan terhadap detail implementasi kelas mengikat tangan Anda ketika tiba saatnya untuk melakukan refactor. Refactoring hampir pasti akan memecahkan tes-tes itu, karena mereka bukan bagian dari API stabil Anda.
Yang mengatakan, mengapa mungkin Anda ingin menulis unit test untuk metode pribadi Anda?
Ada ketegangan alami antara tes unit dan pengembangan bertahap. Pengembang perangkat lunak yang menggunakan REPL (read-eval-print loop) dapat membuktikan seberapa produktifnya dengan cepat menulis dan menguji sedikit fungsionalitas saat Anda "menumbuhkan" kelas atau fungsi. Satu-satunya cara yang baik untuk melakukan itu di lingkungan yang didorong unit test adalah menulis unit test untuk metode pribadi, tetapi ada banyak gesekan dalam melakukan itu. Tes unit membutuhkan waktu untuk menulis, Anda memerlukan metode yang sebenarnya untuk diuji, dan kerangka kerja pengujian Anda perlu mendukung kemampuan untuk menjaga agar metode ini tetap pribadi sehingga tidak mencemari API eksternal Anda.
Beberapa ekosistem seperti C # dan .NET memiliki cara untuk membuat lingkungan seperti REPL (alat seperti Linqpad melakukan ini), tetapi utilitas mereka terbatas karena Anda tidak memiliki akses ke proyek Anda. Jendela langsung di Visual Studio tidak nyaman; masih tidak memiliki Intellisense penuh, Anda harus menggunakan nama yang sepenuhnya memenuhi syarat di dalamnya, dan memicu pembangunan setiap kali Anda menggunakannya.
sumber
Dari pengalaman saya, saya telah menemukan bahwa unit menguji kelas internal, metode biasanya berarti bahwa saya harus mengambil fungsi yang diuji, keluar kelas. Untuk membuat level abstraksi lain.
Ini mengarah pada kepatuhan yang lebih baik terhadap Prinsip Tanggung Jawab Tunggal.
sumber
Saya pikir ini adalah pertanyaan yang bagus karena memaparkan masalah umum dalam menguji cakupan. Tetapi jawaban yang baik harus memberi tahu Anda bahwa pertanyaannya tidak tepat karena, secara teori, Anda seharusnya tidak dapat menguji metode pribadi . Itu sebabnya mereka pribadi .
Mungkin pertanyaan yang lebih baik adalah "Apa yang harus saya lakukan ketika saya ingin menguji metode pribadi?" , dan jawabannya agak jelas: Anda harus mengeksposnya dengan cara yang memungkinkan pengujian. Sekarang, ini tidak selalu berarti bahwa Anda hanya perlu membuat metode publik dan hanya itu. Kemungkinan besar Anda ingin melakukan abstraksi yang lebih tinggi; pindah ke pustaka atau API yang berbeda sehingga Anda dapat melakukan tes di pustaka itu, tanpa memaparkan fungsi itu di API utama Anda.
Ingatlah bahwa ada alasan mengapa metode Anda memiliki tingkat aksesibilitas yang berbeda, dan Anda harus selalu memikirkan bagaimana kelas Anda akan digunakan pada akhirnya.
sumber