Unlimited Plugins, WordPress themes, videos & courses! Unlimited asset downloads! From $16.50/m
Advertisement
  1. Code
  2. PHP

Testing Like a Boss di Larvel: Model

by
Difficulty:AdvancedLength:LongLanguages:

Indonesian (Bahasa Indonesia) translation by Dika Budiaji (you can also view the original English article)

Jika Anda berharap untuk mempelajari mengapa tes bermanfaat, ini bukanlah artikel untuk Anda. Selama tutorial ini, saya akan berasumsi bahwa Anda sudah memahami keuntungan, dan berharap untuk belajar cara terbaik untuk menulis dan mengatur tes Anda dalam Laravel 4.

Versi 4 Laravel menawarkan perbaikan serius dalam kaitannya dengan testing, bila dibandingkan dengan rilis sebelumnya. Ini adalah artikel pertama dari seri yang akan mencakup bagaimana untuk menulis tes untuk aplikasi Laravel 4. Kami akan mulai seri dengan membahas model testing.


Setup

In-memory database

Kecuali Anda menjalankan raw query pada database Anda, Laravel memungkinkan aplikasi Anda untuk tetap agnostik database. Dengan perubahan sederhana driver, aplikasi Anda sekarang dapat bekerja dengan DBMS yang lain (MySQL, PostgreSQL, SQLite, dll). Di antara pilihan default, SQLite menawarkan fitur yang aneh, namun sangat berguna: database di memori.

Dengan Sqlite, kita dapat mengatur koneksi database: memori:, yang secara drastis akan mempercepat tes kami, karena database tidak ada pada hard disk. Selain itu, produksi pengembangan database akan pernah diisi dengan data uji kiri-atas, karena sambungan,: memori:, selalu dimulai dengan database kosong.

Singkatnya: in-memory database memungkinkan untuk tes cepat dan bersih.

Dalam direktori app/config/testing, membuat file baru, bernama database.php, dan mengisinya dengan konten berikut:

Fakta bahwa database.php ditempatkan dalam konfigurasi testing direktori berarti bahwa pengaturan ini hanya akan digunakan ketika di lingkungan testing (yang Laravel secara otomatis mengatur). Dengan demikian, ketika aplikasi yang diakses biasanya, database di memori tidak akan digunakan.

Sebelum menjalankan tes

Karena  in-memory database selalu kosong saat sambungan dibuat, sangat penting untuk bermigrasi database sebelum setiap tes. Untuk melakukannya, buka app/tests/TestCase.php dan menambahkan metode berikut ke akhir kelas:

Catatan: Metode setUp() yang dijalankan oleh PHPUnit sebelum setiap tes.

Metode ini akan menyiapkan database, dan mengubah status Laravel's Mailer kelas untuk berpura-pura. Dengan cara ini, Mailer tidak akan mengirim email nyata ketika menjalankan tes. Sebaliknya, itu akan log "Kirim".

Untuk menyelesaikan app/tests/TestCase.php, panggilan prepareForTests() dalam PHPUnit setUp() metode, yang akan mengeksekusi sebelum setiap tes.

Jangan lupa parent::setUp(), seperti kita sedang menimpa metode parent class.

Pada titik ini, app/tests/TestCase.php akan tampak seperti kode berikut. Ingat bahwa createApplication dibuat secara otomatis oleh Laravel. Anda tidak perlu khawatir tentang hal itu.

Sekarang, untuk menulis kami tes, hanya extend TestCase, dan database akan diinisialisasi dan bermigrasi sebelum setiap tes.


Tes

Memang benar untuk mengatakan bahwa, dalam artikel ini, kami tidak akan mengikuti proses TDD. Masalahnya di sini didaktik, dengan tujuan untuk menunjukkan bagaimana tes dapat ditulis. Karena ini, saya memilih untuk mengungkapkan model dalam pertanyaan pertama, dan kemudian mereka tes yang terkait. Saya percaya bahwa ini adalah cara yang lebih baik untuk menggambarkan tutorial ini.

