Advertisement
  1. Code
  2. Web Development

Memulai dengan Phpspec

by
Read Time:15 minsLanguages:

Indonesian (Bahasa Indonesia) translation by Arief Syahrir (you can also view the original English article)

Dalam tutorial ini pendek, belum komprehensif, kita akan melihat behavior driven development (BDD) dengan phpspec. Sebagian besar, itu akan menjadi pengantar tool phpspec, tetapi ketika kami pergi, kami akan menyentuh pada konsep-konsep BDD yang berbeda. BDD adalah topik panas hari ini dan phpspec telah mendapatkan banyak perhatian dalam komunitas PHP baru saja.

SpecBDD & Phpspec

BDD adalah semua tentang menggambarkan perilaku perangkat lunak, untuk mendapatkan desain yang tepat. Hal ini sering dikaitkan dengan TDD, tapi sedangkan TDD berfokus pada pengujian aplikasi Anda, BDD lebih tentang menggambarkan perilaku. Dengan menggunakan pendekatan BDD akan memaksa Anda untuk terus-menerus mempertimbangkan persyaratan aktual dan perilaku yang diinginkan dari perangkat lunak yang Anda sedang bangun.

Dua tool BDD telah mendapatkan banyak perhatian dalam komunitas PHP baru-baru ini, Behat dan phpspec. Behat membantu Anda menggambarkan perilaku eksternal aplikasi Anda, menggunakan bahasa Gherkin dapat dibaca. phpspec, di sisi lain, membantu Anda menggambarkan perilaku internal aplikasi Anda, dengan menulis kecil "spesifikasi" di bahasa PHP - maka SpecBDD. Spesifikasi ini menguji bahwa kode Anda memiliki perilaku yang diinginkan.

Apa yang akan kita lakukan

Dalam tutorial ini, kita akan membahas segala sesuatu yang berkaitan dengan phpspec. Perjalanan kami, kami akan membangun fundament todo daftar aplikasi, langkah demi langkah, dengan menggunakan pendekatan SpecBDD. Ketika kita pergi, kita akan memiliki phpspec memimpin jalan!

Catatan: Ini adalah artikel menengah tentang PHP. Saya menganggap Anda memiliki pemahaman yang baik tentang PHP berorientasi objek.

Instalasi

Untuk tutorial ini, saya menganggap Anda memiliki hal-nal berikut dan berjalan:

Instalasi phpspec melalui composer adalah cara termudah. Semua yang harus Anda lakukan adalah menjalankan perintah berikut dalam terminal:

Ini akan membuat composer.json file untuk Anda dan menginstal phpspec di vendor/ Direktori.

Untuk memastikan bahwa semuanya bekerja, menjalankan phpspec dan melihat bahwa Anda mendapatkan output yang berikut:

Konfigurasi

Sebelum kita mulai, kita perlu melakukan sedikit konfigurasi. ketika phpspec berjalan, akan mencarifile YAML bernama phpspec.yml. Karena kami akan menempatkan kode kita dalam sebuah namespace, kita perlu memastikan bahwa phpspec tahu tentang hal ini. Juga, sementara kita berada di itu, mari kita pastikan bahwa spesifikasi kami terlihat bagus dan cantik saat kami menjalankan mereka.

Pergi ke depan dan membuat file dengan isi sebagai berikut:

Ada banyak opsi konfigurasi lain tersedia, yang Anda dapat baca dalam dokumentasi.

Hal lain yang perlu kita lakukan, adalah untuk memberitahu composer bagaimana autoload kode kita. phpspec akan menggunakan autoloader composer, sehingga hal ini diperlukan untuk spesifikasi kami untuk dijalankan.

Menambahkan unsur autoload ke file composer.json bahwa Composer dibuat untuk Anda:

Menjalankan composer dump-autoload akan memperbarui autoloader setelah perubahan ini.

Spec pertama kami

Sekarang kita siap untuk menulis spec pertama kami. Kita akan mulai dengan menggambarkan class yang disebut TaskCollection. Kita akan memiliki phpspec menghasilkan spesifikasi class bagi kita dengan menggunakan perintah describe (atau alternatif desc versi pendek).

Jadi apa yang terjadi di sini? Pertama, kami meminta phpspec untuk menciptakan spesifikasi untuk TaskCollection. Kedua, kami menjalankan spec kami suite dan kemudian phpspec otomatis ditawarkan untuk menciptakan class TaskCollection yang sebenarnya untuk kami. Keren, bukan?

Pergi ke depan dan menjalankan suite lagi, dan Anda akan melihat bahwa kita sudah memiliki satu contoh spec kami (kita akan melihat dalam sekejap apa contoh):

