Students Save 30%! Learn & create with unlimited courses & creative assets Students Save 30%! Save Now
Advertisement
  1. Code
  2. Laravel
Code

Laravel, BDD dan Anda: fitur pertama

by
Difficulty:IntermediateLength:LongLanguages:
This post is part of a series called Laravel, BDD And You.
Laravel, BDD and You: Let’s Get Started

Indonesian (Bahasa Indonesia) translation by Ari Gustiawan (you can also view the original English article)

Dalam bagian kedua dari seri ini disebut Laravel, BDD dan Anda, kami akan mulai menggambarkan dan membangun fitur kami pertama menggunakan Behat dan PhpSpec. Dalam artikel terakhir kami punya segalanya diatur dan melihat bagaimana dengan mudah kita dapat berinteraksi dengan Laravel dalam skenario Behat.

Baru saja creator Behat, Konstantin Kudryashov (alias everzet), menulis sebuah artikel yang benar-benar hebat disebut Introducing Modelling by Example. Workflow kita akan menggunakan, ketika kita membangun fitur kami, sangat terinspirasi oleh everzet.

Singkatnya, kita akan menggunakan .feature ke design core kita dan user interface. Saya sering merasa bahwa saya memiliki banyak duplikasi di fitur saya dalam acceptance/functional dan integration suites. Ketika saya membaca saran everzet's  tentang cara menggunakan fitur yang sama untuk beberapa konteks, itu semua mengklik bagi saya dan saya percaya itu adalah cara untuk terbaik.

Dalam kasus kami, kita akan memiliki kami functional context, yang, untuk saat ini, juga akan berfungsi sebagai acceptance layer, dan integration context kita, yang akan mencakup domain kita. Kita akan mulai dengan membangun domain dan kemudian tambahkan UI dan hal-hal khusus framework.

Small Refactoring

Untuk menggunakan pendekatan "shared feature, muptiple context", yang harus kita lakukan beberapa refactorings kami setup yang sudah ada.

Pertama, kami akan menghapus fitur welcome  yang kita lakukan di bagian pertama, karena kita tidak benar-benar membutuhkannya dan itu tidak benar-benar mengikuti style generik yang kita butuhkan untuk menggunakan beberapa konteks.

Kedua, kita akan memiliki fitur kami di root folder fitur, sehingga kita dapat pergi ke depan dan menghapus atribut path dari file behat.yml kami. Kami juga akan untuk mengubah nama LaravelFeatureContext FunctionalFeatureContext (ingat untuk mengubah nama kelas juga):

Akhirnya, hanya untuk membersihkan hal-hal sedikit, saya pikir kita harus pindah semua yang berhubungan dengn laravel ke traitnya:

Dalam FunctionalFeatureContext kita kemudian dapat menggunakan trait dan menghapus hal-hal yang baru saja kita pindahkan:

Trait adalah cara yang bagus untuk membersihkan konteks Anda.

Fitur sharing

Seperti yang disajikan pada bagian satu, kita akan membangun sebuah aplikasi kecil untuk time tracking. Fitur pertama akan tentang time tracking dan generate time sheet dari entri yang dilacak. Berikut adalah fitur:

Ingatlah bahwa ini adalah hanya sebuah contoh. Saya merasa lebih mudah untuk menentukan fitur dalam kehidupan nyata, karena Anda memiliki masalah yang sebenarnya Anda butuhkan untuk memecahkan dan sering mendapatkan kesempatan untuk membahas fitur dengan rekan-rekan, klien atau stakeholders lainnya.

Oke, mari kita memiliki Behat menghasilkan langkah-langkah skenario untuk kami:

Kita perlu men-tweak langkah-langkah yang dihasilkan hanya sedikit. Kita hanya perlu empat langkah untuk meng-cover skenario. Hasil akhir akan terlihat seperti ini:

Konteks fungsional kami semua sudah siap, tetapi kita juga perlu konteks untuk integration suite. Pertama, kita akan menambahkan suite ke behat.yml file:

Selanjutnya, kami hanya dapat menyalin default FeatureContext:

Ingat untuk mengubah nama kelas IntegrationFeatureContext dan juga untuk menyalin statement yang digunakan untuk PendingException.

