搜尋
首頁後端開發php教程編寫高品質的測試

Writing high quality tests

不幸的是,測試在許多組織中仍然沒有得到應有的關注。有時,如果開發人員沒有編寫任何測試,他們會感到內疚,同時測試程式碼往往沒有得到適當的審查。相反,評論中經常檢查的唯一事情是是否有任何測試,這是一種恥辱,因為僅僅進行測試還不夠好。實際上,它們至少應該與專案中的所有其他程式碼具有相同的質量,即使不是更高的品質。否則,測試確實可能會阻礙您,因為測試失敗的次數太多,難以理解,或者運行時間太長。我已經在關於使用記憶體中實作而不是儲存庫模擬的部落格文章中討論了其中的一些要點。現在我想討論一些其他的、更一般的、我在寫測試時要注意的事情。

極簡主義是關鍵

Stack Overflow 要求您為問題添加最少的、可重現的範例,在我看來,這對於出於完全相同的原因編寫測試也是非常好的建議。尤其是在編寫測試幾個月後閱讀測驗時,如果發生的事情較少,就更容易完全理解正在發生的事情。因此只編寫測試絕對必要的程式碼,並抵制僅僅因為這樣做很容易就添加更多內容的誘惑。但測試程式碼當然仍然必須完整,即測試應包含盡可能多的行,但盡可能少。

追求 100% 的程式碼覆蓋率

這可能是一個不受歡迎的觀點,但我認為以 100% 程式碼覆蓋率為目標是完全有意義的,儘管許多人似乎認為這是一種不好的做法。

有時團隊會選擇較低的值,例如程式碼覆蓋率達到 90%。然而,這對我來說沒有多大意義。首先,所有這些數字都有些隨意,很難使用資料進行備份。此外,在編寫新程式碼時,並非所有程式碼都需要經過測試才能通過該閾值。如果有人設法提高了覆蓋率,那麼下一個人可能根本不編寫任何測試,同時仍然保持高於 90% 的程式碼覆蓋率,這會導致錯誤的自信感。

我經常聽到的藉口之一是為 getter 和 setter 等簡單函數編寫測試沒有意義。也許令人驚訝的是,我完全同意這一點。但這裡有一個問題:如果沒有一個測試真正使用這些 getter 和 setter,那麼可能就沒有必要使用它們。 因此,與其抱怨實現 100% 測試覆蓋率有多麼困難,最好不要先編寫不需要的程式碼。這也避免了每行程式碼帶來的維護負擔。

但是,有一個小問題:有時程式碼會執行奇怪的操作,這可能會導致程式碼覆蓋工具將某些行標記為未覆蓋,即使它是在測試運行期間執行的。我沒有經常遇到這樣的情況,但如果沒有辦法使這項工作正常進行,我會將它們排除在程式碼覆蓋範圍之外。例如。 PHPUnit 允許使用他們的 codeCoverageIgnore 註解來做到這一點:

<?php class SomeClass
{
    /**
     * @codeCoverageIgnore
     */
    public function doSomethingNotDetectedAsCovered()
    {

    }
}

這樣這個函數就不會被包含在程式碼覆蓋率分析中,這意味著仍然有可能達到 100% 的程式碼覆蓋率,而且我也會不斷檢查該值。另一種方法是選擇低於 100% 的值,但這樣會出現上面提到的相同問題:其他程式碼也可能不會被測試覆蓋,並且可能會被遺漏。

話雖如此,100% 的程式碼覆蓋率當然不能保證您的程式碼沒有任何錯誤。但是,如果您的應用程式程式碼中確實有未覆蓋的行,您甚至不會對測試進行更改以發現該行中的潛在錯誤。

寫出好的斷言

寫測試的原因是我們想要斷言程式碼的某種行為。因此斷言是測試中非常重要的一部分。

當然,編寫斷言時最重要的考慮因素是它正確地測試程式碼的行為。但緊隨其後的是程式碼失敗時斷言的行為方式。如果斷言由於某種原因失敗,那麼問題對於開發人員來說應該盡可能明顯。在此 Symfony 拉取請求中目前正在處理的情況就是這種情況顯而易見的情況。 Symfony 附帶了一個assertResponseStatusCodeSame 方法,它允許在功能測試中檢查回應的狀態碼:

<?php declare(strict_types=1);