Konteks dari aplikasi demo ini adalah sebuah blog/CMS sederhana, yang mengandung pengguna (otentikasi), posting dan halaman statis (yang ditampilkan dalam menu).

Post model

Harap dicatat bahwa model extend kelas, Ardent, daripada Eloquent. Ardent adalah paket yang membuat untuk validasi mudah, saat menyimpan model (Lihat properti $rules).

Selanjutnya, kami memiliki array public statis $factory, yang memanfaatkan paket FactoryMuff, untuk membantu dengan pembuatan obyek ketika testing.

Ardentx dan FactoryMuff juga tersedia melalui Packagist dan composer.

Dalam model Post kami, kami memiliki relationship dengan model User, melalui metode author magic.

Akhirnya, kami memiliki sebuah metode sederhana yang mengembalikan tanggal, diformat sebagai "hari/bulan/tahun".

Post test

Untuk menjaga hal-hal yang terorganisir, saya sudah ditempatkan kelas dengan tes model Post di app/tests/models/PostTest.php. Kita melalui semua tes, satu bagian pada suatu waktu.

Kami extend beberapa TestCase kelas, yang merupakan persyaratan untuk PHPUnit di Laravel. Juga, jangan lupa kami metode prepareTests yang akan berjalan sebelum setiap tes.

Tes ini adalah salah satu yang "opsional". Kami menguji bahwa hubungan "Post dimilik oleh User". Tujuan di sini adalah sebagian besar untuk menunjukkan fungsi FactoryMuff.

Setelah kelas Post memiliki $factory statis array yang berisi 'author_id' => ' factory | User ' (Perhatikan kode sumber dari model, ditampilkan di atas) FactoryMuff instantiate mengisi User baru atributnya, menyimpan dalam database dan akhirnya kembali dengan id untuk atribut author_id dalam Post.

Untuk ini menjadi mungkin, User model harus memiliki array $factory yang menggambarkan kolom.

Perhatikan bagaimana Anda dapat mengakses relasi User melalui $post->author. Sebagai contoh, kita dapat mengakses $post->author->username, atau atribut pengguna apapun lainnya yang sudah ada.

Package FactoryMuff memungkinkan cepat Instansiasi object-object yang konsisten untuk tujuan testubg, tetap menghargai dan instantiating hubungan yang diperlukan. Dalam kasus ini, ketika kita membuat Post dengan FactoryMuff::create('Post') User akan juga disiapkan dan dibuat tersedia.

Untuk menyelesaikan, kita menentukan jika string kembali dengan metode postedAt() mengikuti format "hari/bulan/tahun". Untuk verifikasi seperti itu, kalimat biasa digunakan untuk menguji jika pola \d{2}\/\d{2}\/\d{4} ("2 nomor" + "bar" + "2 nomor" + "bar" + "4 angka") ditemukan.

Selain itu, kita bisa menggunakan PHPUnit's assertRegExp matcher.

Pada titik ini, app/tests/models/PostTest.php file adalah sebagai berikut:

PS: saya memilih untuk tidak menulis nama tes di CamelCase untuk tujuan terbaca. PSR-1 Maafkan aku, tapi testRelationWithAuthor tidak dapat dibaca sebagai saya pribadi lebih suka. Anda bebas untuk menggunakan gaya yang Anda paling inginkan, tentu saja.

Page model

CMS kita membutuhkan model untuk mewakili halaman statis. Model ini implementasi sebagai berikut:

Kita dapat amati bahwa metode statis, renderMenu(), menjadikan jumlah link semua halaman yang sudah ada. Nilai ini disimpan dalam cache kunci, 'pages_for_menu'. Dengan cara ini, nanti kita panggal ke renderMenu(), akan ada tidak perlu hit database asli. Ini dapat memberikan peningkatan yang signifikan untuk kinerja aplikasi kami.

