Codeception ile PHP Testinize Hızlı Başlayın
Yayınlanan: 2022-03-11Codeception ve PHP'ye geçmeden önce, temel bilgileri ele almalı ve ilk etapta neden uygulamalarda teste ihtiyacımız olduğunu açıklayarak başlamalıyız. En azından bu sefer testlerle vakit kaybetmeden bir projeyi tamamlayabilir miyiz?
Elbette, her şey için teste ihtiyacınız yok; örneğin, başka bir ana sayfa oluşturmak istediğinizde. Projeniz bir yönlendirici tarafından bağlanan statik sayfalar içerdiğinde muhtemelen testlere ihtiyacınız yoktur.
Ancak, aşağıdaki durumlarda kesinlikle teste ihtiyacınız vardır:
- Ekibiniz BDD/TDD kullanıyor.
- Git deponuz birkaç taahhütten fazlasını içeriyor.
- Ciddi bir proje üzerinde çalışan gerçek bir profesyonelsiniz.
Zaten özel bir test departmanınız, testler yapan ve gerektiğinde yenilerini yazan bir grup insan olduğunu söyleyerek kendinizi mazur görebilirsiniz. Ancak, projenize yeni işlevler ekledikten sonra hata düzeltmenin ne kadar süreceğini hayal edebiliyor musunuz?
Test Neyi Çözer?
Öncelikle, test yoluyla ne tür sorunların çözülebileceğine karar verelim. Test ile tüm hatalarınızdan kurtulamazsınız, ancak beklenen davranışı test senaryolarında tanımlayabilirsiniz. Hatalar, test durumlarınızın içinde olabilir. Spagetti kodu, test senaryolarını kullandığınızda bile spagetti kodu olarak kalır.
Ancak, kodunuzun daha sonra değiştirileceğinden (hataları düzelterek veya yeni özellikler ekleyerek) emin olabilirsiniz, böylece kodunuz testte açıklanan hatalardan hala arınmış olacaktır. Ayrıca, iyi yazılmış testler bile bazen belgelerde kullanılabilir çünkü orada tipik senaryoların nasıl ortaya çıktığını görebilir ve beklenen davranışı kontrol edebilirsiniz. Testin geleceğe yönelik küçük ama çok önemli bir yatırım olduğunu söyleyebiliriz.
Peki ne tür testler uygulayabiliriz?
- Birim testleri: Kodunuzun küçük parçalarını kontrol eden düşük seviyeli testler - diğer kodlardan izole edilmiş sınıfınızın yöntemleri.
- Entegrasyon testi: Entegrasyon testleri, uygulamanızın bir bölümünü kontrol eder, birkaç sınıf veya yöntem içerebilirler, ancak bir özellikle sınırlandırılmalıdır. Bu test aynı zamanda farklı sınıfların nasıl etkileşime girdiğini de kontrol etmelidir.
- İşlevsel test: Uygulamanıza yönelik belirli istekleri test eder: tarayıcı yanıtı, veritabanı değişiklikleri vb.
- Kabul testi: Çoğu durumda kabul testi, uygulamanın tüm müşteri gereksinimlerini karşılayıp karşılamadığının kontrol edilmesi anlamına gelir.
Açıklığa kavuşturmak için, süreci bir bina gibi somut bir şeyle örneklediğimizi varsayalım. Bir bina, duvarları oluşturan küçük bloklardan oluşur. Her tuğlanın belirtilen gereksinimleri karşılaması gerekir; gerekli yüke dayanması, belirli bir hacme ve şekle sahip olması vb. Bunlar birim testleridir. Entegrasyon testleri fikri, tuğlaların birbirine ne kadar sıkı ve doğru bir şekilde yapıştığını, binanın belirli bir unsuruna nasıl entegre olduklarını kontrol etmektir. Fonksiyonel testler, binanın tek bir duvarında, iç mekanın elementlerden korunup korunmadığını, pencereden güneşi görmenin mümkün olup olmadığını kontrol etmek için yapılan testlere benzetilebilir. Kabul testi, tüm binanın eksiksiz bir ürün olarak test edilmesini içerir: Kapıyı açın, içeri girin, kapıyı kapatın, ışığı açın, ikinci kata çıkın ve binanın dışındaki bahçeye bakın.
Codeception ile tanışın
Bununla birlikte, bu ayrım koşulludur ve bazen farklı türdeki testleri karıştırmanın cazibesine direnmek zordur.
Birçok geliştirici birim testleri kullanır ve bunun yeterli olduğunu iddia eder. Eskiden böyle bir geliştiriciydim; Farklı testler için farklı sistemler kullanmayı çok zor ve zaman alıcı buldum. Bir süre önce PHPUnit'ten daha kullanışlı bir şey bulmaya karar verdim; Kodumu test etmede daha iyi olmak istedim, ancak tonlarca belge okuyup öğrenmek ve tuzaklar aramak istemedim. Codeception'ı böyle keşfettim. İlk başta, yeni bir şey söz konusu olduğunda sık sık olduğumuz gibi şüpheliydim (bu proje beş yaşında, bu nedenle teknik olarak “yeni” olarak kabul edilemez), ancak birkaç gün onunla oynadıktan sonra , Codeception'ın çok kullanışlı ve güçlü bir sistem olduğu sonucuna vardım.
Peki Codeception'ı nasıl kurarsınız? Aldığı kadar basit:
$ composer require "codeception/codeception" $ php vendor/bin/codecept bootstrap
Kurulumdan sonra, projenizde testler adında yeni bir klasör bulacaksınız ve kabul, işlevsel ve birim adında bazı alt klasörler olacak. Görünüşe göre testlerimizi yazmaya başlayabiliriz. Güzel, ama sırada ne var?
Şimdi, standart bir kabul edilen Merhaba Dünya testi eklemeyi deneyin.
$ php vendor/bin/codecept generate:cept acceptance HelloWorld
Şimdi, aşağıdaki içeriğe sahip bir test/kabul/HelloWorldCept.php kabul testi dosyası alıyoruz:
<?php $I = new AcceptanceTester($scenario); $I->wantTo('perform actions and see result');
$I
adlı varsayılan değişken yalnızca bir harf değildir; bir karakterdir. Testleri ne yapar? Test cihazı, açıkçası. Bu test cihazı, web sitenizin sayfasını veya sınıfını açar, onunla bir şeyler yapar ve eylemlerinin sonucunu size gösterir. Neyin işe yaradığını ve neyin yanlış gittiğini göreceksiniz. Bu nesnenin $I
olarak adlandırılmasının ve bu nedenle wantTo()
, see()
veya amOnPage()
adlı yöntemleri içermesinin nedeni budur.
Öyleyse, bir sayfanın çalışabilirliğini kontrol etmenin yollarını bir testçi gibi düşünelim. İlk yaklaşım, sayfayı açmak ve bir kelime öbeği aramaktır. Sayfanın ziyaretçilere açık olduğunu kanıtlar.
Bu kolay olmalı:
<?php $I->amOnPage('/'); $I->see('Welcome');
Codeception'ın testlerini çalıştırmak için bu komutu kullanabiliriz:
$ php vendor/bin/codecept run
Bir şeylerin yanlış olduğunu hemen görüyoruz. İlk bakışta mesajın çok uzun ve belirsiz olduğu anlaşılıyor, ancak daha yakından baktığımızda her şey netleşiyor.
Bir testimiz vardı, Kabul ve bir hata tespit etti:
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)
Suçlu bu: localhost mevcut değil.
Ve işte testimizin senaryo adımları:
1. $I->amOnPage("/")
Tamam,tests/acceptance.suite.yml dosyasını açalım ve url: http://localhost/
'u gerçekten mevcut olan bir şeyle değiştirelim. Benim durumumda, bu benim yerel test sunucum, url: https://local.codeception-article.com/
Testi tekrar çalıştırın ve sonuç şudur:
Acceptance Tests (1) --------------------------------------------------------------------------------------- Perform actions and result (HelloWorldCept) Ok
Yaşasın! İlk başarılı testimiz!
Tabii ki, amOnPage()
mevcut tek test yöntemi değil, sadece örneğimiz için seçtik. Tüm Codeception test yöntemleri aşağıdaki gruplara ayrılabilir:
- Sayfayla etkileşim:
fillField()
, selectOption(selectOption()
,submitForm()
,click()
- iddialar.
see()
,dontSee()
,seeElement()
,seeInCurrentUrl()
,seeCheckboxIsChecked()
,seeInField()
,seeLink()
. Tüm bu yöntemlere bir sonek ekleyebilir ve bir şey bulunamadığında test senaryosunu kesintiye uğratmayacak bir yönteme ihtiyaç duyduğunuzda kullanabilirsiniz. - Çerez yöntemleri:
setCookie()
,grabCookie()
,seeCookie()
- Test senaryolarının yorumu ve açıklaması:
amGoingTo()
,wantTo()
) , wait(expect()
. Testin hedeflerini hatırlamanıza yardımcı olacak iyi yorumlanmış ve tanımlanmış testler almak için bu yöntemleri kullanın.
Dolayısıyla, şifre sıfırlama e-posta sayfasını test edecek olsaydık, bunu şu şekilde yapabilirdik:
<?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');
Bunu yapması gerekiyor gibi görünüyor, ama ya sayfada Ajax yüklü bazı parçalar varsa? Böyle bir sayfayı test edebilir miyiz? Cevap, Codeception'ın varsayılan olarak Symfony BrowserKit ve Guzzle tabanlı PhpBrowser kullanmasıdır. Basittir, hızlıdır ve kullanmak için yalnızca kıvrılmaya ihtiyacınız vardır.

Ayrıca Selenium'u kullanabilir ve sayfaları gerçek tarayıcılarla test edebilirsiniz. Evet, daha yavaş olacak, ancak JavaScript'i de test edebileceksiniz.
İlk olarak, Selenium sürücüsünü kurmanız, kabul.suite.yml'yi değiştirmeniz ve AcceptanceTester sınıfını yeniden oluşturmanız gerekir. Bundan sonra wait()
ve waitForElement()
yöntemlerini kullanabilirsiniz. Ve daha da ilginci, saveSessionSnapshot()
ve loadSessionSnapshot()
yöntemlerini kullanarak zamandan ve kaynaklarınızdan tasarruf edebileceksiniz. Bu yöntem, oturum durumunu saklamanıza ve önceki oturumlarda yeni testler başlatmanıza olanak tanır. Bu, örneğin test yetkilendirme sürecinde olduğu gibi bazı durumlarda yararlıdır.
Böylece, birçok işlevi test etmek için basit ama güçlü bir yeteneğe sahip oluyoruz.
Fonksiyonel test
Tamam, fonksiyonel teste geçme zamanı.
$ php vendor/bin/codecept generate:cept functional HelloWorld
Ve elde ettiğimiz şey bu:
<?php $I = new FunctionalTester($scenario); $I->amOnPage('/'); $I->see('Welcome');
Bir dakika ne?
Hayır, bu bir hata değil. Fonksiyonel testler, entegrasyon testleri ile aynı şekilde yazılmalıdır. Aradaki fark, işlevsel testlerin doğrudan uygulamanızla etkileşime girmesidir. Bu, işlevsel testi çalıştırmak için bir web sunucusuna ihtiyacınız olmadığı ve uygulamanızın farklı bölümlerini test etmek için daha fazla kapasiteniz olduğu anlamına gelir.
Bu, tüm çerçeveler için desteğin olmadığı anlamına gelir, ancak desteklenen çerçevelerin listesi kapsamlıdır: Symfony, Silex, Phalcon, Yii, Zend Framework, Lumen, Laravel. Bu, çoğu durumda ve çoğu geliştirici için yeterli olmalıdır. Kullanılabilir işlevlerin bir listesini almak için lütfen Codeception'ın modül belgelerine bakın ve ardından bunu functional.suite.yml
içinde açın.
Birim testine geçmeden önce, küçük bir konu açmama izin verin. Fark etmiş olabileceğiniz gibi, testlerimizi key cept ile oluşturduk:
$ php vendor/bin/codecept generate: cept acceptance HelloWorld
Test oluşturmanın tek yolu bu değildir. Cest testleri de var. Aradaki fark, bir sınıfta birden çok ilgili senaryoyu yapılandırabilmenizdir:
$ 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'); } }
Bu örnekte, _before()
ve _after()
yöntemleri her testten önce ve sonra çalıştırılır. Her teste bir AcceptanceTester
sınıfı örneği iletilir, böylece onu cest testlerinde olduğu gibi kullanabilirsiniz. Bu tarz testler belirli durumlarda faydalı olabilir, bu yüzden akılda tutmaya değer.
Birim Testi
Bazı birim testleri için zaman.
Codeception, PHPUnit'e dayalıdır, bu nedenle PHPUnit için yazılmış testleri kullanabilirsiniz. Yeni PHPUnit testleri eklemek için aşağıdaki yaklaşımı kullanın:
$ php vendor/bin/codecept generate:phpunit unit HelloWorld
Veya testlerinizi \PHPUnit_Framework_TestCase
üzerinde devralın.
Ancak daha fazlasını istiyorsanız Codeception'ın birim testlerini denemelisiniz:
$ 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()); } }
Şimdilik olağandışı bir şey yok. _before()
ve _after()
yöntemleri setUp()
() ve gözyaşıDown( tearDown()
analoglarıdır ve her testten önce ve sonra çalışacaktır.
Bu testin ana avantajı, unit.suite.yml
içinde açılabilen modüller ekleyerek test sürecinizi genişletme yeteneğidir:
- Değişiklikleri izlemek için memcache ve veritabanlarına erişim (MySQL, SQLite, PostgreSQL, MongoDB desteklenir)
- REST/SOAP uygulamalarının test edilmesi
- Kuyruklar
Her modülün kendi özellikleri vardır, bu nedenle gerçek testlere geçmeden önce her modül için belgeleri kontrol etmek ve gerekli bilgileri toplamak en iyisidir.
Ayrıca, Codeception/Specify paketini ( composer.json
dosyasına eklenmesi gerekir) kullanabilir ve şöyle bir açıklama yazabilirsiniz:
<?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()); }); } }
Bu kapatma işlevlerinin içindeki PHP kodu yalıtılmıştır, bu nedenle içindeki değişiklikler kodunuzun geri kalanını etkilemeyecektir. Açıklamalar, testi daha okunabilir hale getirmenize ve başarısız testleri belirlemenizi kolaylaştırmanıza yardımcı olacaktır.
İsteğe bağlı bir ekstra olarak, BDD benzeri sözdizimi için Codeception\Verify
paketini kullanabilirsiniz:
<?php public function testUserEmailSave() { verify($map->getEmail())->equals('[email protected]'); }
Ve elbette taslakları kullanabilirsiniz:
<?php public function testUserEmailSave() { $user = Stub::make('User', ['getEmail' => '[email protected]']); $this->assertEquals('[email protected]', $user->getEmail()); }
Karar: Codeception Zamandan ve Efordan Tasarruf Sağlar
Peki Codeception'dan ne beklemelisiniz? Kimin için? Herhangi bir uyarı var mı?
Benim düşünceme göre, bu test çerçevesi her türden farklı ekip için uygundur: Büyük ve küçük, yeni başlayanlar ve savaşta deneyimli PHP uzmanları, popüler bir çerçeve kullananlar ve herhangi bir çerçeve kullanmayanlar.
Her durumda, her şey şuna bağlı: Codeception prime time için hazır.
Çok sayıda modül tarafından kolayca genişletilebilen olgun ve iyi belgelenmiş bir çerçevedir. Codeception moderndir, ancak çok fazla deneme yapmak istemeyen geliştiricilere güvence vermesi gereken, zamana göre test edilmiş PHPUnit'e dayanmaktadır.
İyi bir performans sergiliyor, bu da hızlı olduğu ve çok fazla zaman ve çaba gerektirmediği anlamına geliyor. Daha da iyisi, ustalaşması nispeten kolaydır ve bol miktarda belge, sorunsuz bir öğrenme sürecine yardımcı olmalıdır.
Codeception'ın kurulumu ve yapılandırılması da kolaydır, ancak birçok gelişmiş seçeneğe sahiptir. Çoğu kullanıcının hepsine (veya aslında çoğuna) ihtiyacı olmayacak olsa da, hepsi onunla ne yapmak istediğinize bağlıdır. Temel bilgilerle başlayabilirsiniz ve ekstra özellikler er ya da geç işinize yarayacaktır.