class LoginControllerTest extends WebTestCase
{
    public function testFormAttributes(): void
    {
        $client = static::createClient();

        $client->request('GET', '/login');
        $this->assertResponseStatusCodeSame(200);

        $this->assertSelectorCount(1, 'input[name="email"][required]');
    }
}

這個測試的​​問題是它在狀態碼不是 200 的情況下產生的輸出。由於測試通常在開發環境中運行,因此當訪問這個 URL 時 Symfony 將傳回一個錯誤頁面,並且assertResponseStatusCodeSame 方法將輸出斷言失敗時的完整回應。這個輸出非常長,因為它不僅返回 HTML,還返回 CSS 和 JavaScript,而且我的回滾緩衝區實際上太小,無法讓我閱讀整個訊息。

這絕對是我迄今為止遇到的最糟糕的例子,但如果程式碼中使用了錯誤的斷言,它也會很煩人。讓我們來看看上面的assertSelectorCount斷言的輸出,如果給定的選擇器沒有恰好產生一個元素,則該斷言會失敗並顯示以下訊息:

Failed asserting that the Crawler selector "input[name="email"][required]" was expected to be found 1 time(s) but was found 0 time(s).

它很好地了解了發生的問題。但是,斷言也可以用不同的方式編寫(不要在家裡這樣做!):

<?php class SomeClass
{
    /**
     * @codeCoverageIgnore
     */
    public function doSomethingNotDetectedAsCovered()
    {

    }
}

有人可能會說這完全一樣,因此使用哪種變體並不重要。這與事實相差甚遠,因為如果電子郵件沒有單一必填輸入字段,則會出現以下訊息:

<?php declare(strict_types=1);

class LoginControllerTest extends WebTestCase
{
    public function testFormAttributes(): void
    {
        $client = static::createClient();

        $client->request('GET', '/login');
        $this->assertResponseStatusCodeSame(200);

        $this->assertSelectorCount(1, 'input[name="email"][required]');
    }
}

這根本沒有幫助,無論誰致力於解決問題,首先都必須弄清楚問題到底是什麼。這表明,始終應該使用合適的斷言,並且 PHPUnit 附帶了許多適合所有類型用例的斷言。有時創建自訂斷言甚至是有意義的。

近年來我看到越來越流行的一個相對較新的斷言是快照測試。尤其是當開始從事前端專案時,它似乎有很大幫助。我過去經常將它與 React 一起使用。主要要點是您的測試看起來像這樣:

Failed asserting that the Crawler selector "input[name="email"][required]" was expected to be found 1 time(s) but was found 0 time(s).

神奇的事情發生在 toMatchSnapshot 方法中。在第一次運行時,它將樹變數的內容寫入單獨的檔案中。在後續運行中,它將樹值的新值與先前儲存在單獨檔案中的值進行比較。如果某些內容發生更改,它將導致測試失敗並顯示差異,並可以選擇再次更新快照,這意味著您可以立即修復測試。

雖然這聽起來確實不錯,但它也有一些缺點。首先,快照非常脆弱,因為每當元件的渲染標記發生變更時,測試就會失敗。其次,測試的意圖是隱藏的,因為它沒有解釋作者真正想要測試的內容。

但是,我真正喜歡它的是,每當我更改組件時,它都會提醒我使用該組件的所有其他組件,因為所有這些快照在下次運行時都會失敗。出於這個原因,我喜歡每個組件至少進行一次快照測試。

結論

總而言之,我認為您可以立即開始做一些事情來提高測試品質:

  • 將測試中的程式碼保持在絕對需要的最低限度
  • 目標是 100% 的程式碼覆蓋率,如果無法測試,請正確地將程式碼從程式碼覆蓋率機制中排除
  • 當測試失敗時,使用正確的斷言以獲得更好的錯誤訊息

在我看來,遵循這幾條規則已經會產生巨大的影響,並幫助您長時間享受在程式碼庫中工作!

以上是編寫高品質的測試的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
高流量網站的PHP性能調整高流量網站的PHP性能調整May 14, 2025 am 12:13 AM

TheSecretTokeEpingAphp-PowerEdwebSiterUnningSmoothlyShyunderHeavyLoadInVolvOLVOLVOLDEVERSALKEYSTRATICES:1)emplactopCodeCachingWithOpcachingWithOpCacheToreCescriptexecution Time,2)使用atabasequercachingCachingCachingWithRedataBasEndataBaseLeSendataBaseLoad,3)