Akhirnya, karena kita berbagi fitur, kita dapat hanya menyalin definisi empat langkah dari functional context. Jika Anda menjalankan Behat, Anda akan melihat bahwa fitur dijalankan dua kali: sekali untuk setiap konteks.

Merancang Domain

Pada point ini, kami siap untuk mulai mengisi langkah tertunda dalam integration context kami untuk desain domain inti dari aplikasi kita. Langkah pertama Given I have the following time entries, diikuti oleh sebuah tabel dengan catatan catatan waktu. Jaga agar tetap sederhana, mari kita hanya loop atas baris tabel, cobalah untuk instantiate sebuah catatan waktu untuk masing-masing, dan menambahkannya ke array entri pada konteks:

Menjalankan Behat akan menyebabkan kesalahan fatal, karena kelas TimeTracker\TimeEntry belum ada. Ini adalah dimana PhpSpec memasuki tahap. Pada akhirnya, TimeEntry akan menjadi Eloquent class, meskipun kita belum khawatir tentang hal itu. PhpSpec dan ORMs seperti Eloquent do tidak bermain bersama-sama baik, tetapi kita masih bisa menggunakan PhpSpec untuk menghasilkan kelas dan bahkan spec keluar beberapa basic behavior. Mari kita gunakan PhpSpec Generator untuk generate TimeEntry class:

Setelah kelas ter-generate, kita perlu memperbarui bagian autoload file composer.json kami:

Dan tentu saja jalankn composer dump-autoload.

Menjalankan PhpSpec memberi kita hijau. Menjalankan Behat memberi kita hijau juga. Apa yang besar untuk memulai!

Membiarkan Behat panduan cara kita, bagaimana kita hanya bergerak tahap berikutnya, When I generate the time sheet, segera?

Kata kunci di sini adalah "generate", yang terlihat seperti sebuah istilah dari domain kita. Dalam dunia programmer, menerjemahkan "generate the timesheet" kode bisa hanya berarti instantiating kelas TimeSheet dengan sekelompok waktu entri. Hal ini penting untuk mencoba dan tetap berpegang pada bahasa dari domain ketika kita merancang kode kita. Dengan cara itu, kode kita akan membantu menjelaskan perilaku dimaksudkan aplikasi kita.

Saya mengidentifikasi istilah generate sebagai penting untuk domain, yang adalah mengapa saya pikir kita harus memiliki statis generate metode kelas TimeSheet yang berfungsi sebagai sebuah alias untuk konstruktor. Metode ini harus mengambil koleksi waktu entri dan menyimpannya pada waktu lembar.

Daripada hanya menggunakan array, saya pikir itu akan masuk akal untuk menggunakan Illuminate\Support\Collection kelas yang datang dengan Laravel. Karena TimeEntry akan menjadi model Eloquent, ketika kita query database untuk entri waktu, kita akan mendapatkan salah satu koleksi Laravel ini pula. Bagaimana tentang sesuatu seperti ini:

By the way, TimeSheet tidak akan menjadi kelas Eloquent. Setidaknya untuk saat ini, kita hanya perlu membuat entri bertahan, dan kemudian waktu lembar akan hanya generate dari entri.

Menjalankan Behat akan, sekali lagi, menyebabkan kesalahan fatal, karena TimeSheet tidak ada. PhpSpec dapat membantu kami memecahkan itu:

Kita masih mendapatkan kesalahan fatal setelah membuat kelas, karena metode statis generate() masih belum ada. Karena ini adalah metode statis yang benar-benar sederhana, saya tidak berpikir ada kebutuhan untuk spesifikasi. Hal ini tidak lebih daripada sebuah bungkus untuk konstruktor:

Ini akan mendapatkan Behat kembali ke green, tetapi PhpSpec sekarang mendecit pada kami, berkata: Argument 1 passed to TimeTracker\TimeSheet::__construct() must be an instance of Illuminate\Support\Collection, none given. Kita dapat memecahkan masalah ini dengan menulis fungsi sederhana let() yang akan dipanggil sebelum setiap spesifikasi:

