Mulai Pengujian PHP Anda dengan Codeception

Diterbitkan: 2022-03-11

Sebelum beralih ke Codeception dan PHP, kita harus membahas dasar-dasarnya dan mulai dengan menjelaskan mengapa kita membutuhkan pengujian dalam aplikasi sejak awal. Mungkin kita bisa menyelesaikan sebuah proyek tanpa membuang waktu untuk tes, setidaknya kali ini?

Tentu, Anda tidak perlu tes untuk semuanya; misalnya, ketika Anda ingin membuat beranda lain. Anda mungkin tidak memerlukan pengujian saat proyek Anda berisi halaman statis yang ditautkan oleh satu router.

Namun, Anda pasti membutuhkan pengujian ketika:

  • Tim Anda menggunakan BDD/TDD.
  • Repo Git Anda berisi lebih dari beberapa komit.
  • Anda adalah seorang profesional yang tepat, mengerjakan proyek yang serius.

Anda dapat memaafkan diri sendiri dengan mengatakan bahwa Anda sudah memiliki departemen pengujian khusus, sekelompok orang yang melakukan tes dan menulis yang baru bila diperlukan. Namun, dapatkah Anda bayangkan berapa lama perbaikan bug akan berlangsung setelah Anda menambahkan fungsionalitas baru ke proyek Anda?

Apa yang Dipecahkan oleh Pengujian?

Pertama, mari kita putuskan masalah seperti apa yang dapat diselesaikan melalui pengujian. Anda tidak dapat menghilangkan semua kesalahan dengan pengujian, tetapi Anda dapat menjelaskan perilaku yang diharapkan dalam kasus pengujian. Kesalahan mungkin ada di dalam kasus pengujian Anda. Kode spageti tetap kode spageti bahkan saat Anda menggunakan kasus uji.

Namun, Anda dapat yakin bahwa kode Anda akan diubah sesudahnya (dengan memperbaiki kesalahan, atau menambahkan fitur baru), sehingga kode Anda tetap bebas dari kesalahan yang dijelaskan dalam pengujian. Selain itu, bahkan tes yang ditulis dengan baik terkadang dapat digunakan dalam dokumentasi karena di sana Anda dapat melihat bagaimana skenario umum terungkap dan memeriksa perilaku yang diharapkan. Kita dapat mengatakan bahwa pengujian adalah investasi kecil tapi penting di masa depan.

Jadi tes seperti apa yang bisa kita terapkan?

Tes unit dasar biasanya tidak cukup. Mereka perlu didukung oleh pengujian integrasi, fungsional, dan penerimaan.

Tes unit dasar biasanya tidak cukup. Mereka perlu didukung oleh pengujian integrasi, fungsional, dan penerimaan.
Menciak
  • Tes unit: Tes tingkat rendah yang memeriksa potongan kecil kode Anda - metode kelas Anda diisolasi dari kode lain.
  • Pengujian integrasi: Pengujian integrasi memeriksa bagian dari aplikasi Anda, mungkin berisi beberapa kelas atau metode, tetapi harus dibatasi pada satu fitur. Tes ini juga harus memeriksa bagaimana kelas yang berbeda berinteraksi.
  • Pengujian fungsional: Menguji permintaan khusus untuk aplikasi Anda: respons browser, perubahan basis data, dan sebagainya.
  • Pengujian penerimaan: Dalam kebanyakan kasus, pengujian penerimaan berarti memeriksa apakah aplikasi memenuhi semua persyaratan klien.

Untuk memperjelas, katakanlah kita mengilustrasikan proses dengan sesuatu yang nyata, seperti sebuah bangunan. Sebuah bangunan terdiri dari balok-balok kecil yang membentuk dinding. Setiap bata harus memenuhi persyaratan yang ditentukan; itu harus menahan beban yang diperlukan, memiliki volume dan bentuk tertentu, dan sebagainya. Ini adalah tes unit. Ide dari tes integrasi adalah untuk memeriksa seberapa erat dan akurat bata menempel satu sama lain, bagaimana mereka diintegrasikan ke dalam elemen bangunan tertentu. Pengujian fungsional dapat disamakan dengan pengujian pada satu dinding bangunan, untuk memeriksa apakah bagian dalam terlindung dari elemen atau tidak, dan memungkinkan untuk melihat matahari melalui jendela atau tidak. Pengujian penerimaan melibatkan pengujian seluruh bangunan sebagai produk lengkap: Buka pintu, masuk ke dalam, tutup pintu, nyalakan lampu, naik ke lantai dua dan lihat taman di luar gedung.