Dari output ini, kita dapat melihat bahwa TaskCollection initializable. Tentang apakah ini? Lihatlah spec file phpspec yang dihasilkan, dan itu harus jelas:

Ungkapan 'initializable' berasal dari fungsi bernama it_is_initializable() phpspec yang telah ditambahkan ke class yang disebut TaskCollectionSpec. Fungsi ini adalah apa yang kita sebut sebagai contoh. Dalam contoh khusus ini, kami memiliki apa yang kita sebut sebagai matcher yang disebut shouldHaveType() yang memeriksa jenis TaskCollection kami. Jika Anda mengubah parameter yang dimasukan ke fungsi ini ke sesuatu yang lain dan menjalankan spec lagi, Anda akan melihat bahwa itu akan gagal. Sebelum benar-benar memahami hal ini, saya pikir kita perlu menyelidiki dalam variabel $this merujuk kepada spec kami.

Apa itu $this?

Tentu saja, $this merujuk ke instance class TaskCollectionSpec, karena ini adalah hanya biasa kode PHP. Tetapi dengan phpspec, Anda harus memperlakukan $this berbeda dari apa yang Anda biasanya lakukan, karena di belakang layar, itu sebenarnya merujuk ke objek di bawah tes, yang sebenarnya adalah class TaskCollection. Perilaku ini mewarisi dari kelas ObjectBehavior, yang membuat yakin bahwa fungsi panggilan proxy spec'ed class. Ini berarti bahwa SomeClassSpec akan proxy metode panggilan ke instance SomeClass. phpspec akan membungkus panggilan metode ini untuk menjalankan kembali nilai-nilai mereka terhadap matchers seperti yang Anda hanya lihat.

Anda tidak memerlukan pemahaman yang mendalam ini untuk menggunakan phpspec, hanya ingat bahwa sejauh Anda tahu, $this sebenarnya merujuk ke objek di bawah tes.

Membangun Task Collection

Sejauh ini, kita belum melakukan apa-apa sendiri. Tapi phpspec telah membuat kelas TaskCollection kosong untuk kita gunakan. Sekarang adalah waktu untuk mengisi beberapa kode dan membuat class ini berguna. Kami akan menambahkan dua metode: add() metode, untuk menambahkan tugas, dan count() metode, untuk menghitung jumlah tugas dalam koleksi.

Menambahkan tugas

Sebelum kita menulis kode apapun nyata, kita harus menulis contoh spec kami. Dalam contoh kita, kami ingin mencoba untuk menambahkan tugas ke koleksi, dan kemudian setelah itu membuat yakin bahwa tugas bahkan ditambahkan. Untuk melakukan ini, kita perlu instance class (sejauh tidak ada) Task. Jika kita menambahkan ketergantungan ini sebagai parameter ke fungsi spec kami, phpspec akan secara otomatis memberikan kita contoh yang dapat kita gunakan. Sebenarnya, instance bukan instance asli, tapi apa phpspec mengacu sebagai Collaborator. Objek ini akan bertindak sebagai objek yang sesungguhnya, tetapi phpspec memungkinkan kita untuk melakukan lebih banyak barang mewah dengan ini, yang kita akan melihat segera. Meskipun Task class tidak ada lagi, untuk saat ini, hanya berpura-pura itu. Membuka TaskCollectionSpec dan menambahkan pernyataan use untuk Task class dan kemudian menambahkan contoh it_adds_a_task_to_the_collection():

Dalam contoh kita, kita menulis kode "kami berharap bisa memiliki". Kita memanggil metode add() dan kemudian mencoba untuk memberikan $task. Kemudian kami memeriksa bahwa task bahkan ditambahkan ke variabel instance $tasks. Matcher shouldBe() adalah identitas matcher mirip dengan PHP === komparator. Anda dapat menggunakan baik shouldBe(), shouldBeEqualTo(), shouldEqual() atau shouldReturn() - mereka semua melakukan hal yang sama.

Phpspec berjalan akan menghasilkan beberapa kesalahan, karena kita tidak memiliki class bernama Task.

Mari kita memiliki phpspec memperbaikinya bagi kita:

Menjalankan phpspec lagi, sesuatu yang menarik terjadi:

Sempurna! Jika Anda melihat file TaskCollection.php, Anda akan melihat bahwa phpspec yang membuat fungsi add() bagi kita untuk mengisi:

phpspec yang masih mengeluh, meskipun. Kami tidak memiliki $tasks array, jadi mari kita membuat satu dan menambahkan tugas untuk itu:

Sekarang spesifikasi kami semua bagus dan hijau. Perhatikan bahwa saya memastikan untuk typehint $task parameter.

Hanya untuk memastikan kita mendapatkannya tepat, mari kita menambahkan task lain:

Menjalankan phpspec, sepertinya kita sedang semua baik.

Mengimplementasikan interface Countable

Kami ingin tahu berapa banyak tugas dalam koleksi, yang merupakan alasan yang baik untuk menggunakan salah satu interface dari Standard PHP Library (SPL), yaitu interface Countable. Interface ini menyatakan bahwa kelas mengimplementasikannya harus memiliki metode count().

Sebelumnya, kami menggunakan matcher shouldHaveType(), yang merupakan jenis matcher. Menggunakan instanceof komparator PHP untuk memvalidasi bahwa objek sebenarnya adalah instance class tertentu. Ada 4 jenis matchers, di mana semua melakukan hal yang sama. Salah satunya adalah shouldImplement(), yang sempurna untuk tujuan kita, jadi mari kita pergi ke depan dan menggunakannya dalam sebuah contoh:

Lihat betapa indah yang membaca? Mari kita menjalankan contoh dan memiliki phpspec yang memimpin jalan bagi kita:

Oke, jadi class kami bukan instance Countable karena kita belum menerapkannya. Mari kita memperbarui kode untuk class TaskCollection kami:

Pengujian kami tidak berjalan, karena interface Countable memiliki metode yang abstrak, count(), yang kita miliki untuk menerapkan. Metode yang kosong akan melakukan trik untuk sekarang:

Dan kita kembali ke hijau. Saat ini metode count() kami tidak berbuat banyak, dan itu benar-benar cukup berguna. Mari kita menulis spesifikasi untuk perilaku yang kami berharap untuk memiliki. Pertama, dengan tidak ada tugas, fungsi menghitung kita diharapkan untuk mengembalikan nol:

Mengembalikan nilai null, bukan 0. Untuk mendapatkan tes hijau, mari kita memperbaiki hal ini dengan cara TDD.BDD:

sudah hijau dan semua itu baik, tapi ini tidak mungkin perilaku yang kita inginkan. Sebaliknya, mari kita memperluas spec kami dan menambahkan sesuatu ke $tasks array:

Tentu saja, kode kita masih mengembalikan 0, dan kami memiliki langkah merah. Memperbaiki ini tidak terlalu sulit dan kelas TaskCollection kami sekarang harus terlihat seperti ini:

Kami memiliki tes hijau dan count() metode bekerja. Hari apa ini!

Ekpetasi & harapan

Ingat saya katakan bahwa phpspec memungkinkan Anda untuk hal keren dengan contoh class Collaborator, alias contoh yang secara otomatis disuntikkan oleh phpspec? Jika Anda telah menulis unit test sebelumnya, Anda pasti tahu apa itu mock dan stub. Jika Anda tidak, jangan khawatir terlalu banyak tentang hal itu. Hal ini hanya jargon. Hal ini mengacu pada "fake" objek yang akan bertindak sebagai objek nyata Anda, tetapi memungkinkan Anda untuk menguji dalam isolasi. phpspec akan secara otomatis berganti kepada Collaborator iinstance ke mock dan stub: jika Anda membutuhkannya dalam spesifikasi Anda.

Ini benar-benar mengagumkan. Di belakang layar, phpspec menggunakan perpustakaan Prophecy, yang adalah framework mocking sangat dogmatis yang bermain baik dengan phpspec (dan dibuat oleh orang-orang luar biasa yang sama). Anda dapat menetapkan ekpetasi pada kolaborator (mocking), seperti "metode harus dipanggil", dan Anda dapat menambahkan janji-janji (stubbing), seperti "metode ini akan mengembalikan nilai ini". Dengan phpspec ini benar-benar mudah dan kami akan melakukan hal-hal kedua berikutnya.

Mari kita membuat class, kita akan menyebutnya TodoList, yang dapat membuat penggunaan class koleksi kami.

Menambahkan Task

Contoh pertama kami akan menambahkan, adalah salah satu untuk menambahkan task. Kami akan membuat addTask() metode, yang tidak melakukan apa lebih dari menambahkan tugas untuk koleksi kami. Ini hanya mengarahkan memanggil ke metode add() pada koleksi, jadi ini adalah tempat yang sempurna untuk membuat penggunaan ekpetasi. Kita tidak ingin metode untuk benar-benar memanggil metode add(), kami hanya ingin memastikan bahwa mencoba untuk melakukannya. Selain itu, kami ingin memastikan bahwa ini hanya sekali dipanggil. Lihatlah bagaimana kita bisa pergi tentang hal ini dengan phpspec:

Pertama, kita memiliki phpspec menyediakan kami dengan dua kolaborator kami membutuhkan: kumpulan tugas dan tugas. Kemudian kita menetapkan harapan pada tugas koleksi kolaborator pada dasarnya mengatakan: "metode add() harus dipanggil persis 1 kali dengan variabel $task sebagai parameter". Ini adalah bagaimana kita mempersiapkan kolaborator kami, yang sekarang mock, sebelum kita menetapkannya ke properti $tasks di TodoList. Akhirnya, kami mencoba untuk benar-benar memanggil metode addTask().

OK, phpspec Apakah mengatakan tentang ini:

Properti $tasks ini tidak ada - mudah:

Coba lagi, dan memiliki panduan cara kami phpspec:

Oke, sekarang sesuatu yang menarik terjadi. Melihat pesan "Expected exactly 1 calls that match:..."? Ini adalah harapan gagal kami. Hal ini terjadi karena setelah memanggil metode addTask(), metode add() pada koleksi tidak dipanggil, yang kami harapkan hal itu terjadi.

Untuk mendapatkan kembali ke green, isi kode berikut dalam metode kosong addTask():

Kembali ke hijau! Rasanya enak, benar?

Memeriksa untuk Task

Mari kita lihat pada janji-janji juga. Kami ingin metode yang dapat memberitahu kami jika ada tugas apapun dalam koleksi. Untuk ini, kita akan hanya memeriksa nilai kembali metode count() pada koleksi. Sekali lagi, kita tidak perlu instance asli dengan metode count() asli. Kita hanya perlu untuk memastikan bahwa kode kita memanggil metode count() beberapa dan melakukan beberapa hal tergantung pada nilai kembalian.

Lihatlah contoh berikut:

Kami memiliki tugas kolaborator koleksi yang memiliki metode count() yang akan mengembalikan nilai nol. Ini adalah janji kami. Apakah ini berarti bahwa setiap kali seseorang memanggil metode count(), itu akan mengmbalikan nilai nol. Kami kemudian menetapkan kolaborator untuk properti $tasks pada objek. Akhirnya, kami mencoba untuk memanggil metode, hasTasks(), dan membuat yakin itu mengembalikan nilai false.

Apa phspec harus katakan tentang hal ini?

Dingin. phpspec membuat kita hasTasks() metode dan tidak mengherankan, mengembalikan null, bukan false.

Sekali lagi, ini adalah salah satu yang mudah untuk memperbaiki:

Kami kembali ke hijau, tetapi hal ini tidak cukup apa yang kita inginkan. Mari kita periksa untuktask ketika ada 20 dari mereka. Ini harus mengembalikan nilai true:

Menjalankan phspec dan kami akan mendapatkan:

Oke, false bukan true, jadi kita perlu memperbaiki kode kita. Mari kita menggunakan metode count() untuk melihat apakah ada task atau tidak:

Tah dah! Kembali ke hijau!

Bangunan kustom Matchers

Bagian menulis spesifikasi yang baik adalah untuk membuat mereka sebagai mudah dibaca mungkin. Contoh terakhir kami benar-benar akan meningkat sedikit, berkat phpspec's matchers kustom. Sangat mudah untuk menerapkan kustom matchers - semua harus kita lakukan adalah untuk menimpa getMatchers() metode yang merupakan warisan dari ObjectBehavior. Dengan menerapkan dua matchers kustom, spesifikasi kami dapat diubah untuk terlihat seperti ini:

Saya pikir ini terlihat cukup bagus. Ingat, bahwa refactoring spesifikasi Anda penting untuk menjaga mereka tetap up-to-date. Menerapkan matchers kustom Anda sendiri dapat membersihkan spesifikasi Anda dan membuat mereka lebih mudah dibaca.

Sebenarnya, kita dapat menggunakan negasi terhadap matchers juga:

Ya. Cukup keren!

Kesimpulan

Semua spesifikasi kami hijau dan melihat seberapa baik mereka dokumen kode kita!

Kami memiliki secara efektif dijelaskan dan mencapai perilaku yang diinginkan dari kode kita. Bukan untuk menyebutkan, kode kami adalah 100% ditutupi oleh spesifikasi kami, yang berarti bahwa refactoring tidak menakutkan menyebkan pengalaman.

Dengan mengikuti dari awal, saya berharap kau terinspirasi untuk memberikan phpspec mencoba. Lebih dari pengujian ini tool desain. Setelah Anda terbiasa untuk menggunakan phpspec (dan ini tool kode genearation keren), Anda akan memiliki waktu sulit melepaskan itu lagi! Orang sering mengeluh bahwa melakukan TDD atau BDD memperlambat mereka. Setelah memasukkan phpspec di alur kerja saya, saya benar-benar merasa sebaliknya - produktivitas saya secara signifikan ditingkatkan. Dan kode saya lebih solid!

Advertisement
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.