Artikel ini bukan panduan teoretis untuk menulis tes dan bukan bagaimana cara menggunakan alat dalam tumpukan tertentu, tetapi serangkaian pertanyaan populer, kadang-kadang bahkan banyak yang belum dibentuk, yang akan saya coba berikan jawaban. Sumber dari pertanyaan-pertanyaan ini adalah kolega, orang-orang dari kedua belah pihak dalam wawancara dan kenalan, dan jawabannya akan subyektif, pendek dan tidak lengkap, berdasarkan materi orang lain dan pengalaman mereka. Target pembaca artikel ini adalah pengembang yang menulis dengan kesuksesan tertentu, atau setidaknya mencoba menulis tes, tetapi mengalami kesulitan tertentu dalam menulisnya.
Saya mencoba untuk tidak terikat pada bahasa tertentu untuk meningkatkan jangkauan pembaca, tetapi saya akan segera membuat reservasi bahwa saya bekerja di ekosistem PHP menggunakan PHPUnit, dan karena itu beberapa kesimpulan saya mungkin tidak cocok untuk ekosistem lain. Ketika memilih pertanyaan dan menulis, saya fokus pada banyak laporan dan artikel dan menggunakannya sebagai referensi.
Alasan penulisan adalah artikel terbaru β PHPUnit. Wretting the Doctrine Entity Manager βoleh trawl , beberapa di antaranya akan saya diskusikan juga.
Daftar pertanyaan:
- Menulis atau tidak menulis tes?
- Dan jika waktu tidak dialokasikan untuk tes?
- Jenis pengujian, bagaimana cara memilih?
- Mengapa saya sulit menulis tes untuk waktu yang lama?
- Bagaimana cara menguji metode pribadi?
- Bagaimana cara menulis tes integrasi? Bagaimana cara menguji pangkalan?
- Bagaimana cara: integrasi atau fungsional?
- Apa yang harus dilakukan dengan dependensi eksternal?
- Bagaimana cara menyederhanakan navigasi antara tes dan subjek tes?
- Haruskah saya menggunakan TDD?
- Apa lagi yang bisa digunakan untuk meningkatkan kode?
Menulis atau tidak menulis tes?
Saya melihat banyak pendapat tentang hal ini, tetapi saya sendiri: saya perlu fokus pada kebutuhan bisnis.
Untuk sepotong kode yang dilakukan dalam beberapa jam di lutut, tes tidak diperlukan. Di sisi lain, untuk proyek perusahaan besar dengan ratusan tenaga kerja, semua jenis tes populer diperlukan. Dan segala sesuatu yang berada di antara kutub-kutub ini harus dianggap sebagai kasus khusus, mengevaluasi biaya jenis pengujian tertentu: dengan tes, itu harus lebih kecil daripada tanpa mereka. Secara pribadi, saya menulis tes asap bahkan untuk proyek CRUD kecil yang berlangsung beberapa minggu, karena sudah pada jarak seperti itu mereka membawa manfaat dan mengurangi biaya pengembangan.
Keuntungan dari pengujian, secara singkat dan abstrak:
- Pengurangan signifikan dalam biaya perbaikan bug karena deteksi dini.
- Memperbaiki kontrak.
- Dokumentasi tingkat rendah.
- Deteksi masalah arsitektur.
Jadi jika proyek Anda bukan skrip satu kali dari beberapa file, maka saya merekomendasikan tes tertulis. Oleh karena itu, pertanyaan dari judul harus disusun ulang: "Sejauh mana tes harus ditulis, dan yang mana?" Tentang itu lebih jauh.
Dan jika waktu tidak dialokasikan untuk tes?
Ini adalah masalah yang sangat kontroversial, jadi saya akan membuat reservasi sekali lagi bahwa saya berbicara secara eksklusif tentang pendapat subjektif saya, sementara saya mencoba melakukan ini selembut mungkin.
Menulis tes adalah tugas yang sama besarnya dengan memikirkan, mengkode, atau men-debug-nya. Tes adalah kode yang sama dengan logika bisnis atau pengontrol. Tetapi apakah Anda memiliki pertanyaan tentang mereka? Anda tidak menetapkan tugas terpisah untuk menulis controller dan tidak mengoordinasikannya dengan manajer?
Tidak perlu mencurahkan waktu tambahan untuk menulis unit dan tes integrasi. Tes ditulis sebagai bagian dari tugas utama. Pemimpin teknis proyek, sebagai pemilik repositori proyek dan orang yang kompeten, memutuskan bagaimana, apa dan dengan apa cakupan tes untuk menulis, dengan fokus pada tugas-tugas bisnis, tidak menggembungkan, tetapi mengurangi biaya pengembangan.
Namun, mungkin saja terjadi bahwa pelanggan tidak percaya pada tes dan percaya bahwa dengan bantuan mereka Anda tidak menghemat, tetapi hanya membuang waktu. Ia membayar uang dan menetapkan persyaratan, dengan kesuksesan yang sama ia dapat melarang Anda untuk menggunakan tema gelap di IDE Anda atau memesan untuk menggunakan lima spasi sebagai indentasi. Dan jika kondisinya tidak dibahas atau diskusi menemui jalan buntu, maka pilihan Anda adalah menerima kondisi tersebut atau menolak. Dengan menasihati konsekuensi.
Saya akan membuat reservasi bahwa yang terakhir ini benar hanya jika Anda dapat menulis tes, secara memadai menilai biaya mereka dan perkiraan pengembalian. Jika Anda ingin belajar bagaimana menulisnya dengan mengorbankan perusahaan pada proyek jangka pendek, dan dia menentangnya, maka saya memihaknya.
Jenis pengujian, bagaimana cara memilih?