Ini akan mendapatkan kita kembali ke green seluruh baris. Fungsi memastikan bahwa lembar waktu selalu dibangun dengan mock kelas koleksi.

Kami dengan aman sekarang dapat pindah ke Then my total time spent on... langkah. Kami memerlukan metode yang mengambil nama tugas dan kembali durasi akumulasi semua entri dengan nama tugas ini. Langsung diterjemahkan dari gherkin ke kode, ini bisa menjadi sesuatu seperti totalTimeSpentOn($task):

Metode tidak ada, jadi menjalankan Behat akan memberikan Call to undefined method TimeTracker\TimeSheet::totalTimeSpentOn()

Untuk spesifikasi keluar metode, kita akan menulis spesifikasi yang entah bagaimana terlihat mirip dengan apa yang sudah kita miliki dalam skenario kami:

Perhatikan bahwa kami tidak menggunakanmocksuntuk contoh-contoh TimeEntry dan Collection. Ini adalah integration suite kami dan saya tidak berpikir ada kebutuhan untuk mock hal ini. Objek cukup sederhana dan kami ingin untuk memastikan bahwa objek di domain kita berinteraksi sebagai kita berharap mereka. Ada mungkin banyak pendapat tentang hal ini, tetapi ini masuk akal bagi saya.

Moving along:

Untuk menyaring entri, kita dapat menggunakan metode filter() pada kelas Collection. Solusi sederhana yang membuat kita menjadi hijau:

Spesifikasi kami hijau, tapi aku merasa bahwa kami dapat memperoleh manfaat dari beberapa refactoring di sini. Metode tampaknya untuk melakukan dua hal yang berbeda: menyaring entri dan mengumpulkan durasi. Mari kita ekstrak yang kedua metode sendiri:

PhpSpec masih hijau dan kami sekarang memiliki tiga langkah hijau di Behat. Langkah terakhir harus mudah untuk melaksanakan, karena hal ini agak mirip dengan yang kita hanya melakukan.

Menjalankan Behat akan memberi Call to undefined method TimeTracker\TimeSheet::totalTimeSpent(). Daripada melakukan sebuah contoh yang terpisah kami spec untuk metode ini, bagaimana kita hanya menambahkannya ke yang kita sudah memiliki? Itu mungkin tidak akan benar-benar sesuai dengan apa "benar" untuk melakukan, tetapi marilah kita menjadi sedikit pragmatis:

Biarkan PhpSpec generate metode:

Mendapatkan hijau mudah sekarang bahwa kita memiliki sumDuration() metode:

Dan sekarang kami memiliki fitur hijau. Domain kita perlahan-lahan berkembang!

Merancang User Interface

Sekarang, kita sedang bergerak ke functional suite. Kita akan desain user interface dan menangani semua Laravel-stuff khusus yang tidak diperlukan domain kita.

Saat bekerja di functional suite, kita dapat menambahkan flag -s memerintahkan Behat untuk hanya menjalankan fitur kami melalui FunctionalFeatureContext:

Langkah pertama akan terlihat mirip dengan yang pertama dari integration context. Daripada hanya membuat entri bertahan pada konteks dalam array, kita perlu untuk benar-benar membuat mereka bertahan dalam database sehingga mereka dapat diambil kemudian:

Menjalankan Behat akan memberi kita kesalahan Call to undefined method TimeTracker\TimeEntry::save(),  karena TimeEntry masih bukan model Eloquent. Ini mudah untuk memperbaiki:

Jika kita menjalankan Behat lagi, Laravel akan mengeluh bahwa ia tidak dapat terhubung ke database. Kita bisa memperbaiki ini dengan menambahkan database.php file ke direktori app/config/testing, untuk menambahkan rincian koneksi database. Untuk proyek yang lebih besar, Anda mungkin ingin menggunakan server database yang sama untuk tes dan basis kode produksi Anda, tetapi dalam kasus kami, kami hanya akan menggunakan memori di SQLite database. Ini super sederhana untuk mengatur dengan Laravel:

Sekarang jika kita menjalankan Behat, itu akan memberitahu kita bahwa ada tidak ada tabmle time_entries. Untuk memperbaiki ini, kita perlu membuat migation:

Kami masih tidak hijau, karena kita perlu cara untuk mengajar Behat untuk menjalankan migration sebelum setiap skenario, jadi kita memiliki bersih setiap saat. Dengan menggunakan Behat's anotasi, kita dapat menambahkan dua metode ini untuk trait LaravelTrait:

Ini cukup rapi dan mendapat langkah pertama kami menjadi hijau.

Berikutnya adalah langkah When I generate the time sheet. Cara saya melihatnya, generate lembar waktu adalah setara dengan mengunjungi index action dari time entry resource, karena time sheet adalah kumpulan dari semua entri waktu. Jadi objek time sheet adalah seperti sebuah wadah untuk semua entri waktu dan memberi kita cara yang baik untuk menangani entri. Bukannya pergi ke /time-entries, untuk melihat time sheet , saya pikir karyawan harus pergi ke /time-sheet. Kita harus meletakkan bahwa dalam definisi langkah kita:

Ini akan menyebabkan NotFoundHttpException, karena rute tidak didefinisikan. Aku hanya dijelaskan, saya pikir URL ini harus map index action pada time entry resource:

Untuk mendapatkan hijau, kita perlu menghasilkan controller:

Dan ada kita pergi.

Akhirnya, kita perlu untuk menjelajah halaman untuk menemukan total durasi waktu entri. Saya rasa kita akan memiliki semacam tabel yang merangkum durasi. Terakhir dua langkah sangat mirip bahwa kita hanya akan menerapkan mereka pada saat yang sama:

Crawler mencari<td>node dengan id dari [task_name] TotalDuration atau totalDuration dalam contoh terakhir.

Karena kita masih tidak memiliki view, crawler akan memberitahu kita The current node list is empty.

Untuk memperbaiki ini, mari kita membangun index action. Pertama, kita mengambil koleksi time sheet. Kedua, kami menghasilkan time sheet dari entri dan mengirimkannya  ke tampilan (masih tidak ada).

Tampilan, untuk saat ini, hanya akan terdiri dari sebuah tabel sederhana dengan nilai durasi diringkas:

Jika Anda menjalankan Behat lagi, Anda akan melihat bahwa kita berhasil menerapkan fitur. Mungkin kita harus mengambil waktu untuk menyadari bahwa bahkan tidak sekali Apakah kita membuka browser! Ini adalah perbaikan besar-besaran untuk alur kerja kami, dan sebagai bonus bagus, kita sekarang memiliki otomatis tes untuk aplikasi kita. YAY!

Kesimpulan

Jika Anda menjalankan vendor/bin/behat untuk menjalankan kedua Behat suites, Anda akan melihat bahwa keduanya hijau sekarang. Jika Anda menjalankan PhpSpec meskipun, sayangnya, Anda akan melihat bahwa spesifikasi kami rusak. Kita mendapatkan kesalahan Class 'Eloquent' not found in .... Hal ini karena Eloquent adalah alias. Jika Anda melihat di app/config/app.php di bawah alias, Anda akan melihat bahwa Eloquent adalah benar-benar sebuah alias untuk Illuminate\Database\Eloquent\Model. Untuk mendapatkan PhpSpec kembali ke green, kita perlu mengimpor kelas ini:

Jika Anda menjalankan 2 perintah ini:

Anda akan melihat bahwa kita adalah kembali ke green, baik dengan Behat dan PhpSpec. YAY!

Kami sekarang memiliki dijelaskan dan dirancang fitur pertama kami, benar-benar menggunakan pendekatan BDD. Kita telah melihat bagaimana kita dapat manfaat dari merancang domain inti aplikasi kami, sebelum kita khawatir tentang UI dan hal-hal tertentu framework. Kita juga telah melihat betapa mudahnya untuk berinteraksi dengan Laravel, dan terutama database, dalam konteks Behat kami.

Dalam artikel berikutnya, kami akan melakukan banyak refactoring untuk menghindari terlalu banyak logika pada model Eloquent, karena ini lebih sulit untuk menguji dalam isolasi dan erat digabungkan ke Laravel. Stay tuned!

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.