Saya sedang mengembangkan plugin menggunakan TDD dan satu hal yang saya benar-benar gagal untuk menguji adalah ... kait.
Maksudku OK, saya bisa menguji hook hookback, tetapi bagaimana saya bisa menguji apakah hook benar-benar memicu (baik hook kustom dan WordPress default hooks)? Saya berasumsi bahwa beberapa ejekan akan membantu, tetapi saya tidak tahu apa yang saya lewatkan.
Saya menginstal test suite dengan WP-CLI. Menurut jawaban ini , init
hook seharusnya menjadi pemicu, namun ... tidak; juga, kode tersebut berfungsi di dalam WordPress.
Dari pemahaman saya, bootstrap dimuat terakhir, jadi masuk akal untuk tidak memicu init, jadi pertanyaan yang tersisa adalah: bagaimana sih saya harus menguji apakah kait dipicu?
Terima kasih!
File bootstrap terlihat seperti ini:
$_tests_dir = getenv('WP_TESTS_DIR');
if ( !$_tests_dir ) $_tests_dir = '/tmp/wordpress-tests-lib';
require_once $_tests_dir . '/includes/functions.php';
function _manually_load_plugin() {
require dirname( __FILE__ ) . '/../includes/RegisterCustomPostType.php';
}
tests_add_filter( 'muplugins_loaded', '_manually_load_plugin' );
require $_tests_dir . '/includes/bootstrap.php';
File yang diuji terlihat seperti ini:
class RegisterCustomPostType {
function __construct()
{
add_action( 'init', array( $this, 'register_post_type' ) );
}
public function register_post_type()
{
register_post_type( 'foo' );
}
}
Dan tes itu sendiri:
class CustomPostTypes extends WP_UnitTestCase {
function test_custom_post_type_creation()
{
$this->assertTrue( post_type_exists( 'foo' ) );
}
}
Terima kasih!
sumber
phpunit
, dapatkah Anda melihat tes yang gagal atau lulus? Apakah Anda menginstalbin/install-wp-tests.sh
?RegisterCustomPostType::__construct()
tidak pernah dipanggil ketika plugin dimuat untuk pengujian. Mungkin juga Anda dipengaruhi oleh bug # 29827 ; mungkin mencoba memperbarui versi unit test WP Anda.bin/install-wp-tests.sh
(karena saya menggunakan wp-cli) @JD: RegisterCustomPostType :: __ construct yang disebut (hanya menambahkandie()
pernyataan dan phpunit berhenti di sana)did_action()
untuk memeriksa apakah tindakan telah dipecat.init
hook).Jawaban:
Tes dalam isolasi
Saat mengembangkan sebuah plugin, cara terbaik untuk mengujinya adalah tanpa memuat lingkungan WordPress.
Jika Anda menulis kode yang dapat dengan mudah diuji tanpa WordPress, kode Anda menjadi lebih baik .
Setiap komponen yang diuji unit, harus diuji secara terpisah : ketika Anda menguji suatu kelas, Anda hanya perlu menguji kelas tersebut, dengan asumsi semua kode lain berfungsi dengan sempurna.
Inilah alasan mengapa unit test disebut "unit".
Sebagai manfaat tambahan, tanpa memuat inti, pengujian Anda akan berjalan jauh lebih cepat.
Hindari kait di konstruktor
Kiat yang bisa saya berikan kepada Anda adalah menghindari memasukkan kait ke dalam konstruktor. Itulah salah satu hal yang akan membuat kode Anda dapat diuji secara terpisah.
Mari kita lihat kode tes di OP:
Dan mari kita asumsikan tes ini gagal . Siapa pelakunya ?
Bagaimana itu bisa ditingkatkan?
Anggap kode kelas Anda adalah:
(Catatan: Saya akan merujuk ke versi kelas ini untuk sisa jawabannya)
Cara saya menulis kelas ini memungkinkan Anda untuk membuat instance kelas tanpa memanggil
add_action
.Di kelas di atas ada 2 hal yang harus diuji:
init
sebenarnya memanggiladd_action
lewat untuk argumen yang tepatregister_post_type
sebenarnya memanggilregister_post_type
fungsiSaya tidak mengatakan bahwa Anda harus memeriksa apakah jenis posting ada: jika Anda menambahkan tindakan yang tepat dan jika Anda menelepon
register_post_type
, jenis posting kustom harus ada: jika tidak ada itu adalah masalah WordPress.Ingat: ketika Anda menguji plugin Anda, Anda harus menguji kode Anda , bukan kode WordPress. Dalam pengujian Anda, Anda harus menganggap bahwa WordPress (seperti perpustakaan eksternal lain yang Anda gunakan) berfungsi dengan baik. Itulah arti dari unit test.
Tapi ... dalam praktek?
Jika WordPress tidak dimuat, jika Anda mencoba memanggil metode kelas di atas, Anda mendapatkan kesalahan fatal, jadi Anda perlu mengejek fungsinya.
Metode "manual"
Tentu Anda dapat menulis perpustakaan mengejek Anda atau "secara manual" mengejek setiap metode. Itu mungkin. Saya akan memberi tahu Anda cara melakukan itu, tetapi kemudian saya akan menunjukkan kepada Anda metode yang lebih mudah.
Jika WordPress tidak dimuat saat tes sedang berjalan, itu berarti Anda dapat mendefinisikan kembali fungsinya, misalnya
add_action
atauregister_post_type
.Mari kita asumsikan Anda memiliki file, diambil dari file bootstrap Anda, di mana Anda memiliki:
Saya menulis ulang fungsi untuk hanya menambahkan elemen ke array global setiap kali mereka dipanggil.
Sekarang Anda harus membuat (jika Anda belum memilikinya) memperluas kelas kasus uji dasar Anda
PHPUnit_Framework_TestCase
: yang memungkinkan Anda untuk dengan mudah mengkonfigurasi tes Anda.Itu bisa berupa:
Dengan cara ini, sebelum setiap tes, penghitung global diatur ulang.
Dan sekarang kode pengujian Anda (saya merujuk pada kelas yang ditulis ulang yang saya posting di atas):
Anda harus mencatat:
Bagus .. tapi itu PITA!
Ya, jika Anda harus secara manual mengejek semua fungsi WordPress, itu benar-benar menyebalkan. Beberapa saran umum yang dapat saya berikan adalah menggunakan sesedikit mungkin fungsi WP: Anda tidak perlu menulis ulang WordPress, tetapi fungsi WP abstrak yang Anda gunakan di kelas khusus, sehingga dapat diejek dan diuji dengan mudah.
Misalnya mengenai contoh di atas, Anda dapat menulis kelas yang mendaftarkan jenis posting, memanggil
register_post_type
'init' dengan argumen yang diberikan. Dengan abstraksi ini Anda masih perlu menguji kelas itu, tetapi di tempat lain dari kode Anda yang mendaftarkan jenis posting Anda dapat menggunakan kelas itu, mengejeknya dalam tes (jadi dengan asumsi itu berfungsi).Yang luar biasa adalah, jika Anda menulis kelas yang mengabstraksi pendaftaran CPT, Anda dapat membuat repositori terpisah untuknya, dan terima kasih kepada alat-alat modern seperti Composer menanamkannya dalam semua proyek di mana Anda membutuhkannya: uji sekali, gunakan di mana-mana . Dan jika Anda pernah menemukan bug di dalamnya, Anda dapat memperbaikinya di satu tempat dan dengan sederhana
composer update
semua proyek di mana ia digunakan juga diperbaiki.Untuk kedua kalinya: menulis kode yang dapat diuji secara terpisah berarti menulis kode yang lebih baik.
Tapi cepat atau lambat saya harus menggunakan fungsi WP di suatu tempat ...
Tentu saja. Anda tidak boleh bertindak sejajar dengan inti, itu tidak masuk akal. Anda bisa menulis kelas yang membungkus fungsi WP, tetapi kelas-kelas itu perlu diuji juga. Metode "manual" yang diuraikan di atas dapat digunakan untuk tugas-tugas yang sangat sederhana, tetapi ketika sebuah kelas berisi banyak fungsi WP, itu bisa menyebalkan.
Untungnya, di sana ada orang baik yang menulis hal-hal baik. 10up , salah satu agen WP terbesar, memiliki perpustakaan yang sangat bagus untuk orang yang ingin menguji plugin dengan cara yang benar. Itu
WP_Mock
.Hal ini memungkinkan Anda untuk mengejek fungsi WP sebuah kait . Dengan asumsi Anda telah dimuat dalam tes Anda (lihat repo readme) tes yang sama yang saya tulis di atas menjadi:
Sederhana bukan? Jawaban ini bukan tutorial untuk
WP_Mock
, jadi baca repo readme untuk info lebih lanjut, tetapi contoh di atas harus cukup jelas, saya pikir.Selain itu, Anda tidak perlu menulis apa pun yang dipermainkan
add_action
atau sendirianregister_post_type
, atau mempertahankan variabel global apa pun.Dan kelas WP?
WP juga memiliki beberapa kelas, dan jika WordPress tidak dimuat saat Anda menjalankan tes, Anda perlu mengejeknya.
Itu jauh lebih mudah daripada fungsi mengejek, PHPUnit memiliki sistem tertanam untuk mengejek objek, tetapi di sini saya ingin menyarankan Mockery kepada Anda. Ini adalah perpustakaan yang sangat kuat dan sangat mudah digunakan. Selain itu, ini adalah ketergantungan
WP_Mock
, jadi jika Anda memilikinya, Anda juga memiliki ejekan.Tapi bagaimana dengan itu
WP_UnitTestCase
?Suite pengujian WordPress dibuat untuk menguji inti WordPress , dan jika Anda ingin berkontribusi pada inti itu sangat penting, tetapi menggunakannya untuk plugin hanya membuat Anda menguji tidak secara terpisah.
Letakkan mata Anda di dunia WP: ada banyak kerangka kerja PHP dan CMS modern di luar sana dan tidak ada yang menyarankan pengujian plugin / modul / ekstensi (atau apa pun namanya) menggunakan kode kerangka kerja.
Jika Anda melewatkan pabrik, fitur berguna dari suite, Anda harus tahu bahwa ada hal-hal luar biasa di sana.
Gotchas dan kerugiannya
Ada kasus ketika alur kerja yang saya sarankan di sini kurang: pengujian basis data khusus .
Bahkan, jika Anda menggunakan tabel dan fungsi WordPress standar untuk menulis di sana (pada
$wpdb
metode level terendah ) Anda tidak perlu benar - benar menulis data atau menguji apakah data benar - benar dalam database, pastikan saja metode yang tepat dipanggil dengan argumen yang tepat.Namun, Anda dapat menulis plugin dengan tabel kustom dan fungsi yang membuat kueri untuk ditulis di sana, dan menguji apakah kueri itu berfungsi, itu adalah tanggung jawab Anda.
Dalam kasus-kasus itu, WordPress test suite dapat banyak membantu Anda, dan memuat WordPress mungkin diperlukan dalam beberapa kasus untuk menjalankan fungsi-fungsi seperti
dbDelta
.(Tidak perlu dikatakan untuk menggunakan db yang berbeda untuk tes, bukan?)
Untungnya PHPUnit memungkinkan Anda untuk mengatur tes Anda di "suite" yang dapat dijalankan secara terpisah, sehingga Anda dapat menulis suite untuk tes basis data khusus tempat Anda memuat lingkungan WordPress (atau sebagian darinya) meninggalkan semua tes Anda bebas WordPress .
Pastikan untuk menulis kelas yang abstrak sebanyak mungkin operasi basis data, dengan cara semua kelas plugin lainnya memanfaatkannya, sehingga dengan mengolok-olok Anda dapat dengan benar menguji mayoritas kelas tanpa berurusan dengan basis data.
Untuk ketiga kalinya, menulis kode mudah diuji dalam isolasi berarti menulis kode yang lebih baik.
sumber