Anda dapat melihat piramida pengujian Mike Cohen: sebagai pengembang, kami tertarik pada dua tingkat pengujian terendah. Upaya maksimal harus diberikan pada pengujian unit, ini adalah yang termurah (dengan murahnya maksud saya adalah waktu yang dihabiskan untuk pengembangan dan dukungan), tes semacam itu sangat sederhana untuk diterapkan, sangat sederhana untuk dijalankan, mereka bekerja dengan cepat.
Tetapi apakah pengujian unit selalu berlaku atau disarankan? Saya percaya bahwa untuk CRUD primitif, tes seperti itu akan memakan waktu terlalu lama dengan dampak yang kecil dan tidak menjamin apa pun. Cobalah untuk menguji repositori (Repositori di DataMapper) dan kemudian jawab pertanyaannya, apa yang diberikannya kepada kita. Tetapi untuk berbagai kalkulator, pendekatan ini akan ideal.
Selalu mencoba menulis unit test jika memungkinkan, tetapi jangan menguji apa yang tidak berguna untuk diuji.
Bagaimana cara menguji kerja bersama backend dan frontend, jika ini adalah proyek yang berbeda pada tumpukan yang berbeda? Sama seperti backend dan aplikasi mobile: ini adalah pengujian sistem, dan itu harus menarik bagi insinyur QA dan DevOps, bukan pengembang (well, hanya jika Anda tidak memiliki scrum tanpa ampun nyata, di mana satu-satunya peran yang tersedia adalah pengembang stack penuh).
Selain itu, pengujian sistem adalah yang paling mahal dalam hal pengembangan dan dukungan, baik dalam waktu maupun dalam infrastruktur. Solusi masalah yang terkait dengan ini sudah ada di luar kompetensi pengembang "linear" dan pertanyaan tentang penerapan dan volume harus diputuskan oleh direktur teknis dan pemimpin bidang bersama-sama dengan bisnis.
Mengapa saya sulit menulis tes untuk waktu yang lama?
Terkadang sulit untuk menulis tes karena kode tidak siap untuk mereka. Setumpuk massa, tempat beberapa dari mereka memberi yang lain, juga merupakan konsekuensi.
Jangan gunakan pendaftar, lajang, pelacak, Anda sangat menyulitkan hidup Anda dengan ini. Ini adalah klaim utama untuk artikel yang saya sebutkan di atas. Gunakan DI, dan terapkan repositori yang diperlukan dalam layanan segera. Patuhi hukum Demeter untuk menghindari rantai moka. Coba sedikit kerja menggunakan metodologi TDD.
Perlakukan tes seperti kode kelas satu, amati kode kualitas tinggi yang sama seperti dalam logika bisnis. Kualitas kode tes yang buruk akan menurunkan produktivitas seiring waktu.
Bagaimana cara menguji metode pribadi?
Tidak mungkin. Kami sedang menguji kontrak - antarmuka yang disediakan oleh modul ke modul lain. Kami tidak perlu menguji implementasi internal, itu bisa berubah.
Bagaimana jika ada beberapa logika rumit di dalam pengujian, dan pengujian kontrak berubah menjadi sejumlah besar input, di mana sesuatu yang aneh terjadi di dalam? Diperlukan untuk memperbaiki kode, mendistribusikannya ke kelas yang berbeda, di mana metode pribadi tersebut akan menjadi publik, mereka sudah menulis unit test. Dan jika tidak ada tes, tempat-tempat seperti itu akan sulit dideteksi, yang akan meningkatkan biaya untuk mendukung kode tersebut.
Bagaimana cara menulis tes integrasi? Bagaimana cara menguji pangkalan?
Gunakan perlengkapan. Jelajahi alat populer di tumpukan Anda.
Jangan menulis paket perlengkapan universal yang besar, gunakan nomor minimumnya. Jika Anda memerlukan keadaan objek tertentu untuk pengujian Anda, maka jangan gunakan kembali perlengkapan seperti itu di tempat lain di mana keadaan seperti itu tidak diperlukan, jika tidak, dukungan pengujian akan menjadi lebih rumit: mengubahnya untuk beberapa tes akan merusak yang lain dan memerlukan waktu tambahan.
Ada tes integrasi yang tidak melalui siklus lengkap dari permintaan ke respons, dan interaksi kelas diperiksa hanya di dalam komponen. Jika mereka tidak memiliki pekerjaan langsung dengan database, maka Anda dapat membuat satu set data dan / atau mok yang akan masuk ke input. Dalam kasus seperti itu, Anda dapat menghindari penggunaan perlengkapan dan mengurangi kompleksitas dan waktu pelaksanaan tes integrasi tersebut ke tingkat modular.
Bagaimana cara: integrasi atau fungsional?
Pengujian integrasi adalah salah satu level pengujian dalam hal isolasi. Pengujian fungsional - pengujian kepatuhan. Definisi-definisi ini terletak pada bidang-bidang yang berbeda, dan Anda tidak dapat menempatkan tanda yang sama di antara mereka, tetapi dalam praktiknya dalam percakapan di antara pengembang, mereka memiliki makna yang sama, meskipun ini tidak benar.
Apa yang harus dilakukan dengan dependensi eksternal?
Kami mengganti dependensi eksternal dengan moki. Tidak hanya untuk tes unit, tetapi juga untuk tes integrasi.
Misalnya, kami menggunakan klien HTTPS untuk mengakses beberapa API melalui kelas Guzzle. Jika Anda membuat instance kelas seperti itu di dalam kelas yang diuji, akan sulit untuk menggantinya, tetapi solusinya akan sangat sederhana: kami mengimplementasikan klien seperti itu di konstruktor, dan selama pengujian kami akan menggantinya dengan moch.
Bagaimana cara menyederhanakan navigasi antara tes dan subjek tes?
Alat pengembangan modern dapat melacak lokasi tes atau kelas tes jika Anda menggunakan standar penamaan. Untuk kemudahan navigasi, Anda dapat menggunakan pintasan keyboard Ctrl + Shift + T dalam produk JetBrains, di samping itu, jika tes tidak ada, maka Anda akan diminta untuk membuatnya dan membuat wireframe.
Kadang-kadang Anda memerlukan beberapa kelas atau metode pengujian yang berbeda untuk subjek pengujian, dalam hal ini Anda perlu membantu IDE, misalnya, menambahkan penjelasan @covers dalam kasus PHPUnit.
Haruskah saya menggunakan TDD?
TDD adalah salah satu metodologi pengembangan di mana iteratif dan tentu menulis tes pertama, dan kemudian kode. Mencoba itu pasti sepadan, itu akan mengajarkan Anda cara menulis kode yang diuji dengan baik. Namun, pendekatan ini tidak banyak digunakan, ia memiliki masalah. Salah satu masalah ini adalah Anda menulis tes yang tidak akan Anda tulis dengan pendekatan klasik. Dan tes semacam itu juga perlu didukung, menghabiskan waktu untuk itu, dan manfaatnya kecil. Misalnya, tes untuk setter atau tes untuk kelas di mana tidak ada yang terjadi kecuali panggilan ketergantungan. Tempat-tempat seperti itu paling baik diperiksa dengan pengujian integrasi.
Apa lagi yang bisa digunakan untuk meningkatkan kode?
Alat analisis statis adalah cara lain untuk meningkatkan kualitas kode Anda. Mereka sebagian tumpang tindih dengan hasil tes, tetapi mereka sering menemukan bahwa tes tidak ditemukan, terutama dengan cakupan yang buruk. Keuntungan yang tidak diragukan lagi - Anda melihat hasilnya langsung di IDE dan mendapatkan umpan balik secara instan.
Ini tidak berarti bahwa itu cukup untuk meninggalkan mereka hanya pada IDE, saya sangat merekomendasikan menggunakannya pada CI juga untuk melihat kesalahan potensial dan tidak merusak kode tersebut.
Saya juga merekomendasikan menambahkan dukungan alat pengecekan gaya kode ke IDE dan CI. Kesalahan sering disembunyikan di antara kode yang ditulis sembarangan, dan alat-alat semacam itu memungkinkan Anda menemukan area-area tersebut.
Bahan untuk studi lebih lanjut