Namun, jika Page yang disimpan atau dihapus (metode afterSave() dan delete()), nilai cache akan dihapus, menyebabkan renderMenu() untuk mencerminkan keadaan baru database. Jadi, jika nama halaman  berubah, atau jika akan dihapus, key 'pages_for_menu' dihapus dari cache. (Cache::forget('pages_for_menu');)

Catatan: Metode, afterSave(), tersedia melalui Ardent package. Jika tidak, maka akan diperlukan untuk menerapkan method save() untuk membersihkan cache dan memanggil parent::save();

Page Test

Di: app/tests/models/PageTest.php, kita akan menulis testing berikut:

Sekali lagi, kami memiliki tes "opsional" untuk mengkonfirmasi relasi. Karena hubungan tanggung jawab Illuminate\Database\Eloquent, yang telah ditutupi oleh Laravel sendiri tes, kita tidak perlu untuk menulis tes lain untuk mengkonfirmasi bahwa kode ini bekerja seperti yang diharapkan.

Ini adalah salah satu paling penting tes untuk model Page. Pertama, empat halaman dibuat dalam for loop. Setelah itu, hasil dari panggilan renderMenu() disimpan dalam variabel $result. Variabel ini harus berisi string HTML, yang berisi link ke halaman yang sudah ada.

Foreach loop memeriksa apakah slug (url) setiap halaman di $result. Ini adalah cukup, karena format yang sama persis dari HTML tidak relevan dengan kebutuhan kita.

Akhirnya, kita menentukan apakah cache kunci, pages_for_menu, memiliki sesuatu yang disimpan. Dengan kata lain, renderMenu() panggilan benar-benar disimpan beberapa nilai ke cache?

Tes ini bertujuan untuk memverifikasi jika, saat menyimpan Page baru, tombol cache 'pages_for_menu' dikosongkan. FactoryMuff::create('Page'); akhirnya memicu save() method, sehingga yang harus cukup untuk kunci, 'pages_for_menu', harus dibersihkan.

Mirip dengan tes sebelumnya, yang satu ini menentukan jika tombol 'pages_for_menu' dikosongkan benar setelah menghapus Page.

PageTest.php Anda akan terlihat seperti:

User model

Terkait dengan model sebelumnya, kami sekarang memiliki User. Berikut adalah kode untuk model:

Model ini tidak ada tes.

Kita dapat mengamati bahwa, dengan pengecualian dari relasi (yang dapat membantu untuk menguji), tidak ada setiap metode pelaksanaan di sini. Gimana tentang otentikasi? Yah, penggunaan package Confide sudah menyediakan implementasi dan tes untuk ini.

Test untuk Zizaco\Confide\ConfideUser terletak di ConfideUserTest.php.

Hal ini penting untuk menentukan tanggung jawab kelas sebelum menulis tes Anda. Pengujian pilihan untuk "reset password" User akan redundant. Hal ini karena tanggung-jawab yang tepat untuk tes ini dalam Zizaco\Confide\ConfideUser. bukan di User

Hal yang sama juga berlaku untuk tes validasi data. Sebagai paket, Ardent, menangani tanggung jawab ini, itu tidak akan membuat banyak akal untuk menguji fungsionalitas lagi.

Singkatnya: menjaga tes Anda bersih dan terorganisir. Menentukan tanggung-jawab yang tepat dari setiap kelas, dan menguji hanya apa adalah benar-benar tanggung jawabnya.


Kesimpulan

Running Tests

Menggunakanin-memory database adalah praktik yang baik untuk melaksanakan tes terhadap database dengan cepat. Berkat bantuan dari beberapa package, seperti Ardent, FactoryMuff dan Confide, Anda dapat meminimalkan jumlah kode pada model Anda, sementara menjaga tes bersih dan objektif.

Dalam sekuel untuk artikel ini, kami akan meninjau Controller pengujian. Menantikan!

Mari kita masih memulai dengan Laravel 4, mengajarkan Anda penting!

Advertisement
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.