国产av日韩一区二区三区精品,成人性爱视频在线观看,国产,欧美,日韩,一区,www.成色av久久成人,2222eeee成人天堂

目錄
項目設(shè)置
設(shè)置測試
我們?nèi)鄙偈颤N?
在測試之前構(gòu)建所有文件
除了這件事……
獎勵回合!
結(jié)論
關(guān)於 PHP 中 JavaScript 風(fēng)格測試觀察者的常見問題解答 (FAQ)
如何在 PHP 中設(shè)置 JavaScript 風(fēng)格的測試觀察者?
使用 PHP 中的測試觀察者的好處是什麼?
我可以在 JavaScript 函數(shù)內(nèi)使用 PHP 代碼嗎?
如何使用 Codeception 測試我的 PHP 代碼?
如何在 JavaScript 中編寫 PHP 代碼?
首頁 後端開發(fā) php教程 如何在PHP中寫JavaScript風(fēng)格的測試觀察者

如何在PHP中寫JavaScript風(fēng)格的測試觀察者

Feb 09, 2025 am 10:58 AM

How to Write JavaScript-Style Test Watchers in PHP

核心要點

  • 將 JavaScript 風(fēng)格的測試觀察者集成到 PHP 項目中,自動化預(yù)處理文件的轉(zhuǎn)換,並在文件更改時重新運行單元測試,從而提高開發(fā)效率。
  • 使用 PHPUnit 等工具設(shè)置自動化測試,並使用 PHPUnit-Watcher 觀察文件修改,確保在開發(fā)過程中立即獲得反饋並檢測錯誤。
  • 在 PHP 項目中實現(xiàn)預(yù)處理腳本,允許進(jìn)行類似於 JavaScript Babel 的語法轉(zhuǎn)換,從而提高兼容性並減少手動編碼工作。
  • 配置 PHP 測試環(huán)境,以便在測試之前自動重建預(yù)處理文件,從而保持準(zhǔn)確的代碼覆蓋率並簡化測試過程。
  • 探索使用文件觀察者的高級配置,以便有選擇地僅重建已修改的文件,從而顯著加快大型項目中大量文件的測試週期。

本文由 Younes Rafie 審核。感謝所有 SitePoint 的同行評審人員,使 SitePoint 內(nèi)容達(dá)到最佳狀態(tài)!


我一開始並沒有為我的代碼編寫測試。像許多人一樣,我的“測試”就是編寫代碼並刷新頁面。 “看起來對嗎?”,我會問自己。如果我認(rèn)為是對的,我就繼續(xù)進(jìn)行。

事實上,我做過的大部分工作都是在不太關(guān)心其他形式測試的公司。經(jīng)過多年時間,以及像 Chris Hartjes 這樣的人的明智建議,我才看到了測試的價值。而且我仍在學(xué)習(xí)好的測試是什麼樣的。

How to Write JavaScript-Style Test Watchers in PHP

我最近開始從事一些包含捆綁測試觀察者的 JavaScript 項目。

這是一個關(guān)於測試驅(qū)動 NodeJS 開發(fā)的精彩高級視頻教程!

在 JavaScript 的世界裡,預(yù)處理源代碼並不少見。在 JavaScript 的世界裡,開發(fā)人員使用不被廣泛支持的語法編寫代碼,然後將代碼轉(zhuǎn)換為被廣泛支持的語法,通常使用名為 Babel 的工具。

為了減少調(diào)用轉(zhuǎn)換腳本的負(fù)擔(dān),樣板項目已開始包含自動監(jiān)視文件更改的腳本;然後調(diào)用這些腳本。

我參與的這些項目採用了類似的方法來重新運行單元測試。當(dāng)我更改 JavaScript 文件時,這些文件會被轉(zhuǎn)換,並且單元測試會被重新運行。這樣,我可以立即看到是否破壞了任何東西。

本教程的代碼可以在 Github 上找到。我已經(jīng)用 PHP 7.1 測試過它。

項目設(shè)置

自從開始從事這些項目以來,我開始為 PHPUnit 設(shè)置類似的東西。事實上,我設(shè)置 PHPUnit 觀察者腳本的第一個項目是一個也預(yù)處理文件的 PHP 項目。

在我向我的項目添加預(yù)處理腳本後,這一切就開始了:

composer require pre/short-closures