Temui Codeception

Namun, pembagian ini bersyarat dan terkadang sulit untuk menahan godaan untuk mencampur berbagai jenis tes.

Banyak pengembang menggunakan tes unit dan mengklaim itu sudah cukup. Saya pernah menjadi salah satu pengembang tersebut; Saya menemukan menggunakan sistem yang berbeda untuk berbagai jenis tes terlalu sulit dan memakan waktu. Beberapa waktu yang lalu, saya memutuskan untuk menemukan sesuatu yang lebih berguna daripada PHPUnit; Saya ingin menjadi lebih baik dalam menguji kode saya, tetapi saya tidak ingin membaca dan mempelajari banyak dokumentasi dan mencari jebakan. Begitulah cara saya menemukan Codeception. Awalnya, saya skeptis, seperti yang sering terjadi pada sesuatu yang baru (proyek ini berusia lima tahun, jadi secara teknis, ini tidak dapat dianggap "baru"), tetapi setelah bermain-main dengannya selama beberapa hari , saya menyimpulkan Codeception adalah sistem yang sangat berguna dan kuat.

Jadi bagaimana Anda menginstal Codeception? Ini sesederhana yang didapat:

 $ composer require "codeception/codeception" $ php vendor/bin/codecept bootstrap

Setelah menginstal, Anda akan menemukan folder baru bernama tes di proyek Anda, dan akan ada beberapa subfolder bernama acceptance, functional dan unit . Sepertinya kita bisa mulai menulis tes kita. Keren, tapi apa selanjutnya?

Sekarang, coba tambahkan standar penerimaan tes Hello World.

 $ php vendor/bin/codecept generate:cept acceptance HelloWorld

Sekarang, kita mendapatkan file tes penerimaan tes/penerimaan/HelloWorldCept.php, dengan konten berikut:

 <?php $I = new AcceptanceTester($scenario); $I->wantTo('perform actions and see result');

Variabel default, bernama $I , bukan hanya sebuah huruf; itu adalah karakter. Apa yang melakukan tes? Penguji, jelas. Penguji ini membuka halaman atau kelas situs web Anda, melakukan sesuatu dengannya, dan menunjukkan kepada Anda hasil akhir dari tindakannya. Anda akan melihat apa yang berhasil dan apa yang salah. Itulah mengapa objek ini diberi nama $I dan mengapa objek ini berisi metode yang disebut wantTo() , see() atau amOnPage() .

Jadi, mari kita berpikir seperti seorang penguji tentang cara memeriksa operabilitas halaman. Pendekatan pertama adalah membuka halaman dan mencari frase. Ini membuktikan bahwa halaman tersebut tersedia untuk pengunjung.

Ini seharusnya mudah:

 <?php $I->amOnPage('/'); $I->see('Welcome');

Kita dapat menggunakan perintah ini untuk menjalankan tes Codeception:

 $ php vendor/bin/codecept run

Kami segera melihat bahwa ada sesuatu yang salah. Sepintas, pesannya terlihat terlalu panjang dan tidak jelas, tetapi ketika kita melihat lebih dekat, semuanya menjadi jelas.

Ups! Ada yang salah. Itulah inti dari pengujian. Lihat pesannya, identifikasi kesalahannya, dan pelajari kesalahan Anda.

Ups! Ada yang salah. Itulah inti dari pengujian. Lihat pesannya, identifikasi kesalahannya, dan pelajari kesalahan Anda.
Menciak