PHP中的依賴注入:初學者的代碼示例PHP中的依賴注入:初學者的代碼示例May 14, 2025 am 12:08 AM

你應該關心DependencyInjection(DI),因為它能讓你的代碼更清晰、更易維護。 1)DI通過解耦類,使其更模塊化,2)提高了測試的便捷性和代碼的靈活性,3)使用DI容器可以管理複雜的依賴關係,但要注意性能影響和循環依賴問題,4)最佳實踐是依賴於抽象接口,實現鬆散耦合。

PHP性能:是否可以優化應用程序?PHP性能:是否可以優化應用程序?May 14, 2025 am 12:04 AM

是的,優化papplicationispossibleandessential.1)empartcachingingcachingusedapcutorediucedsatabaseload.2)優化的atabaseswithexing,高效Quereteries,and ConconnectionPooling.3)EnhanceCodeWithBuilt-unctions,避免使用,避免使用ingglobalalairaiables,並避免使用

PHP性能優化:最終指南PHP性能優化:最終指南May 14, 2025 am 12:02 AM

theKeyStrategiestosigantificallyBoostPhpaPplicationPerformenCeare:1)UseOpCodeCachingLikeLikeLikeLikeLikeCacheToreDuceExecutiontime,2)優化AtabaseInteractionswithPreparedStateTementStatementStatementAndProperIndexing,3)配置

PHP依賴注入容器:快速啟動PHP依賴注入容器:快速啟動May 13, 2025 am 12:11 AM

aphpdepentioncontiveContainerIsatoolThatManagesClassDeptions,增強codemodocultion,可驗證性和Maintainability.itactsasaceCentralHubForeatingingIndections,因此reducingTightCightTightCoupOulplingIndeSingantInting。

PHP中的依賴注入與服務定位器PHP中的依賴注入與服務定位器May 13, 2025 am 12:10 AM

選擇DependencyInjection(DI)用於大型應用,ServiceLocator適合小型項目或原型。 1)DI通過構造函數注入依賴,提高代碼的測試性和模塊化。 2)ServiceLocator通過中心註冊獲取服務,方便但可能導致代碼耦合度增加。

PHP性能優化策略。PHP性能優化策略。May 13, 2025 am 12:06 AM

phpapplicationscanbeoptimizedForsPeedAndeffificeby:1)啟用cacheInphp.ini,2)使用preparedStatatementSwithPdoforDatabasequesies,3)3)替換loopswitharray_filtaray_filteraray_maparray_mapfordataprocrocessing,4)conformentnginxasaseproxy,5)

PHP電子郵件驗證:確保正確發送電子郵件PHP電子郵件驗證:確保正確發送電子郵件May 13, 2025 am 12:06 AM

phpemailvalidation invoLvesthreesteps:1)格式化進行regulareXpressecthemailFormat; 2)dnsvalidationtoshethedomainhasavalidmxrecord; 3)

See all articles

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

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

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

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

熱門文章

熱工具

SublimeText3 Mac版

SublimeText3 Mac版

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

SecLists

SecLists

SecLists是最終安全測試人員的伙伴。它是一個包含各種類型清單的集合,這些清單在安全評估過程中經常使用,而且都在一個地方。 SecLists透過方便地提供安全測試人員可能需要的所有列表,幫助提高安全測試的效率和生產力。清單類型包括使用者名稱、密碼、URL、模糊測試有效載荷、敏感資料模式、Web shell等等。測試人員只需將此儲存庫拉到新的測試機上,他就可以存取所需的每種類型的清單。

SAP NetWeaver Server Adapter for Eclipse

SAP NetWeaver Server Adapter for Eclipse

將Eclipse與SAP NetWeaver應用伺服器整合。

DVWA

DVWA

Damn Vulnerable Web App (DVWA) 是一個PHP/MySQL的Web應用程序,非常容易受到攻擊。它的主要目標是成為安全專業人員在合法環境中測試自己的技能和工具的輔助工具,幫助Web開發人員更好地理解保護網路應用程式的過程,並幫助教師/學生在課堂環境中教授/學習Web應用程式安全性。 DVWA的目標是透過簡單直接的介面練習一些最常見的Web漏洞,難度各不相同。請注意,該軟體中

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具