mata teras
Artikel ini dikaji semula oleh Younes Rafie. Terima kasih kepada semua pengulas rakan sebaya untuk mendapatkan kandungan SitePoint dengan sebaik -baiknya!
Malah, kebanyakan kerja yang saya lakukan adalah kepada syarikat -syarikat yang tidak peduli dengan bentuk ujian lain. Selepas bertahun -tahun pengalaman, dan nasihat bijak dari orang seperti Chris Hartjes, saya melihat nilai ujian. Dan saya masih belajar ujian yang baik.
Saya baru -baru ini mula bekerja pada beberapa projek JavaScript yang termasuk pemerhati ujian yang dibundel.
Ini adalah tutorial video maju yang indah mengenai pembangunan NodeJS yang didorong oleh ujian!
Di dunia JavaScript, ia bukan perkara biasa untuk kod sumber pra -proses. Di dunia JavaScript, pemaju menulis kod menggunakan sintaks yang tidak disokong dan kemudian menukar kod ke sintaks yang disokong secara meluas, sering menggunakan alat yang dipanggil Babel.
Untuk mengurangkan beban skrip penukaran memanggil, projek boilerplate telah mula memasukkan skrip yang secara automatik memantau perubahan fail;
Projek -projek yang saya kerjakan mengambil pendekatan yang sama dengan ujian unit rerun. Apabila saya menukar fail JavaScript, fail ditukar dan ujian unit adalah rerun. Dengan cara ini, saya dapat melihat dengan segera sama ada apa -apa yang rosak.
Kod untuk tutorial ini boleh didapati di GitHub. Saya telah mengujinya dengan Php 7.1.
Tetapan Projek
Selepas saya menambah skrip pra -proses untuk projek saya, semuanya bermula:
composer require pre/short-closures
Skrip preprocessing khusus ini membolehkan saya menamakan semula kelas yang dimuatkan secara automatik PSR-4 (dari Path/to/file.php ⇒ Path/to/file.pre) untuk memilih ke dalam fungsi yang mereka berikan. Jadi saya menambah perkara berikut ke fail komposer.json saya:
"autoload": { "psr-4": { "App\": "src" } }, "autoload-dev": { "psr-4": { "App\Tests\": "tests" } }
ini dari composer.json
Kemudian saya menambah kelas untuk menghasilkan fungsi yang mengandungi butiran sesi pengguna semasa:
namespace App; use Closure; class Session { private $user; public function __construct(array $user) { $this->user = $user; } public function closureWithUser(Closure $closure) { return () => { $closure($this->user); }; } }
Ini berasal dari src/session.pre
Untuk memeriksa sama ada ini berfungsi, saya menyediakan skrip sampel kecil:
require_once __DIR__ . "/vendor/autoload.php"; $session = new App\Session(["id" => 1]); $closure = ($user) => { print "user: " . $user["id"] . PHP_EOL; }; $closureWithUser = $session->closureWithUser($closure); $closureWithUser();
ini berasal dari contoh.pre
... dan kerana saya ingin menggunakan penutupan pendek dalam kelas bukan PSR-4, saya juga perlu menyediakan loader:
require_once __DIR__ . "/vendor/autoload.php"; Pre\Plugin\process(__DIR__ . "/example.pre");
ini berasal dari loader.php
Bahagian kod ini banyak untuk menggambarkan titik kecil. Kelas Sesi mempunyai kaedah ClosureWithuser yang menerima satu penutupan dan mengembalikan yang lain. Apabila dipanggil, penutupan baru ini akan memanggil penutupan asal, menyediakan array sesi pengguna sebagai parameter.
untuk menjalankan semua ini, taipkan terminal:
php loader.php
Sebagai nota sampingan, preprocessors ini menghasilkan sintaks PHP yang berkesan yang cantik. Nampaknya ini:
$closure = function ($user) { print "user: " . $user["id"] . PHP_EOL; };
... dan
public function closureWithUser(Closure $closure) { return [$closure = $closure ?? null, "fn" => function () use (&$closure) { $closure($this->user); }]["fn"]; }
Anda mungkin tidak mahu mengemukakan kedua -dua PHP dan pra fail ke repositori. Untuk melakukan ini, saya telah menambah apl/**/*. Php dan contoh.php ke .gitignore.
Jadi bagaimana kita menguji ini? Mari mulakan dengan memasang phpunit:
composer require --dev phpunit/phpunit
Kemudian, kita harus membuat fail konfigurasi:
<?xml version="1.0" encoding="UTF-8"?> <phpunit backupGlobals="false" backupStaticAttributes="false" bootstrap="vendor/autoload.php" colors="true" convertErrorsToExceptions="true" convertNoticesToExceptions="true" convertWarningsToExceptions="false" processIsolation="false" stopOnFailure="false" syntaxCheck="false" > <testsuites> <testsuite> <directory suffix="Test.php">tests</directory> </testsuite> </testsuites> <filter> <whitelist addUncoveredFilesFromWhitelist="true"> <directory suffix=".php">src</directory> </whitelist> </filter> </phpunit>
ini dari phpunit.xml
Jika kita menjalankan vendor/bin/phpunit, ia akan berfungsi. Tetapi kami belum menguji apa -apa lagi. Mari buat satu:
namespace App\Tests; use App\Session; use PHPUnit\Framework\TestCase; class SessionTest extends TestCase { public function testClosureIsDecorated() { $user = ["id" => 1]; $session = new Session($user); $expected = null; $closure = function($user) use (&$expected) { $expected = "user: " . $user["id"]; }; $closureWithUser = $session ->closureWithUser($closure); $closureWithUser(); $this->assertEquals("user: 1", $expected); } }
Ini berasal dari ujian/sessiontest.php
Apabila kita menjalankan vendor/bin/phpunit, satu ujian berlalu. Ya!
Setakat ini, semuanya berjalan lancar. Kami menulis sekeping kecil kod dan ujian kod ini. Kami tidak perlu bimbang tentang bagaimana kerja pra -proses (langkah ke atas projek JavaScript).
Masalahnya bermula apabila kita cuba menyemak liputan kod:
vendor/bin/phpunit --coverage-html coverage
Semasa kami menguji sesi, liputan akan dilaporkan. Ia adalah kelas yang mudah, jadi kami telah mencapai liputan 100% di atasnya. Tetapi jika kita menambah kelas lain:
namespace App; class BlackBox { public function get($key) { return $GLOBALS[$key]; } }
Ini berasal dari src/blackbox.pre
Apa yang berlaku apabila kita memeriksa liputan? Masih 100%.
Ini berlaku kerana kita tidak mempunyai sebarang ujian yang memuatkan Blackbox.pre, yang bermaksud ia tidak pernah disusun. Oleh itu, apabila PHPUnit mencari fail PHP yang ditimpa, ia tidak dapat melihat fail pra -proses ini.
mari buat skrip baru untuk membina semua fail pra sebelum cuba menjalankan ujian:
composer require pre/short-closures
Ini berasal dari ujian/bootstrap.php
di sini, kami membuat 3 fungsi;
kita perlu menggantikan fail bootstrap semasa dalam phpunit.xml:
"autoload": { "psr-4": { "App\": "src" } }, "autoload-dev": { "psr-4": { "App\Tests\": "tests" } }
ini dari phpunit.xml
Sekarang, setiap kali kita menjalankan ujian, skrip ini akan terlebih dahulu membersihkan dan membina semula semua fail pra ke fail PHP. Liputan dilaporkan dengan betul dan kami dapat meneruskan perjalanan gembira kami ...
Dalam projek ini yang saya nyatakan, saya mempunyai 101 fail pra. Hanya untuk menjalankan suite ujian unit saya (mudah -mudahan cepat), ini memerlukan banyak pra -proses. Kami memerlukan cara untuk memantau perubahan dan membina semula bahagian penting sahaja. Pertama, mari pasang pemerhati fail:
namespace App; use Closure; class Session { private $user; public function __construct(array $user) { $this->user = $user; } public function closureWithUser(Closure $closure) { return () => { $closure($this->user); }; } }
require_once __DIR__ . "/vendor/autoload.php"; $session = new App\Session(["id" => 1]); $closure = ($user) => { print "user: " . $user["id"] . PHP_EOL; }; $closureWithUser = $session->closureWithUser($closure); $closureWithUser();
ini berasal dari skrip/test-testSkrip ini mencipta pencari Symfony (digunakan untuk mengimbas folder SRC dan ujian kami). Kami menentukan fail perubahan sementara, tetapi ini tidak diperlukan untuk apa yang kami lakukan. Kami seterusnya menggunakan gelung tak terhingga. ResourceWatcher mempunyai kaedah yang boleh kita gunakan untuk melihat sama ada fail dibuat, diubahsuai, atau dipadam.
baru, mari kita cari fail mana yang telah diubah dan membina semula mereka:
require_once __DIR__ . "/vendor/autoload.php"; Pre\Plugin\process(__DIR__ . "/example.pre");
ini berasal dari skrip/test-testKod ini sama dengan apa yang kita lakukan dalam fail bootstrap, tetapi ia hanya terpakai kepada fail yang diubah. Kita juga harus membuat semula ujian apabila fail berubah:
php loader.php
ini berasal dari skrip/test-testKami memperkenalkan beberapa pembolehubah persekitaran. Anda boleh menguruskan pembolehubah ini mengikut keinginan anda, tetapi saya lebih suka menambahkannya ke skrip komposer:
$closure = function ($user) { print "user: " . $user["id"] . PHP_EOL; };
ini dari composer.jsonapp_cover tidak begitu penting. Ia hanya memberitahu pemerhati sama ada skrip mengandungi liputan kod. APP_REBUILD memainkan peranan yang lebih penting: ia mengawal sama ada fail pra dibina semula apabila fail ujian/bootstrap.php dimuatkan. Kita perlu mengubah suai fail supaya fail itu dibina semula hanya apabila diminta:
public function closureWithUser(Closure $closure) { return [$closure = $closure ?? null, "fn" => function () use (&$closure) { $closure($this->user); }]["fn"]; }
Ini berasal dari ujian/bootstrap.phpkita juga perlu mengubah suai skrip Observer untuk menetapkan pembolehubah persekitaran ini sebelum memasukkan kod bootstrap. Seluruh skrip pemerhati kelihatan seperti ini:
composer require --dev phpunit/phpunit
ini berasal dari skrip/test-test
Sekarang kita harus dapat memulakannya dan menjalankan ujian kita setiap kali perubahan fail pra -diproses ...
Beberapa perkara yang perlu diingat (RAWR). Pertama, anda memerlukan skrip chmod x/* untuk menjalankan skrip pemerhati. Kedua, anda perlu menetapkan Config: {Process-Timeout: 0} (dalam Composer.json), jika tidak, pemerhati akan mati selepas 300 saat.Pusingan ganjaran!
composer require pre/short-closures
Ini berasal dari ujian/bootstrap.php... dan kami membolehkan pra -proses dalam fail ujian (untuk pra, itu bermakna menamakannya ke .pre). Kemudian kita boleh mula menggunakan preprocessor yang sama dalam fail ujian kami:
"autoload": { "psr-4": { "App\": "src" } }, "autoload-dev": { "psr-4": { "App\Tests\": "tests" } }
Ini berasal dari ujian/sessiontest.preKesimpulan
Adakah kaedah ini berkesan untuk anda? Ia boleh menyesuaikan diri dengan pelayan HTTP yang tidak segerak atau proses jangka panjang yang lain. Tolong beritahu kami apa yang anda fikirkan dalam komen.
FAQ untuk pemerhati ujian gaya JavaScript dalam PHP (FAQ)
Apakah faedah menggunakan pemerhati ujian dalam PHP?
Ya, anda boleh menggunakan kod PHP di dalam fungsi JavaScript, tetapi ini tidak disyorkan. PHP adalah bahasa sisi pelayan, manakala JavaScript adalah bahasa sisi klien. Ini bermakna bahawa kod PHP dilaksanakan pada pelayan sebelum halaman dihantar kepada klien, manakala kod JavaScript dilaksanakan pada klien selepas halaman diterima. Oleh itu, jika anda cuba menggunakan kod PHP di dalam fungsi JavaScript, kod PHP akan dilaksanakan sebelum fungsi JavaScript, yang mungkin membawa kepada hasil yang tidak dijangka.
Codeception adalah rangka kerja ujian untuk PHP yang menyokong ujian unit, ujian fungsional, dan ujian penerimaan. Untuk menguji kod PHP anda dengan codeception, anda perlu memasang codeception dan mengkonfigurasinya untuk projek anda. Anda kemudian boleh menulis ujian untuk kod anda menggunakan sintaks codeception dan menjalankan ujian anda menggunakan alat baris arahan codeception.
Secara teknikal anda boleh menulis kod PHP dalam JavaScript, ini tidak disyorkan. PHP adalah bahasa sisi pelayan, manakala JavaScript adalah bahasa sisi klien. Ini bermakna bahawa kod PHP dilaksanakan pada pelayan sebelum halaman dihantar kepada klien, manakala kod JavaScript dilaksanakan pada klien selepas halaman diterima. Oleh itu, jika anda cuba menulis kod PHP dalam JavaScript, kod PHP akan dilaksanakan sebelum kod JavaScript, yang boleh membawa kepada hasil yang tidak dijangka. Sebaliknya, lebih baik menggunakan AJAX untuk menghantar data dari klien ke pelayan dan sebaliknya.
Atas ialah kandungan terperinci Cara Menulis Pengawal Ujian Gaya JavaScript di PHP. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!