這些特定的預(yù)處理腳本允許我重命名 PSR-4 自動加載的類(從 path/to/file.php ? path/to/file.pre),以選擇加入它們提供的功能。所以我向我的 composer.json 文件添加了以下內(nèi)容:

"autoload": {
    "psr-4": {
        "App\": "src"
    }
},
"autoload-dev": {
    "psr-4": {
        "App\Tests\": "tests"
    }
}

這來自 composer.json

然後我添加了一個類來生成包含當(dāng)前用戶會話詳細(xì)信息的函數(shù):

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);
        };
    }
}

這來自 src/Session.pre

為了檢查這是否有效,我設(shè)置了一個小的示例腳本:

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();

這來自 example.pre

……而且因為我想在非 PSR-4 類中使用短閉包,我還需要設(shè)置一個加載器:

require_once __DIR__ . "/vendor/autoload.php";

Pre\Plugin\process(__DIR__ . "/example.pre");

這來自 loader.php

這段代碼很多,是為了說明一個小點。 Session 類有一個 closureWithUser 方法,它接受一個閉包並返回另一個。調(diào)用時,這個新的閉包將調(diào)用原始閉包,提供用戶會話數(shù)組作為參數(shù)。

要運行所有這些,請在終端中鍵入:

php loader.php

作為旁注,這些預(yù)處理器生成的有效 PHP 語法非常漂亮。它看起來像這樣:

$closure = function ($user) {
   print "user: " . $user["id"] . PHP_EOL;
};

……和

public function closureWithUser(Closure $closure)
{
   return [$closure = $closure ?? null, "fn" => function () use (&$closure) {
       $closure($this->user);
   }]["fn"];
}

你可能不想將 php 和 pre 文件都提交到倉庫。為此,我已經(jīng)將 app/**/*.php 和 examples.php 添加到 .gitignore 中。

設(shè)置測試

那麼我們?nèi)绾螠y試這個呢?讓我們從安裝 PHPUnit 開始:

composer require --dev phpunit/phpunit

然後,我們應(yīng)該創(chuàng)建一個配置文件:

<?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>

這來自 phpunit.xml

如果我們運行 vendor/bin/phpunit,它將有效。但是我們還沒有任何測試。讓我們做一個:

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);
    }
}

這來自 tests/SessionTest.php

當(dāng)我們運行 vendor/bin/phpunit 時,單個測試通過了。耶!

我們?nèi)鄙偈颤N?

到目前為止,一切順利。我們編寫了一小段代碼,以及這段代碼的測試。我們甚至不必?fù)?dān)心預(yù)處理是如何工作的(比 JavaScript 項目更上一層樓)。

當(dāng)我們嘗試檢查代碼覆蓋率時,問題就開始了:

vendor/bin/phpunit --coverage-html coverage

由於我們對 Session 進(jìn)行了測試,因此將報告覆蓋率。它是一個簡單的類,因此我們已經(jīng)對它實現(xiàn)了 100% 的覆蓋率。但是如果我們添加另一個類:

namespace App;

class BlackBox
{
    public function get($key)
    {
        return $GLOBALS[$key];
    }
}

這來自 src/BlackBox.pre

當(dāng)我們檢查覆蓋率時會發(fā)生什麼?仍然是 100%。

發(fā)生這種情況是因為我們沒有任何加載 BlackBox.pre 的測試,這意味著它從未被編譯。因此,當(dāng) PHPUnit 查找已覆蓋的 PHP 文件時,它看不到這個可預(yù)處理的文件。

在測試之前構(gòu)建所有文件

讓我們創(chuàng)建一個新腳本,在嘗試運行測試之前構(gòu)建所有 Pre 文件:

composer require pre/short-closures

這來自 tests/bootstrap.php

在這裡,我們創(chuàng)建了 3 個函數(shù);一個用於獲取遞歸文件迭代器(來自路徑),一個用於刪除此迭代器的文件,一個用於重新編譯 Pre 文件。

我們需要替換 phpunit.xml 中當(dāng)前的 bootstrap 文件:

"autoload": {
    "psr-4": {
        "App\": "src"
    }
},
"autoload-dev": {
    "psr-4": {
        "App\Tests\": "tests"
    }
}

這來自 phpunit.xml

現(xiàn)在,每當(dāng)我們運行測試時,此腳本將首先清理並重建所有 Pre 文件到 PHP 文件。覆蓋率被正確報告,我們可以繼續(xù)我們的快樂旅程……

除了這件事……