Kami memiliki satu tes, Acceptance , dan mendeteksi kesalahan:

 Acceptance Tests (1) Perform actions and see result (HelloWorldCept) Error ---------- 1) Failed to perform actions and see result in HelloWorldCept (tests/acceptance/HelloWorldCept .php) [GuzzleHttp\Exception\ConnectException] cURL error 6: Could not resolve host: localhost (see http://curl.haxx.se/libcurl/c/libcurl-errors.html)

Ini penyebabnya: localhost tidak tersedia.

Dan berikut adalah langkah-langkah skenario pengujian kami:

 1. $I->amOnPage("/")

Oke, mari kita buka tes/acceptance.suite.yml dan ubah url: http://localhost/ menjadi sesuatu yang benar-benar tersedia. Dalam kasus saya, ini adalah Host pengujian lokal saya, url: https://local.codeception-article.com/

Jalankan tes lagi dan inilah yang seharusnya Anda dapatkan:

 Acceptance Tests (1) --------------------------------------------------------------------------------------- Perform actions and result (HelloWorldCept) Ok

Hore! Tes pertama kami yang berhasil!

Tentu saja, amOnPage() bukan satu-satunya metode pengujian yang tersedia, kami hanya memilihnya sebagai contoh. Semua metode pengujian Codeception dapat dibagi menjadi beberapa kelompok berikut:

  • Interaksi dengan halaman: fillField() , selectOption( selectOption() , submitForm() , click()
  • Pernyataan. see() , dontSee() , seeElement() , seeInCurrentUrl() , seeCheckboxIsChecked() , seeInField() , seeLink() . Untuk semua metode ini, Anda dapat menambahkan sufiks dan menggunakannya saat Anda membutuhkan metode yang tidak akan mengganggu skenario pengujian ketika sesuatu tidak dapat ditemukan.
  • Metode cookie: setCookie() , grabCookie() , seeCookie()
  • Komentar dan deskripsi skenario pengujian: amGoingTo() , wantTo() , expect() . Gunakan metode ini untuk mendapatkan komentar dan deskripsi tes yang baik, yang akan membantu Anda mengingat tujuan tes.

Jadi, jika kami ingin menguji halaman email pengaturan ulang kata sandi, kami dapat melakukannya dengan cara ini:

 <?php $I = new AcceptanceTester($scenario); $I->wantTo('Test forgotten password functionality'); $I->amOnPage('/forgotten') $I->see('Enter email'); $I->fillField('email', '[email protected]'); $I->click('Continue'); $I->expect('Reset password link not sent for incorrect email'); $I->see('Email is incorrect, try again'); $I->amGoingTo('Fill correct email and get link'); $I->see('Enter email'); $I->fillField('email', '[email protected]'); $I->click('Continue'); $I->expect('Reset password link sent for correct email'); $I->see('Please check your email for next instructions');

Sepertinya ini harus dilakukan, tetapi bagaimana jika ada beberapa bagian yang dimuat Ajax di halaman? Bisakah kita menguji halaman seperti itu? Jawabannya adalah Codeception menggunakan PhpBrowser, berdasarkan Symfony BrowserKit dan Guzzle, secara default. Ini sederhana, cepat dan Anda hanya perlu curl untuk menggunakannya.

Anda juga dapat menggunakan Selenium dan menguji halaman dengan browser asli. Ya, ini akan lebih lambat, tetapi Anda juga dapat menguji JavaScript.

Pertama, Anda perlu menginstal driver Selenium, mengubah acceptance.suite.yml dan membangun kembali kelas AcceptanceTester. Setelah ini, Anda dapat menggunakan metode wait() dan waitForElement() . Dan, yang lebih menarik, Anda akan dapat menghemat waktu dan sumber daya dengan menggunakan metode saveSessionSnapshot() dan loadSessionSnapshot() . Metode ini memungkinkan Anda untuk menyimpan status sesi dan memulai pengujian baru di sesi sebelumnya. Ini berguna dalam beberapa situasi, misalnya, dalam proses otorisasi pengujian.

Jadi, kita berakhir dengan kemampuan yang sederhana, namun kuat, untuk menguji banyak fungsi.

Pengujian Fungsional

Oke, saatnya beralih ke pengujian fungsional.

 $ php vendor/bin/codecept generate:cept functional HelloWorld

Dan inilah yang kami dapatkan:

 <?php $I = new FunctionalTester($scenario); $I->amOnPage('/'); $I->see('Welcome');

Tunggu apa?

Tidak, itu bukan kesalahan. Tes fungsional harus ditulis dengan cara yang sama seperti tes integrasi. Perbedaannya adalah bahwa tes fungsional berinteraksi langsung dengan aplikasi Anda. Itu berarti Anda tidak memerlukan server web untuk menjalankan pengujian fungsional, dan Anda memiliki lebih banyak kapasitas untuk menguji berbagai bagian aplikasi Anda.

Ini berarti bahwa dukungan untuk semua kerangka kerja kurang, tetapi daftar kerangka kerja yang didukung sangat luas: Symfony, Silex, Phalcon, Yii, Zend Framework, Lumen, Laravel. Ini harus cukup untuk sebagian besar kasus dan sebagian besar pengembang. Silakan lihat dokumentasi modul Codeception untuk mendapatkan daftar fungsi yang tersedia dan kemudian aktifkan di functional.suite.yml .

Codeception mendukung kerangka kerja utama: Symfony, Silex, Phalcon, Yii, Zend Framework, Lumen, Laravel.

Codeception mendukung kerangka kerja utama: Symfony, Silex, Phalcon, Yii, Zend Framework, Lumen, Laravel.
Menciak

Sebelum kita melanjutkan ke pengujian unit, izinkan saya membuat penyimpangan kecil. Seperti yang mungkin Anda perhatikan, kami membuat pengujian kami dengan key cept:

 $ php vendor/bin/codecept generate: cept acceptance HelloWorld

Ini bukan satu-satunya cara untuk membuat tes. Ada juga tes cest . Perbedaannya adalah Anda dapat menyusun beberapa skenario terkait dalam satu kelas:

 $ php vendor/bin/codecept generate:cest acceptance HelloWorld <?php class HelloWorldCest { public function _before(AcceptanceTester $I) { $I->amOnPage('/forgotten') } public function _after(AcceptanceTester $I) { } // tests public function testEmailField(AcceptanceTester $I) { $I->see('Enter email'); } public function testIncorrectEmail(AcceptanceTester $I) { $I->fillField('email', '[email protected]'); $I->click('Continue'); $I->see('Email is incorrect, try again'); } public function testCorrectEmail(AcceptanceTester $I) { $I->fillField('email', '[email protected]'); $I->click('Continue'); $I->see('Please check your email for next instructions'); } }

Dalam contoh ini, metode _before() dan _after() dijalankan sebelum dan sesudah setiap pengujian. Instance kelas AcceptanceTester diteruskan ke setiap pengujian, sehingga Anda dapat menggunakannya dengan cara yang sama seperti dalam pengujian cest. Gaya tes ini dapat berguna dalam situasi tertentu, jadi perlu diingat.

Pengujian Unit

Waktu untuk beberapa pengujian unit.

Codeception didasarkan pada PHPUnit, sehingga Anda dapat menggunakan tes yang ditulis untuk PHPUnit. Untuk menambahkan tes PHPUnit baru, gunakan pendekatan berikut:

 $ php vendor/bin/codecept generate:phpunit unit HelloWorld

Atau cukup mewarisi pengujian Anda di \PHPUnit_Framework_TestCase .

Tetapi jika Anda menginginkan sesuatu yang lebih, Anda harus mencoba unit test Codeception:

 $ php vendor/bin/codecept generate:test unit HelloWorld <?php class HelloWorldTest extends \Codeception\TestCase\Test { /** * @var \UnitTester */ protected $tester; protected function _before() { } protected function _after() { } // tests public function testUserSave() { $user = User::find(1); $user->setEmail('[email protected]'); $user->save(); $user = User::find(1); $this->assertEquals('[email protected]', $user->getEmail()); } }

Tidak ada yang luar biasa untuk saat ini. Metode _before() dan _after() adalah analog setUp() () dan tearDown( tearDown() dan akan berjalan sebelum dan sesudah setiap pengujian.

Keuntungan utama dari tes ini adalah kemampuannya untuk memperluas proses pengujian Anda dengan memasukkan modul yang dapat diaktifkan di unit.suite.yml :

  • Akses ke memcache dan database untuk melacak perubahan (MySQL, SQLite, PostgreSQL, MongoDB didukung)
  • Pengujian aplikasi REST/SOAP
  • antrian

Setiap modul memiliki fiturnya sendiri, jadi yang terbaik adalah memeriksa dokumentasi dan mengumpulkan informasi yang diperlukan untuk setiap modul sebelum melanjutkan ke pengujian yang sebenarnya.

Plus, Anda dapat menggunakan paket Codeception/Specify (yang perlu ditambahkan ke composer.json ) dan menulis deskripsi seperti ini:

 <?php class HelloWorldTest extends \Codeception\TestCase\Test { use \Codeception\Specify; private $user; protected function _before() { $this->user = User::find(1); } public function testUserEmailSave() { $this->specify("email can be stored", function() { $this->user->setEmail('[email protected]'); $this->user->save(); $user = User::find(1); $this->assertEquals('[email protected]', $user->getEmail()); }); } }

Kode PHP di dalam fungsi penutupan ini diisolasi, jadi perubahan di dalamnya tidak akan memengaruhi sisa kode Anda. Deskripsi akan membantu Anda membuat pengujian lebih mudah dibaca dan mempermudah mengidentifikasi pengujian yang gagal.

Sebagai tambahan opsional, Anda dapat menggunakan paket Codeception\Verify untuk sintaks seperti BDD:

 <?php public function testUserEmailSave() { verify($map->getEmail())->equals('[email protected]'); }

Dan tentu saja Anda dapat menggunakan rintisan:

 <?php public function testUserEmailSave() { $user = Stub::make('User', ['getEmail' => '[email protected]']); $this->assertEquals('[email protected]', $user->getEmail()); }

Putusan: Codeception Menghemat Waktu dan Usaha

Jadi apa yang Anda harapkan dari Codeception? Untuk siapa? Apakah ada peringatan?

Codeception dapat digunakan oleh pengembang dengan tingkat kemahiran PHP yang sangat berbeda dan tim dari semua ukuran.

Codeception dapat digunakan oleh pengembang dengan tingkat kemahiran PHP yang sangat berbeda dan tim dari semua ukuran.
Menciak

Menurut pendapat saya, kerangka pengujian ini cocok untuk semua jenis tim yang berbeda: besar dan kecil, pemula dan profesional PHP yang tangguh, mereka yang menggunakan kerangka kerja populer, dan mereka yang tidak menggunakan kerangka kerja apa pun.

Bagaimanapun, semuanya bermuara pada ini: Codeception siap untuk prime time.

Ini adalah kerangka kerja yang matang dan terdokumentasi dengan baik yang dapat dengan mudah diperluas oleh banyak modul. Codeception modern, tetapi berdasarkan PHPUnit yang telah teruji waktu, yang seharusnya meyakinkan pengembang yang tidak ingin bereksperimen terlalu banyak.

Ini berkinerja baik, yang berarti cepat dan tidak memerlukan terlalu banyak waktu dan usaha. Lebih baik lagi, ini relatif mudah untuk dikuasai, dan dokumentasi yang melimpah akan membantu proses pembelajaran yang tidak merepotkan.

Codeception juga mudah dipasang dan dikonfigurasi, namun menawarkan banyak opsi lanjutan. Meskipun sebagian besar pengguna tidak membutuhkan semua (atau memang, sebagian besar) dari mereka, itu semua tergantung pada apa yang ingin Anda lakukan dengannya. Anda dapat mulai dengan dasar-dasarnya, dan fitur tambahan akan berguna cepat atau lambat.

Terkait: Kode PHP Buggy: 10 Kesalahan Paling Umum yang Dilakukan Pengembang PHP