Saya telah membaca dokumen phpunit dan menemukan kutipan berikut:
Anda selalu dapat menulis lebih banyak tes. Namun, Anda akan segera menemukan bahwa hanya sebagian kecil dari tes yang dapat Anda bayangkan yang benar-benar bermanfaat. Yang Anda inginkan adalah menulis tes yang gagal walaupun Anda pikir itu harus berhasil, atau tes yang berhasil meskipun Anda pikir itu harus gagal. Cara lain untuk memikirkannya adalah dari segi biaya / manfaat. Anda ingin menulis tes yang akan membayar Anda kembali dengan informasi. --Erich Gamma
Itu membuat saya bertanya-tanya. Bagaimana Anda menentukan apa yang membuat tes unit lebih bermanfaat daripada yang lain, selain dari apa yang dinyatakan dalam kutipan tentang biaya / manfaat. Bagaimana cara Anda memutuskan bagian kode mana yang Anda buat untuk pengujian unit? Saya meminta itu karena salah satu dari kutipan itu juga mengatakan:
Jadi jika ini bukan tentang pengujian, tentang apa? Ini tentang mencari tahu apa yang Anda coba lakukan sebelum Anda lari setengah matang untuk mencoba melakukannya. Anda menulis spesifikasi yang memakukan aspek kecil perilaku dalam bentuk yang ringkas, tidak ambigu, dan dapat dieksekusi. Sesederhana itu. Apakah itu berarti Anda menulis tes? Tidak. Itu berarti Anda menulis spesifikasi tentang apa yang harus dilakukan kode Anda. Itu berarti Anda menentukan perilaku kode Anda sebelumnya. Tapi tidak jauh sebelumnya. Sebenarnya, tepat sebelum Anda menulis kode adalah yang terbaik karena pada saat itulah Anda memiliki sebanyak mungkin informasi yang Anda miliki hingga saat itu. Seperti TDD yang dilakukan dengan baik, Anda bekerja dengan sedikit tambahan ... menentukan satu aspek kecil perilaku sekaligus, kemudian menerapkannya. Ketika Anda menyadari bahwa ini semua tentang menentukan perilaku dan bukan menulis tes, sudut pandang Anda bergeser. Tiba-tiba ide memiliki kelas Uji untuk masing-masing kelas produksi Anda sangat terbatas. Dan pemikiran menguji setiap metode Anda dengan metode pengujian sendiri (dalam hubungan 1-1) akan menggelikan. --Memiliki Astels
Bagian penting dari itu adalah
* Dan pemikiran menguji setiap metode Anda dengan metode pengujiannya sendiri (dalam hubungan 1-1) akan menggelikan. *
Jadi, jika membuat tes untuk setiap metode adalah 'laughable', bagaimana / kapan Anda memilih untuk apa Anda menulis tes?
sumber
Jawaban:
Berapa banyak tes per metode?
Yah maksimum teoritis dan sangat tidak praktis adalah kompleksitas N-Path (anggap semua tes mencakup cara yang berbeda melalui kode;)). Minimal adalah SATU! Per metode publik yaitu, ia tidak menguji detail implementasi, hanya perilaku eksternal suatu kelas (mengembalikan nilai & memanggil objek lain).
Anda mengutip:
dan kemudian bertanya:
Tapi saya pikir Anda salah paham tentang penulis di sini:
Gagasan memiliki
one test method
perone method in the class to test
adalah apa yang penulis sebut "menggelikan".(Setidaknya bagi saya) Ini bukan tentang 'kurang' ini tentang 'lebih banyak'
Jadi izinkan saya ulangi seperti saya memahaminya:
Dan pemikiran menguji setiap metode Anda dengan HANYA SATU METODE (metode pengujian sendiri dalam hubungan 1-1) akan menggelikan.
Mengutip penawaran Anda lagi:
Ketika Anda berlatih TDD Anda tidak berpikir :
Saya punya metode
calculateX($a, $b);
dan perlu testestCalculcateX
yang menguji SEMUA tentang metode ini.Apa yang dikatakan TDD kepada Anda adalah untuk berpikir tentang apa kode Anda HARUS LAKUKAN :
Saya perlu menghitung lebih besar dari dua nilai ( test case pertama! ) Tetapi jika $ a lebih kecil dari nol maka ia harus menghasilkan kesalahan ( case test kedua! ) Dan jika $ b lebih kecil dari nol seharusnya .... ( test case ketiga! ) dan seterusnya.
Anda ingin menguji perilaku, bukan hanya metode tunggal tanpa konteks.
Dengan begitu Anda mendapatkan test suite yang merupakan dokumentasi untuk kode Anda dan BENAR-BENAR menjelaskan apa yang diharapkan untuk dilakukan, mungkin bahkan mengapa :)
Bagaimana cara Anda memutuskan bagian kode mana yang Anda buat untuk pengujian unit?
Ya, segala sesuatu yang berakhir di repositori atau di dekat produksi memerlukan tes. Saya tidak berpikir penulis kutipan Anda tidak akan setuju dengan itu ketika saya mencoba untuk menyatakan di atas.
Jika Anda tidak memiliki tes untuk itu akan lebih sulit (lebih mahal) untuk mengubah kode, terutama jika bukan Anda yang membuat perubahan.
TDD adalah cara untuk memastikan bahwa Anda memiliki tes untuk SEMUA tetapi selama Anda MENULIS tes itu baik-baik saja. Biasanya menulisnya pada hari yang sama membantu karena Anda tidak akan melakukannya nanti, bukan? :)
Tanggapan terhadap komentar:
Ada tiga hal yang bisa disebut metode ini:
Metode publik dari kelas lain
Kita dapat mengejek kelas lain sehingga kita telah menetapkan status di sana. Kami mengendalikan konteks sehingga tidak masalah di sana.
* Metode yang dilindungi atau pribadi pada yang sama *
Apa pun yang bukan bagian dari API umum suatu kelas tidak diuji secara langsung, biasanya.
Anda ingin menguji perilaku dan bukan implementasi dan jika kelas melakukan semua itu berfungsi dalam satu metode publik besar atau dalam banyak metode yang lebih kecil yang dilindungi disebut implementasi . Anda ingin dapat MENGUBAH metode yang dilindungi tersebut tanpa menyentuh tes Anda. Karena tes Anda akan rusak jika kode Anda berubah perilaku! Untuk itulah tes Anda, untuk memberi tahu Anda ketika Anda memecahkan sesuatu :)
Metode publik di kelas yang sama
Itu tidak sering terjadi bukan? Dan jika memang suka dalam contoh berikut ada beberapa cara untuk menangani ini:
Bahwa setter ada dan bukan bagian dari metode eksekusi tanda tangan adalah topik lain;)
Apa yang bisa kita uji di sini adalah jika eksekusi tidak meledak ketika kita menetapkan nilai yang salah. Itu
setBla
melempar pengecualian ketika Anda melewatkan string dapat diuji secara terpisah, tetapi jika kami ingin menguji bahwa kedua nilai yang diizinkan (12 & 14) tidak bekerja BERSAMA (untuk alasan apa pun) daripada satu kasus uji.Jika Anda menginginkan test suite "baik", Anda dapat, di php, mungkin (!) Menambahkan
@covers Stuff::execute
anotasi untuk memastikan Anda hanya menghasilkan cakupan kode untuk metode ini dan hal-hal lain yang baru saja setup perlu diuji secara terpisah (sekali lagi, jika kamu menginginkan itu).Jadi intinya adalah: Mungkin Anda harus membuat beberapa dunia di sekitarnya terlebih dahulu tetapi Anda harus dapat menulis kasus uji yang bermakna yang biasanya hanya menjangkau satu atau mungkin dua fungsi nyata (setter tidak dihitung di sini). Sisanya dapat diejek atau di tes terlebih dahulu dan kemudian diandalkan (lihat
@depends
)* Catatan: Pertanyaannya dimigrasikan dari SO dan awalnya tentang PHP / PHPUnit, itu sebabnya contoh kode dan referensi dari dunia php, saya pikir ini juga berlaku untuk bahasa lain karena phpunit tidak berbeda jauh dari yang lain xUnit kerangka kerja pengujian.
sumber
Pengujian dan Pengujian Unit bukan hal yang sama. Unit Testing adalah bagian yang sangat penting dan menarik dari Pengujian secara keseluruhan. Saya akan mengklaim bahwa fokus Unit Testing membuat kami berpikir tentang pengujian semacam ini dengan cara yang agak bertentangan dengan kutipan di atas.
Pertama, jika kita mengikuti TDD atau bahkan DTH (yaitu mengembangkan dan menguji dengan harmonis) kita menggunakan tes yang kita tulis sebagai fokus untuk memperbaiki desain kita. Dengan memikirkan kasus sudut dan menulis tes sesuai dengan itu kami menghindari bug masuk di tempat pertama, jadi sebenarnya kami menulis tes yang kami harapkan lulus (OK tepat pada awal TDD mereka gagal, tapi itu hanya artefak pemesanan, ketika kode selesai kami harapkan mereka lulus, dan sebagian besar melakukannya, karena Anda sudah memikirkan kode tersebut.
Kedua, Tes Unit benar-benar menjadi milik mereka saat kami melakukan refactor. Kami mengubah implementasi kami tetapi mengharapkan jawaban tetap sama - Uji Unit adalah perlindungan kami terhadap melanggar kontrak antarmuka kami. Jadi satu lagi kami berharap tes lulus.
Ini menyiratkan bahwa untuk antarmuka publik kami, yang mungkin stabil, kami membutuhkan keterlacakan yang jelas sehingga kami dapat melihat bahwa setiap metode publik diuji.
Untuk menjawab pertanyaan eksplisit Anda: Tes Unit untuk antarmuka publik memiliki nilai.
diedit dalam komentar tanggapan:
Menguji metode pribadi? Ya, kita harus, tetapi jika kita tidak harus menguji sesuatu maka di situlah saya berkompromi. Lagipula jika metode publik berfungsi maka bisakah bug-bug itu menjadi barang pribadi begitu penting? Secara pragmatis, churn cenderung terjadi pada hal-hal pribadi, Anda bekerja keras untuk mempertahankan antarmuka publik Anda, tetapi jika hal-hal yang Anda bergantung pada perubahan hal-hal pribadi dapat berubah. Pada titik tertentu kita mungkin menemukan mempertahankan tes internal adalah banyak usaha. Apakah upaya itu dihabiskan dengan baik?
sumber
Tes unit harus menjadi bagian dari strategi pengujian yang lebih besar. Saya mengikuti prinsip-prinsip ini dalam memilih jenis tes apa yang akan ditulis dan kapan:
Fokus pada penulisan tes ujung ke ujung. Anda mencakup lebih banyak kode per tes daripada dengan unit test dan karenanya mendapatkan lebih banyak pengujian untuk hasil Jadikan ini validasi otomatis roti dan mentega sistem Anda secara keseluruhan.
Drop down untuk menulis tes unit di sekitar nugget logika yang rumit. Tes unit bernilai berat dalam situasi di mana tes ujung ke ujung akan sulit untuk di-debug atau sulit untuk ditulis untuk cakupan kode yang memadai.
Tunggu hingga API yang Anda uji stabil untuk menulis kedua jenis tes. Anda ingin menghindari refactor implementasi dan pengujian Anda.
Rob Ashton memiliki artikel bagus tentang topik ini, yang saya banyak manfaatkan untuk mengartikulasikan prinsip-prinsip di atas.
sumber
Saya cenderung mengikuti pendekatan berbeda untuk pengujian unit yang tampaknya bekerja dengan baik. Alih-alih menganggap unit test sebagai "Menguji beberapa perilaku" saya lebih menganggapnya sebagai "spesifikasi yang harus diikuti oleh kode saya". Dengan cara ini, Anda pada dasarnya dapat menyatakan bahwa suatu objek harus berperilaku dengan cara tertentu, dan mengingat bahwa Anda berasumsi bahwa di tempat lain dalam program Anda, Anda dapat yakin itu relatif bebas bug.
Jika Anda menulis API publik, ini sangat berharga. Namun, Anda akan selalu memerlukan dosis yang baik dari tes integrasi end-to-end juga karena mendekati cakupan tes unit 100% biasanya tidak layak dan akan kehilangan hal-hal yang kebanyakan akan dianggap "tidak dapat diuji" oleh metode pengujian unit (mengejek, dll)
sumber