我們的代碼庫很小,但它不需要很小。我們可以在真實的應(yīng)用程序中嘗試這個,並立即後悔每次想要測試時都必須重建文件。

在這個我提到的項目中,我有 101 個 Pre 文件。僅僅為了運行我的(希望很快的)單元測試套件,這就需要大量的預(yù)處理。我們需要一種方法來監(jiān)視更改,並且只重建重要的部分。首先,讓我們安裝一個文件觀察者:

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);
        };
    }
}

然後,讓我們創(chuàng)建一個測試腳本:

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();

這來自 scripts/watch-test

該腳本創(chuàng)建一個 Symfony 查找器(用於掃描我們的 src 和 tests 文件夾)。我們定義了一個臨時更改文件,但這對於我們正在做的事情來說並不是嚴(yán)格要求的。我們接下來使用一個無限循環(huán)。 ResourceWatcher 有一個我們可以用來查看是否創(chuàng)建、修改或刪除了任何文件的方法。

新的,讓我們找到哪些文件已更改,並重建它們:

require_once __DIR__ . "/vendor/autoload.php";

Pre\Plugin\process(__DIR__ . "/example.pre");

這來自 scripts/watch-test

這段代碼類似於我們在 bootstrap 文件中所做的操作,但它只應(yīng)用於已更改的文件。當(dāng)文件更改時,我們還應(yīng)該重新運行測試:

php loader.php

這來自 scripts/watch-test

我們正在引入幾個環(huán)境變量。您可以根據(jù)自己的喜好管理這些變量,但我更喜歡將它們添加到 composer 腳本中:

$closure = function ($user) {
   print "user: " . $user["id"] . PHP_EOL;
};

這來自 composer.json

APP_COVER 並不是那麼重要。它只是告訴觀察者腳本是否包含代碼覆蓋率。 APP_REBUILD 扮演著更重要的角色:它控制在加載 tests/bootstrap.php 文件時是否重建 Pre 文件。我們需要修改該文件,以便僅在請求時重建文件:

public function closureWithUser(Closure $closure)
{
   return [$closure = $closure ?? null, "fn" => function () use (&$closure) {
       $closure($this->user);
   }]["fn"];
}

這來自 tests/bootstrap.php

我們還需要修改觀察者腳本,以便在包含 bootstrap 代碼之前設(shè)置此環(huán)境變量。整個觀察者腳本如下所示:

composer require --dev phpunit/phpunit

這來自 scripts/watch-test

現(xiàn)在我們應(yīng)該能夠啟動它,並在每次可預(yù)處理文件更改時運行我們的測試……

How to Write JavaScript-Style Test Watchers in PHP

