{"id":48508,"date":"2024-12-02T10:38:33","date_gmt":"2024-12-02T02:38:33","guid":{"rendered":"https:\/\/fwq.ai\/blog\/48508\/"},"modified":"2024-12-02T10:38:33","modified_gmt":"2024-12-02T02:38:33","slug":"%e9%9b%86%e6%88%90%e6%b5%8b%e8%af%95%e4%b8%ad%e7%9a%84-php-%e5%87%bd%e6%95%b0%e4%bb%a3%e7%a0%81%e8%a6%86%e7%9b%96%e7%8e%87","status":"publish","type":"post","link":"https:\/\/fwq.ai\/blog\/48508\/","title":{"rendered":"\u96c6\u6210\u6d4b\u8bd5\u4e2d\u7684 PHP \u51fd\u6570\u4ee3\u7801\u8986\u76d6\u7387"},"content":{"rendered":"<p><b><\/b> <\/p>\n<h1>\u96c6\u6210\u6d4b\u8bd5\u4e2d\u7684 PHP \u51fd\u6570\u4ee3\u7801\u8986\u76d6\u7387<\/h1>\n<p>\u6700\u8fd1\u53d1\u73b0\u4e0d\u5c11\u5c0f\u4f19\u4f34\u90fd\u5bf9<span style=\"color: #FF6600;, Helvetica, Arial, sans-serif;font-size: 14px;background-color: #FFFFFF\">\u6587\u7ae0<\/span>\u5f88\u611f\u5174\u8da3\uff0c\u6240\u4ee5\u4eca\u5929\u7ee7\u7eed\u7ed9\u5927\u5bb6\u4ecb\u7ecd<span style=\"color: #FF6600;, Helvetica, Arial, sans-serif;font-size: 14px;background-color: #FFFFFF\">\u6587\u7ae0<\/span>\u76f8\u5173\u7684\u77e5\u8bc6\uff0c\u672c\u6587<span style=\"color: #FF6600;, Helvetica, Arial, sans-serif;font-size: 14px;background-color: #FFFFFF\">\u300a\u96c6\u6210\u6d4b\u8bd5\u4e2d\u7684 PHP \u51fd\u6570\u4ee3\u7801\u8986\u76d6\u7387\u300b<\/span>\u4e3b\u8981\u5185\u5bb9\u6d89\u53ca\u5230<span style=\"color: #FF6600;, Helvetica, Arial, sans-serif;font-size: 14px;background-color: #FFFFFF\"><\/span>\u7b49\u7b49\u77e5\u8bc6\u70b9\uff0c\u5e0c\u671b\u80fd\u5e2e\u5230\u4f60\uff01\u5f53\u7136\u5982\u679c\u9605\u8bfb\u672c\u6587\u65f6\u5b58\u5728\u4e0d\u540c\u60f3\u6cd5\uff0c\u53ef\u4ee5\u5728\u8bc4\u8bba\u4e2d\u8868\u8fbe\uff0c\u4f46\u662f\u8bf7\u52ff\u4f7f\u7528\u8fc7\u6fc0\u7684\u63aa\u8f9e~<\/p>\n<p>\u96c6\u6210\u6d4b\u8bd5\u4e2d\u7684 PHP \u51fd\u6570\u4ee3\u7801\u8986\u76d6\u7387\u4f7f\u7528 PHPUnit\uff081\uff09\u548c XDebug\uff082\uff09\u6765\u6d4b\u91cf\u6bcf\u4e2a\u51fd\u6570\u7684\u4ee3\u7801\u8986\u76d6\u7387\uff083\uff09\uff0c\u6709\u52a9\u4e8e\u6807\u8bc6\u672a\u6d4b\u8bd5\u7684\u4ee3\u7801\u8def\u5f84\uff084\uff09\uff0c\u63d0\u9ad8\u6d4b\u8bd5\u4fe1\u5fc3\uff085\uff09\u3002\u53ef\u4ee5\u901a\u8fc7\u914d\u7f6e php.ini\uff086\uff09\u548c\u5728\u6d4b\u8bd5\u4e2d\u4f7f\u7528 XHProf \u9a71\u52a8\u7a0b\u5e8f\uff087\uff09\u6765\u542f\u7528\u4ee3\u7801\u8986\u76d6\u7387\uff088\uff09\u3002\u5b9e\u6218\u6848\u4f8b\u5c55\u793a\u4e86\u5982\u4f55\u6d4b\u8bd5\u51fd\u6570\u5e76\u6d4b\u91cf\u5176\u4ee3\u7801\u8986\u76d6\u7387\uff089\uff09\uff0c\u4ece\u800c\u751f\u6210\u663e\u793a\u6267\u884c\u4ee3\u7801\u884c\u7684\u8986\u76d6\u7387\u62a5\u544a\uff0810\uff09\u3002<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/www.17golang.com\/uploads\/20241027\/1730039495671e4ec705dae.jpg\" class=\"aligncenter\" title=\"\u96c6\u6210\u6d4b\u8bd5\u4e2d\u7684 PHP \u51fd\u6570\u4ee3\u7801\u8986\u76d6\u7387\u63d2\u56fe\" alt=\"\u96c6\u6210\u6d4b\u8bd5\u4e2d\u7684 PHP \u51fd\u6570\u4ee3\u7801\u8986\u76d6\u7387\u63d2\u56fe\" \/><\/p>\n<p><strong>\u96c6\u6210\u6d4b\u8bd5\u4e2d\u7684 PHP \u51fd\u6570\u4ee3\u7801\u8986\u76d6\u7387<\/strong><\/p>\n<p><strong>\u7b80\u4ecb<\/strong><\/p>\n<p>\u96c6\u6210\u6d4b\u8bd5\u662f\u786e\u4fdd\u5e94\u7528\u7a0b\u5e8f\u4e0d\u540c\u6a21\u5757\u534f\u540c\u5de5\u4f5c\u7684\u5173\u952e\u3002PHP \u4e2d\uff0c\u6211\u4eec\u53ef\u4ee5\u4f7f\u7528 PHPUnit \u6846\u67b6\u8fdb\u884c\u96c6\u6210\u6d4b\u8bd5\uff0c\u5e76\u4f7f\u7528 XDebug \u6269\u5c55\u6765\u6d4b\u91cf\u6bcf\u4e2a\u51fd\u6570\u7684\u4ee3\u7801\u8986\u76d6\u7387\u3002<\/p>\n<p><strong>\u4ee3\u7801\u8986\u76d6\u7387\u6982\u8ff0<\/strong><\/p>\n<p>\u4ee3\u7801\u8986\u76d6\u7387\u662f\u4e00\u79cd\u5ea6\u91cf\u6807\u51c6\uff0c\u7528\u4e8e\u8861\u91cf\u4ee3\u7801\u7684\u54ea\u4e9b\u90e8\u5206\u5df2\u5728\u6d4b\u8bd5\u4e2d\u6267\u884c\u3002\u5b83\u6709\u52a9\u4e8e\u6807\u8bc6\u672a\u6d4b\u8bd5\u7684\u4ee3\u7801\u8def\u5f84\uff0c\u5e76\u63d0\u9ad8\u6d4b\u8bd5\u7684\u4fe1\u5fc3\u3002<\/p>\n<p><strong>XDebug \u4f7f\u7528<\/strong><\/p>\n<p>\u8981\u83b7\u5f97\u51fd\u6570\u4ee3\u7801\u8986\u76d6\u7387\uff0c\u6211\u4eec\u9700\u8981\u542f\u7528 XDebug \u6269\u5c55\u5e76\u914d\u7f6e\u5b83\u6765\u8bb0\u5f55\u8986\u76d6\u7387\u6570\u636e\u3002\u4ee5\u4e0b\u4e3a php.ini \u914d\u7f6e\u6587\u4ef6\u4e2d\u7684\u793a\u4f8b\u914d\u7f6e\uff1a<\/p>\n<pre>zend_extension=xdebug.so\n\nxdebug.coverage_enable=1\nxdebug.coverage_output_dir=\/tmp\/coverage<\/pre>\n<p><strong>\u4ee3\u7801\u793a\u4f8b<\/strong><\/p>\n<p>\u6211\u4eec\u521b\u5efa\u4e00\u4e2a\u793a\u4f8b\u96c6\u6210\u6d4b\u8bd5\uff0c\u5e76\u4f7f\u7528 XDebug \u6d4b\u91cf\u51fd\u6570\u4ee3\u7801\u8986\u76d6\u7387\uff1a<\/p>\n<pre>use PHPUnit\\Framework\\TestCase;\nuse XDebug\\CodeCoverage\\Driver\\XHProf;\n\nclass IntegrationTest extends TestCase\n{\n    public function testFunctionCoverage()\n    {\n        $driver = new XHProf();\n        $driver-&gt;start();\n\n        \/\/ \u8fd0\u884c\u88ab\u6d4b\u8bd5\u7684\u4ee3\u7801\n\n        $coverageData = $driver-&gt;stop();\n        file_put_contents('\/tmp\/coverage.xhprof', serialize($coverageData));\n\n        \/\/ \u65ad\u8a00\u51fd\u6570\u4ee3\u7801\u8986\u76d6\u7387\n        $this-&gt;assertGreaterThan(0, $coverageData['functions']['myFunction']['executed_lines']);\n    }\n}<\/pre>\n<p><strong>\u5b9e\u6218\u6848\u4f8b<\/strong><\/p>\n<p>Consider the following PHP code:<\/p>\n<pre>function sum(int $a, int $b): int\n{\n    if ($a &lt; 0 || $b &lt; 0) {\n        throw new Exception('Invalid numbers for sum');\n    }\n\n    return $a + $b;\n}<\/pre>\n<p>To test the <code>sum<\/code> function and measure its code coverage, we can create an integration test as follows:<\/p>\n<pre>use PHPUnit\\Framework\\TestCase;\nuse XDebug\\CodeCoverage\\Driver\\XHProf;\n\nclass SumIntegrationTest extends TestCase\n{\n    public function testPositiveNumbers()\n    {\n        $driver = new XHProf();\n        $driver-&gt;start();\n\n        $sum = sum(1, 2);\n\n        $coverageData = $driver-&gt;stop();\n        file_put_contents('\/tmp\/coverage.xhprof', serialize($coverageData));\n\n        $this-&gt;assertEquals(3, $sum);\n        $this-&gt;assertGreaterThan(0, $coverageData['functions']['sum']['executed_lines']);\n    }\n\n    public function testNegativeNumbers()\n    {\n        $driver = new XHProf();\n        $driver-&gt;start();\n\n        try {\n            $sum = sum(-1, -2);\n            $this-&gt;fail('Expected Exception was not thrown.');\n        } catch (Exception $e) {\n            $coverageData = $driver-&gt;stop();\n            file_put_contents('\/tmp\/coverage.xhprof', serialize($coverageData));\n        }\n\n        $this-&gt;assertGreaterThan(0, $coverageData['functions']['sum']['executed_lines']);\n    }\n}<\/pre>\n<p>In this test:<\/p>\n<ul>\n<li>The <code>testPositiveNumbers<\/code> method exercises the <code>sum<\/code> function with positive numbers and asserts the correct result. It also verifies that the function code was executed.<\/li>\n<li>The <code>testNegativeNumbers<\/code> method exercises the <code>sum<\/code> function with negative numbers and asserts that the expected exception is thrown. It also verifies that the function code was executed.<\/li>\n<\/ul>\n<p>By running the tests, we can generate the coverage report, which shows the lines of code that were executed during the tests. This information can be used to identify untested code paths and improve the coverage of the integration tests.<\/p>\n<p>\u5230\u8fd9\u91cc\uff0c\u6211\u4eec\u4e5f\u5c31\u8bb2\u5b8c\u4e86\u300a\u96c6\u6210\u6d4b\u8bd5\u4e2d\u7684 PHP \u51fd\u6570\u4ee3\u7801\u8986\u76d6\u7387\u300b\u7684\u5185\u5bb9\u4e86\u3002\u4e2a\u4eba\u8ba4\u4e3a\uff0c\u57fa\u7840\u77e5\u8bc6\u7684\u5b66\u4e60\u548c\u5de9\u56fa\uff0c\u662f\u4e3a\u4e86\u66f4\u597d\u7684\u5c06\u5176\u8fd0\u7528\u5230\u9879\u76ee\u4e2d\uff0c\u6b22\u8fce\u5173\u6ce8\u7c73\u4e91\u516c\u4f17\u53f7\uff0c\u5e26\u4f60\u4e86\u89e3\u66f4\u591a\u5173\u4e8ephp,\u4ee3\u7801\u8986\u76d6\u7387\u7684\u77e5\u8bc6\u70b9\uff01<\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u96c6\u6210\u6d4b\u8bd5\u4e2d\u7684 PHP \u51fd\u6570\u4ee3\u7801\u8986\u76d6\u7387 \u6700\u8fd1\u53d1\u73b0\u4e0d\u5c11\u5c0f\u4f19\u4f34\u90fd\u5bf9\u6587\u7ae0\u5f88\u611f\u5174\u8da3\uff0c\u6240\u4ee5\u4eca\u5929\u7ee7\u7eed\u7ed9\u5927\u5bb6\u4ecb\u7ecd\u6587\u7ae0\u76f8\u5173\u7684\u77e5\u8bc6\uff0c\u672c\u6587\u300a\u96c6\u6210\u6d4b\u8bd5\u4e2d\u7684 PHP \u51fd\u6570\u4ee3\u7801\u8986\u76d6\u7387\u300b\u4e3b\u8981\u5185\u5bb9\u6d89\u53ca\u5230\u7b49\u7b49\u77e5\u8bc6\u70b9\uff0c\u5e0c\u671b\u80fd\u5e2e\u5230\u4f60\uff01\u5f53\u7136\u5982\u679c\u9605\u8bfb\u672c\u6587\u65f6\u5b58\u5728\u4e0d\u540c\u60f3\u6cd5\uff0c\u53ef\u4ee5\u5728\u8bc4\u8bba\u4e2d\u8868\u8fbe\uff0c\u4f46\u662f\u8bf7\u52ff\u4f7f\u7528\u8fc7\u6fc0\u7684\u63aa\u8f9e~ \u96c6\u6210\u6d4b\u8bd5\u4e2d\u7684 PHP \u51fd\u6570\u4ee3\u7801\u8986\u76d6\u7387\u4f7f\u7528 PHPUnit\uff081\uff09\u548c XDebug\uff082\uff09\u6765\u6d4b\u91cf\u6bcf\u4e2a\u51fd\u6570\u7684\u4ee3\u7801\u8986\u76d6\u7387\uff083\uff09\uff0c\u6709\u52a9\u4e8e\u6807\u8bc6\u672a\u6d4b\u8bd5\u7684\u4ee3\u7801\u8def\u5f84\uff084\uff09\uff0c\u63d0\u9ad8\u6d4b\u8bd5\u4fe1\u5fc3\uff085\uff09\u3002\u53ef\u4ee5\u901a\u8fc7\u914d\u7f6e php.ini\uff086\uff09\u548c\u5728\u6d4b\u8bd5\u4e2d\u4f7f\u7528 XHProf \u9a71\u52a8\u7a0b\u5e8f\uff087\uff09\u6765\u542f\u7528\u4ee3\u7801\u8986\u76d6\u7387\uff088\uff09\u3002\u5b9e\u6218\u6848\u4f8b\u5c55\u793a\u4e86\u5982\u4f55\u6d4b\u8bd5\u51fd\u6570\u5e76\u6d4b\u91cf\u5176\u4ee3\u7801\u8986\u76d6\u7387\uff089\uff09\uff0c\u4ece\u800c\u751f\u6210\u663e\u793a\u6267\u884c\u4ee3\u7801\u884c\u7684\u8986\u76d6\u7387\u62a5\u544a\uff0810\uff09\u3002 \u96c6\u6210\u6d4b\u8bd5\u4e2d\u7684 PHP \u51fd\u6570\u4ee3\u7801\u8986\u76d6\u7387 \u7b80\u4ecb \u96c6\u6210\u6d4b\u8bd5\u662f\u786e\u4fdd\u5e94\u7528\u7a0b\u5e8f\u4e0d\u540c\u6a21\u5757\u534f\u540c\u5de5\u4f5c\u7684\u5173\u952e\u3002PHP \u4e2d\uff0c\u6211\u4eec\u53ef\u4ee5\u4f7f\u7528 PHPUnit \u6846\u67b6\u8fdb\u884c\u96c6\u6210\u6d4b\u8bd5\uff0c\u5e76\u4f7f\u7528 XDebug \u6269\u5c55\u6765\u6d4b\u91cf\u6bcf\u4e2a\u51fd\u6570\u7684\u4ee3\u7801\u8986\u76d6\u7387\u3002 \u4ee3\u7801\u8986\u76d6\u7387\u6982\u8ff0 \u4ee3\u7801\u8986\u76d6\u7387\u662f\u4e00\u79cd\u5ea6\u91cf\u6807\u51c6\uff0c\u7528\u4e8e\u8861\u91cf\u4ee3\u7801\u7684\u54ea\u4e9b\u90e8\u5206\u5df2\u5728\u6d4b\u8bd5\u4e2d\u6267\u884c\u3002\u5b83\u6709\u52a9\u4e8e\u6807\u8bc6\u672a\u6d4b\u8bd5\u7684\u4ee3\u7801\u8def\u5f84\uff0c\u5e76\u63d0\u9ad8\u6d4b\u8bd5\u7684\u4fe1\u5fc3\u3002 XDebug \u4f7f\u7528 \u8981\u83b7\u5f97\u51fd\u6570\u4ee3\u7801\u8986\u76d6\u7387\uff0c\u6211\u4eec\u9700\u8981\u542f\u7528 XDebug \u6269\u5c55\u5e76\u914d\u7f6e\u5b83\u6765\u8bb0\u5f55\u8986\u76d6\u7387\u6570\u636e\u3002\u4ee5\u4e0b\u4e3a php.ini \u914d\u7f6e\u6587\u4ef6\u4e2d\u7684\u793a\u4f8b\u914d\u7f6e\uff1a zend_extension=xdebug.so xdebug.coverage_enable=1 xdebug.coverage_output_dir=\/tmp\/coverage \u4ee3\u7801\u793a\u4f8b \u6211\u4eec\u521b\u5efa\u4e00\u4e2a\u793a\u4f8b\u96c6\u6210\u6d4b\u8bd5\uff0c\u5e76\u4f7f\u7528 XDebug \u6d4b\u91cf\u51fd\u6570\u4ee3\u7801\u8986\u76d6\u7387\uff1a use PHPUnit\\Framework\\TestCase; use XDebug\\CodeCoverage\\Driver\\XHProf; class IntegrationTest extends TestCase { public function testFunctionCoverage() { $driver = [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[16],"tags":[],"class_list":["post-48508","post","type-post","status-publish","format-standard","hentry","category-16"],"_links":{"self":[{"href":"https:\/\/fwq.ai\/blog\/wp-json\/wp\/v2\/posts\/48508","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/fwq.ai\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/fwq.ai\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/fwq.ai\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/fwq.ai\/blog\/wp-json\/wp\/v2\/comments?post=48508"}],"version-history":[{"count":0,"href":"https:\/\/fwq.ai\/blog\/wp-json\/wp\/v2\/posts\/48508\/revisions"}],"wp:attachment":[{"href":"https:\/\/fwq.ai\/blog\/wp-json\/wp\/v2\/media?parent=48508"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/fwq.ai\/blog\/wp-json\/wp\/v2\/categories?post=48508"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/fwq.ai\/blog\/wp-json\/wp\/v2\/tags?post=48508"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}