需要記住幾件事(rawr)。首先,您需要 chmod x scripts/* 才能運行觀察者腳本。其次,您需要設(shè)置 config: {process-timeout: 0}(在 composer.json 中),否則觀察者將在 300 秒後死亡。

獎勵回合!

這個測試觀察者還啟用了一個很酷的副作用:能夠在我們的 PHPUnit 測試中使用預(yù)處理器/轉(zhuǎn)換。如果我們向 tests/bootstrap.php 添加一些代碼:

composer require pre/short-closures

這來自 tests/bootstrap.php

……並且我們在測試文件中啟用預(yù)處理(對於 Pre,這意味著將其重命名為 .pre)。然後我們可以開始在我們的測試文件中使用相同的預(yù)處理器:

"autoload": {
    "psr-4": {
        "App\": "src"
    }
},
"autoload-dev": {
    "psr-4": {
        "App\Tests\": "tests"
    }
}

這來自 tests/SessionTest.pre

結(jié)論

我不敢相信在嘗試創(chuàng)建這種測試觀察者之前,我已經(jīng)做了這麼多的預(yù)處理器工作。這證明了我們可以從其他語言和框架中學(xué)到什麼。如果我沒有參與那些 JavaScript 項目,我可能會繼續(xù)在每次測試運行之前重建我的文件。噁心!

這種方法對您有效嗎?它可以適應(yīng)異步 HTTP 服務(wù)器或其他長期運行的進(jìn)程。請在評論中告訴我們您的想法。

關(guān)於 PHP 中 JavaScript 風(fēng)格測試觀察者的常見問題解答 (FAQ)

如何在 PHP 中設(shè)置 JavaScript 風(fēng)格的測試觀察者?

在 PHP 中設(shè)置 JavaScript 風(fēng)格的測試觀察者涉及多個步驟。首先,您需要安裝 PHPUnit 和 PHPUnit-Watcher。 PHPUnit 是一個用於 PHP 的測試框架,它提供了一種為代碼編寫測試的方法。 PHPUnit-Watcher 是一個監(jiān)視您的代碼並在保存文件時運行 PHPUnit 測試的工具。安裝這些工具後,您可以配置 PHPUnit-Watcher 來監(jiān)視您的代碼並自動運行您的測試。此設(shè)置允許您立即獲得代碼更改的反饋,這可以幫助您更快地發(fā)現(xiàn)和修復(fù)錯誤。

使用 PHP 中的測試觀察者的好處是什麼?

在 PHP 中使用測試觀察者有很多好處。它提供代碼更改的即時反饋,這可以幫助您更快地發(fā)現(xiàn)和修復(fù)錯誤。它還可以節(jié)省您的時間,因為您不必在每次代碼更改後手動運行測試。此外,它鼓勵您為代碼編寫測試,這可以提高代碼質(zhì)量並使其更易於維護(hù)。

我可以在 JavaScript 函數(shù)內(nèi)使用 PHP 代碼嗎?

是的,您可以在 JavaScript 函數(shù)內(nèi)使用 PHP 代碼,但不建議這樣做。 PHP 是一種服務(wù)器端語言,而 JavaScript 是一種客戶端語言。這意味著 PHP 代碼在頁面發(fā)送到客戶端之前在服務(wù)器上執(zhí)行,而 JavaScript 代碼在頁面接收後在客戶端執(zhí)行。因此,如果您嘗試在 JavaScript 函數(shù)內(nèi)使用 PHP 代碼,PHP 代碼將在 JavaScript 函數(shù)之前執(zhí)行,這可能會導(dǎo)致意外結(jié)果。

如何使用 Codeception 測試我的 PHP 代碼?

Codeception 是一個用於 PHP 的測試框架,它支持單元測試、功能測試和驗收測試。要使用 Codeception 測試您的 PHP 代碼,您首先需要安裝 Codeception 並為您的項目配置它。然後,您可以使用 Codeception 的語法為您的代碼編寫測試,並使用 Codeception 的命令行工具運行您的測試。

如何在 JavaScript 中編寫 PHP 代碼?

雖然從技術(shù)上講可以在 JavaScript 中編寫 PHP 代碼,但不建議這樣做。 PHP 是一種服務(wù)器端語言,而 JavaScript 是一種客戶端語言。這意味著 PHP 代碼在頁面發(fā)送到客戶端之前在服務(wù)器上執(zhí)行,而 JavaScript 代碼在頁面接收後在客戶端執(zhí)行。因此,如果您嘗試在 JavaScript 中編寫 PHP 代碼,PHP 代碼將在 JavaScript 代碼之前執(zhí)行,這可能會導(dǎo)致意外結(jié)果。相反,最好使用 AJAX 將數(shù)據(jù)從客戶端發(fā)送到服務(wù)器,反之亦然。

以上是如何在PHP中寫JavaScript風(fēng)格的測試觀察者的詳細(xì)內(nèi)容。更多資訊請關(guān)注PHP中文網(wǎng)其他相關(guān)文章!

本網(wǎng)站聲明
本文內(nèi)容由網(wǎng)友自願投稿,版權(quán)歸原作者所有。本站不承擔(dān)相應(yīng)的法律責(zé)任。如發(fā)現(xiàn)涉嫌抄襲或侵權(quán)的內(nèi)容,請聯(lián)絡(luò)admin@php.cn

熱AI工具

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅(qū)動的應(yīng)用程序,用於創(chuàng)建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發(fā)環(huán)境

Dreamweaver CS6

Dreamweaver CS6

視覺化網(wǎng)頁開發(fā)工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

如何在PHP中實施身份驗證和授權(quán)? 如何在PHP中實施身份驗證和授權(quán)? Jun 20, 2025 am 01:03 AM

tosecurelyhandleauthenticationandationallizationInphp,lofterTheSesteps:1.AlwaysHashPasswordSwithPassword_hash()andverifyusingspasspassword_verify(),usepreparedStatatementStopreventsqlineptions,andStoreSeruserDatain usseruserDatain $ _sessiveferterlogin.2.implementrole-2.imaccessccsccccccccccccccccccccccccc.

如何在PHP中安全地處理文件上傳? 如何在PHP中安全地處理文件上傳? Jun 19, 2025 am 01:05 AM

要安全處理PHP中的文件上傳,核心在於驗證文件類型、重命名文件並限制權(quán)限。 1.使用finfo_file()檢查真實MIME類型,僅允許特定類型如image/jpeg;2.用uniqid()生成隨機文件名,存儲至非Web根目錄;3.通過php.ini和HTML表單限製文件大小,設(shè)置目錄權(quán)限為0755;4.使用ClamAV掃描惡意軟件,增強安全性。這些步驟有效防止安全漏洞,確保文件上傳過程安全可靠。

PHP中==(鬆散比較)和===(嚴(yán)格的比較)之間有什麼區(qū)別? PHP中==(鬆散比較)和===(嚴(yán)格的比較)之間有什麼區(qū)別? Jun 19, 2025 am 01:07 AM

在PHP中,==與===的主要區(qū)別在於類型檢查的嚴(yán)格程度。 ==在比較前會進(jìn)行類型轉(zhuǎn)換,例如5=="5"返回true,而===要求值和類型都相同才會返回true,例如5==="5"返回false。使用場景上,===更安全應(yīng)優(yōu)先使用,==僅在需要類型轉(zhuǎn)換時使用。

如何在PHP( - , *, /,%)中執(zhí)行算術(shù)操作? 如何在PHP( - , *, /,%)中執(zhí)行算術(shù)操作? Jun 19, 2025 pm 05:13 PM

PHP中使用基本數(shù)學(xué)運算的方法如下:1.加法用 號,支持整數(shù)和浮點數(shù),也可用於變量,字符串?dāng)?shù)字會自動轉(zhuǎn)換但不推薦依賴;2.減法用-號,變量同理,類型轉(zhuǎn)換同樣適用;3.乘法用*號,適用於數(shù)字及類似字符串;4.除法用/號,需避免除以零,並註意結(jié)果可能是浮點數(shù);5.取模用%號,可用於判斷奇偶數(shù),處理負(fù)數(shù)時餘數(shù)符號與被除數(shù)一致。正確使用這些運算符的關(guān)鍵在於確保數(shù)據(jù)類型清晰並處理好邊界情況。

如何與PHP的NOSQL數(shù)據(jù)庫(例如MongoDB,Redis)進(jìn)行交互? 如何與PHP的NOSQL數(shù)據(jù)庫(例如MongoDB,Redis)進(jìn)行交互? Jun 19, 2025 am 01:07 AM

是的,PHP可以通過特定擴展或庫與MongoDB和Redis等NoSQL數(shù)據(jù)庫交互。首先,使用MongoDBPHP驅(qū)動(通過PECL或Composer安裝)創(chuàng)建客戶端實例並操作數(shù)據(jù)庫及集合,支持插入、查詢、聚合等操作;其次,使用Predis庫或phpredis擴展連接Redis,執(zhí)行鍵值設(shè)置與獲取,推薦phpredis用於高性能場景,Predis則便於快速部署;兩者均適用於生產(chǎn)環(huán)境且文檔完善。

我如何了解最新的PHP開發(fā)和最佳實踐? 我如何了解最新的PHP開發(fā)和最佳實踐? Jun 23, 2025 am 12:56 AM

TostaycurrentwithPHPdevelopmentsandbestpractices,followkeynewssourceslikePHP.netandPHPWeekly,engagewithcommunitiesonforumsandconferences,keeptoolingupdatedandgraduallyadoptnewfeatures,andreadorcontributetoopensourceprojects.First,followreliablesource

什麼是PHP,為什麼它用於Web開發(fā)? 什麼是PHP,為什麼它用於Web開發(fā)? Jun 23, 2025 am 12:55 AM

PHPbecamepopularforwebdevelopmentduetoitseaseoflearning,seamlessintegrationwithHTML,widespreadhostingsupport,andalargeecosystemincludingframeworkslikeLaravelandCMSplatformslikeWordPress.Itexcelsinhandlingformsubmissions,managingusersessions,interacti

如何設(shè)置PHP時區(qū)? 如何設(shè)置PHP時區(qū)? Jun 25, 2025 am 01:00 AM

tosetTherightTimeZoneInphp,restate_default_timezone_set()functionAtthestArtofyourscriptWithavalIdidentIdentifiersuchas'america/new_york'.1.usedate_default_default_timezone_set_set()

See all articles