{"id":2460,"date":"2025-03-24T08:47:13","date_gmt":"2025-03-23T23:47:13","guid":{"rendered":"https:\/\/dexall.co.jp\/articles\/?p=2460"},"modified":"2025-03-24T08:47:44","modified_gmt":"2025-03-23T23:47:44","slug":"phpunit%e5%ae%8c%e5%85%a8%e3%82%ac%e3%82%a4%e3%83%89%ef%bc%9a%e5%ae%9f%e8%b7%b5%e3%81%a7%e4%bd%bf%e3%81%88%e3%82%8b7%e3%81%a4%e3%81%ae%e3%83%86%e3%82%b9%e3%83%88%e6%89%8b%e6%b3%95%e3%81%a8%e8%a8%ad","status":"publish","type":"post","link":"https:\/\/dexall.co.jp\/articles\/?p=2460","title":{"rendered":"PHPUnit\u5b8c\u5168\u30ac\u30a4\u30c9\uff1a\u5b9f\u8df5\u3067\u4f7f\u3048\u308b7\u3064\u306e\u30c6\u30b9\u30c8\u624b\u6cd5\u3068\u8a2d\u5b9a\u306e\u30d9\u30b9\u30c8\u30d7\u30e9\u30af\u30c6\u30a3\u30b9\u30102025\u5e74\u7248\u3011"},"content":{"rendered":"\n<div class=\"toc\"><br \/>\n<b>Warning<\/b>:  Undefined array key \"is_admin\" in <b>\/home\/xs392991\/dexall.co.jp\/public_html\/articles\/wp-content\/themes\/sango-theme\/library\/gutenberg\/dist\/classes\/Toc.php<\/b> on line <b>116<\/b><br \/>\n<br \/>\n<b>Warning<\/b>:  Undefined array key \"is_category_top\" in <b>\/home\/xs392991\/dexall.co.jp\/public_html\/articles\/wp-content\/themes\/sango-theme\/library\/gutenberg\/dist\/classes\/Toc.php<\/b> on line <b>121<\/b><br \/>\n<br \/>\n<b>Warning<\/b>:  Undefined array key \"is_top\" in <b>\/home\/xs392991\/dexall.co.jp\/public_html\/articles\/wp-content\/themes\/sango-theme\/library\/gutenberg\/dist\/classes\/Toc.php<\/b> on line <b>128<\/b><br \/>\n    <div id=\"toc_container\" class=\"sgb-toc--bullets js-smooth-scroll\" data-dialog-title=\"\u76ee\u6b21\">\n      <p class=\"toc_title\">\u76ee\u6b21 <\/p>\n      <ul class=\"toc_list\">  <li class=\"first\">    <a href=\"#i-0\">PHPUnit \u3068\u306f\uff1aWeb \u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u306e\u54c1\u8cea\u3092\u652f\u3048\u308b\u30c6\u30b9\u30c8\u30d5\u30ec\u30fc\u30e0\u30ef\u30fc\u30af<\/a>    <ul class=\"menu_level_1\">      <li class=\"first\">        <a href=\"#i-1\">PHPUnit \u304c\u89e3\u6c7a\u3059\u308b3\u3064\u306e\u958b\u767a\u73fe\u5834\u306e\u8ab2\u984c<\/a>      <\/li>      <li class=\"last\">        <a href=\"#i-2\">PHPUnit\u306e\u4e3b\u8981\u6a5f\u80fd\u3068\u7279\u5fb4<\/a>      <\/li>    <\/ul>  <\/li>  <li>    <a href=\"#i-7\">PHPUnit\u74b0\u5883\u69cb\u7bc9\u306e\u5b8c\u5168\u30de\u30cb\u30e5\u30a2\u30eb<\/a>    <ul class=\"menu_level_1\">      <li class=\"first\">        <a href=\"#i-8\">Composer\u3092\u4f7f\u7528\u3057\u305f\u6700\u65b0\u7248\u306e\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u65b9\u6cd5<\/a>      <\/li>      <li>        <a href=\"#i-9\">\u8a2d\u5b9a\u30d5\u30a1\u30a4\u30ebphpunit.xml\u306e\u4f5c\u6210\u3068\u91cd\u8981\u306a\u8a2d\u5b9a\u9805\u76ee<\/a>      <\/li>      <li class=\"last\">        <a href=\"#i-10\">IDE\u3068\u306e\u9023\u643a\u3067\u30c6\u30b9\u30c8\u3092\u52b9\u7387\u5316\u3059\u308b\u65b9\u6cd5<\/a>      <\/li>    <\/ul>  <\/li>  <li>    <a href=\"#i-14\">\u5b9f\u8df5\u3067\u4f7f\u3048\u308b7\u3064\u306ePHPUnit\u30c6\u30b9\u30c8\u624b\u6cd5<\/a>    <ul class=\"menu_level_1\">      <li class=\"first\">        <a href=\"#i-15\">\u57fa\u672c\u7684\u306a\u30a2\u30b5\u30fc\u30b7\u30e7\u30f3\u3092\u4f7f\u7528\u3057\u305f\u30c6\u30b9\u30c8\u30b1\u30fc\u30b9\u4f5c\u6210<\/a>      <\/li>      <li>        <a href=\"#i-16\">\u30e2\u30c3\u30af\u30aa\u30d6\u30b8\u30a7\u30af\u30c8\u3092\u6d3b\u7528\u3057\u305f\u5916\u90e8\u4f9d\u5b58\u306e\u30c6\u30b9\u30c8<\/a>      <\/li>      <li>        <a href=\"#i-17\">\u30c7\u30fc\u30bf\u30d7\u30ed\u30d0\u30a4\u30c0\u30fc\u306b\u3088\u308b\u30d1\u30e9\u30e1\u30fc\u30bf\u5316\u30c6\u30b9\u30c8<\/a>      <\/li>      <li>        <a href=\"#i-18\">\u4f8b\u5916\u51e6\u7406\u306e\u30c6\u30b9\u30c8\u624b\u6cd5<\/a>      <\/li>      <li>        <a href=\"#i-19\">\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u64cd\u4f5c\u306e\u30c6\u30b9\u30c8\u65b9\u6cd5<\/a>      <\/li>      <li>        <a href=\"#i-20\">\u975e\u540c\u671f\u51e6\u7406\u306e\u30c6\u30b9\u30c8\u5b9f\u88c5<\/a>      <\/li>      <li class=\"last\">        <a href=\"#i-21\">\u30d7\u30e9\u30a4\u30d9\u30fc\u30c8\u30e1\u30bd\u30c3\u30c9\u306e\u30c6\u30b9\u30c8\u30c6\u30af\u30cb\u30c3\u30af<\/a>      <\/li>    <\/ul>  <\/li>  <li>    <a href=\"#i-22\">PHPUnit\u30c6\u30b9\u30c8\u306e\u8a2d\u8a08\u30d9\u30b9\u30c8\u30d7\u30e9\u30af\u30c6\u30a3\u30b9<\/a>    <ul class=\"menu_level_1\">      <li class=\"first\">        <a href=\"#i-23\">\u30c6\u30b9\u30c8\u30b1\u30fc\u30b9\u8a2d\u8a08\u306e\u539f\u5247\u3068TDD\u306e\u5b9f\u8df5\u65b9\u6cd5<\/a>      <\/li>      <li>        <a href=\"#i-26\">\u30c6\u30b9\u30c8\u306e\u547d\u540d\u898f\u5247\u3068\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u69cb\u9020\u306e\u6574\u7406<\/a>      <\/li>      <li class=\"last\">        <a href=\"#i-29\">\u30c6\u30b9\u30c8\u30ab\u30d0\u30ec\u30c3\u30b8\u306e\u6e2c\u5b9a\u3068\u6d3b\u7528\u65b9\u6cd5<\/a>      <\/li>    <\/ul>  <\/li>  <li>    <a href=\"#i-33\">CI\/CD\u30d1\u30a4\u30d7\u30e9\u30a4\u30f3\u306b\u304a\u3051\u308bPHPUnit\u306e\u6d3b\u7528\u6cd5<\/a>    <ul class=\"menu_level_1\">      <li class=\"first\">        <a href=\"#i-34\">GitHubActions\u3067\u306e\u81ea\u52d5\u30c6\u30b9\u30c8\u8a2d\u5b9a<\/a>      <\/li>      <li class=\"last\">        <a href=\"#i-37\">Jenkins\u9023\u643a\u306b\u3088\u308b\u30c6\u30b9\u30c8\u81ea\u52d5\u5316\u306e\u5b9f\u73fe<\/a>      <\/li>    <\/ul>  <\/li>  <li>    <a href=\"#i-41\">PHPUnit\u3067\u3088\u304f\u3042\u308b\u30a8\u30e9\u30fc\u3068\u30c8\u30e9\u30d6\u30eb\u30b7\u30e5\u30fc\u30c6\u30a3\u30f3\u30b0<\/a>    <ul class=\"menu_level_1\">      <li class=\"first\">        <a href=\"#i-42\">\u74b0\u5883\u69cb\u7bc9\u6642\u306e\u4e3b\u8981\u306a\u30a8\u30e9\u30fc\u5bfe\u51e6\u6cd5<\/a>      <\/li>      <li>        <a href=\"#i-46\">\u30c6\u30b9\u30c8\u5b9f\u884c\u6642\u306e\u30e1\u30e2\u30ea\u7ba1\u7406\u3068\u30d1\u30d5\u30a9\u30fc\u30de\u30f3\u30b9\u5411\u4e0a<\/a>      <\/li>      <li class=\"last\">        <a href=\"#i-49\">\u975e\u4e92\u63db\u6027\u306e\u89e3\u6c7a\u3068\u30d0\u30fc\u30b8\u30e7\u30f3\u30a2\u30c3\u30d7\u6642\u306e\u6ce8\u610f\u70b9<\/a>      <\/li>    <\/ul>  <\/li>  <li class=\"last\">    <a href=\"#i-54\">\u5b9f\u8df5\u7684\u306aPHPUnit\u30c6\u30b9\u30c8\u30b3\u30fc\u30c9\u4f8b\u3068\u30b5\u30f3\u30d7\u30eb\u30d7\u30ed\u30b8\u30a7\u30af\u30c8<\/a>    <ul class=\"menu_level_1\">      <li class=\"first\">        <a href=\"#i-55\">EC\u30b5\u30a4\u30c8\u306e\u30b7\u30e7\u30c3\u30d4\u30f3\u30b0\u30ab\u30fc\u30c8\u6a5f\u80fd\u306e\u30c6\u30b9\u30c8\u5b9f\u88c5\u4f8b<\/a>      <\/li>      <li>        <a href=\"#i-58\">\u30e6\u30fc\u30b6\u30fc\u8a8d\u8a3c\u30b7\u30b9\u30c6\u30e0\u306e\u30c6\u30b9\u30c8\u30b1\u30fc\u30b9\u4f5c\u6210<\/a>      <\/li>      <li class=\"last\">        <a href=\"#i-61\">API\u30a8\u30f3\u30c9\u30dd\u30a4\u30f3\u30c8\u306e\u30c6\u30b9\u30c8\u5b9f\u88c5\u65b9\u6cd5<\/a>      <\/li>    <\/ul>  <\/li><\/ul>\n      <a href=\"#\" class=\"sgb-toc-button js-toc-button\" rel=\"nofollow\" data-open-dialog=\"true\"><i class=\"fa fa-list\"><\/i><span class=\"sgb-toc-button__text\">\u76ee\u6b21\u3078<\/span><\/a>\n    <\/div><\/div><h2 class=\"wp-block-heading\" id=\"i-0\">PHPUnit \u3068\u306f\uff1aWeb \u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u306e\u54c1\u8cea\u3092\u652f\u3048\u308b\u30c6\u30b9\u30c8\u30d5\u30ec\u30fc\u30e0\u30ef\u30fc\u30af<\/h2>\n\n\n\n<p>PHPUnit\u306f\u3001PHP\u8a00\u8a9e\u7528\u306e\u5358\u4f53\u30c6\u30b9\u30c8\u30d5\u30ec\u30fc\u30e0\u30ef\u30fc\u30af\u3068\u3057\u3066\u6700\u3082\u5e83\u304f\u4f7f\u7528\u3055\u308c\u3066\u3044\u308b\u30c4\u30fc\u30eb\u3067\u3059\u3002Sebastian Bergmann\u306b\u3088\u3063\u3066\u958b\u767a\u3055\u308c\u3001xUnit\u30a2\u30fc\u30ad\u30c6\u30af\u30c1\u30e3\u306b\u57fa\u3065\u3044\u3066\u8a2d\u8a08\u3055\u308c\u3066\u3044\u307e\u3059\u3002\u591a\u304f\u306e\u4e3b\u8981\u306aPHP\u30d7\u30ed\u30b8\u30a7\u30af\u30c8\u3084\u30d5\u30ec\u30fc\u30e0\u30ef\u30fc\u30af\uff08Laravel\u3001Symfony\u3001WordPress\u306a\u3069\uff09\u3067\u63a1\u7528\u3055\u308c\u3066\u304a\u308a\u3001\u4fe1\u983c\u6027\u306e\u9ad8\u3044\u30c6\u30b9\u30c8\u74b0\u5883\u3092\u63d0\u4f9b\u3057\u307e\u3059\u3002<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-1\">PHPUnit \u304c\u89e3\u6c7a\u3059\u308b3\u3064\u306e\u958b\u767a\u73fe\u5834\u306e\u8ab2\u984c<\/h3>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>\u54c1\u8cea\u4fdd\u8a3c\u306e\u52b9\u7387\u5316\u3068\u81ea\u52d5\u5316<\/strong><\/li>\n<\/ol>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u624b\u52d5\u30c6\u30b9\u30c8\u306b\u3088\u308b\u4eba\u7684\u30df\u30b9\u306e\u524a\u6e1b<\/li>\n\n\n\n<li>\u7d99\u7d9a\u7684\u306a\u30ea\u30b0\u30ec\u30c3\u30b7\u30e7\u30f3\u30c6\u30b9\u30c8\u306e\u5b9f\u73fe<\/li>\n\n\n\n<li>\u30c6\u30b9\u30c8\u5b9f\u884c\u6642\u9593\u306e\u5927\u5e45\u306a\u77ed\u7e2e<\/li>\n<\/ul>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">   \/\/ \u5f93\u6765\u306e\u624b\u52d5\u30c6\u30b9\u30c8\n   $result = someFunction();\n   if ($result === expected) {\n       echo \"Test passed\";\n   }\n\n   \/\/ PHPUnit\u3092\u4f7f\u7528\u3057\u305f\u81ea\u52d5\u5316\u30c6\u30b9\u30c8\n   public function testSomeFunction(): void\n   {\n       $this-&gt;assertEquals(expected, someFunction());\n   }<\/pre>\n\n\n\n<ol start=\"2\" class=\"wp-block-list\">\n<li><strong>\u958b\u767a\u901f\u5ea6\u3068\u54c1\u8cea\u306e\u4e21\u7acb<\/strong><\/li>\n<\/ol>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u30c6\u30b9\u30c8\u30d5\u30a1\u30fc\u30b9\u30c8\u306a\u958b\u767a\u30a2\u30d7\u30ed\u30fc\u30c1\u306e\u5b9f\u73fe<\/li>\n\n\n\n<li>\u65e9\u671f\u306e\u30d0\u30b0\u767a\u898b\u306b\u3088\u308b\u4fee\u6b63\u30b3\u30b9\u30c8\u306e\u524a\u6e1b<\/li>\n\n\n\n<li>\u30ea\u30d5\u30a1\u30af\u30bf\u30ea\u30f3\u30b0\u306e\u5b89\u5168\u6027\u78ba\u4fdd<\/li>\n<\/ul>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">   \/\/ \u30c6\u30b9\u30c8\u30d5\u30a1\u30fc\u30b9\u30c8\u306a\u958b\u767a\u4f8b\n   public function testCalculateTotal(): void\n   {\n       $cart = new ShoppingCart();\n       $cart-&gt;addItem(new Product(\"A\", 100), 2);\n       $cart-&gt;addItem(new Product(\"B\", 150), 1);\n\n       $this-&gt;assertEquals(350, $cart-&gt;calculateTotal());\n   }<\/pre>\n\n\n\n<ol start=\"3\" class=\"wp-block-list\">\n<li><strong>\u30c1\u30fc\u30e0\u958b\u767a\u306b\u304a\u3051\u308b\u30b3\u30fc\u30c9\u54c1\u8cea\u306e\u6a19\u6e96\u5316<\/strong><\/li>\n<\/ol>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u7d71\u4e00\u3055\u308c\u305f\u30c6\u30b9\u30c8\u57fa\u6e96\u306e\u78ba\u7acb<\/li>\n\n\n\n<li>\u30b3\u30fc\u30c9\u30ec\u30d3\u30e5\u30fc\u306e\u52b9\u7387\u5316<\/li>\n\n\n\n<li>\u65b0\u898f\u30e1\u30f3\u30d0\u30fc\u306e\u5b66\u7fd2\u66f2\u7dda\u306e\u7de9\u548c<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-2\">PHPUnit\u306e\u4e3b\u8981\u6a5f\u80fd\u3068\u7279\u5fb4<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"i-3\">1. \u8c4a\u5bcc\u306a\u30a2\u30b5\u30fc\u30b7\u30e7\u30f3\u30e1\u30bd\u30c3\u30c9<\/h4>\n\n\n\n<p>PHPUnit\u306f\u3001\u69d8\u3005\u306a\u691c\u8a3c\u30b7\u30ca\u30ea\u30aa\u306b\u5bfe\u5fdc\u3059\u308b\u591a\u69d8\u306a\u30a2\u30b5\u30fc\u30b7\u30e7\u30f3\u30e1\u30bd\u30c3\u30c9\u3092\u63d0\u4f9b\u3057\u307e\u3059\uff1a<\/p>\n\n\n<div id=\"id-bba2e0c7-a025-4f4c-a189-08b09b65cce5\">\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>\u30a2\u30b5\u30fc\u30b7\u30e7\u30f3\u30bf\u30a4\u30d7<\/th><th>\u4e3b\u306a\u7528\u9014<\/th><th>\u4f7f\u7528\u4f8b<\/th><\/tr><\/thead><tbody><tr><td>assertEquals()<\/td><td>\u5024\u306e\u4e00\u81f4\u78ba\u8a8d<\/td><td><code>$this-&gt;assertEquals($expected, $actual);<\/code><\/td><\/tr><tr><td>assertInstanceOf()<\/td><td>\u30aa\u30d6\u30b8\u30a7\u30af\u30c8\u306e\u578b\u78ba\u8a8d<\/td><td><code>$this-&gt;assertInstanceOf(ExpectedClass::class, $object);<\/code><\/td><\/tr><tr><td>assertContains()<\/td><td>\u914d\u5217\u30fb\u6587\u5b57\u5217\u306e\u5305\u542b\u78ba\u8a8d<\/td><td><code>$this-&gt;assertContains($needle, $haystack);<\/code><\/td><\/tr><tr><td>assertNull()<\/td><td>null\u5024\u306e\u78ba\u8a8d<\/td><td><code>$this-&gt;assertNull($value);<\/code><\/td><\/tr><\/tbody><\/table><\/figure>\n<\/div>\n\n\n<h4 class=\"wp-block-heading\" id=\"i-4\">2. \u30e2\u30c3\u30af\u3068\u30b9\u30bf\u30d6\u6a5f\u80fd<\/h4>\n\n\n\n<p>\u5916\u90e8\u4f9d\u5b58\u3092\u6301\u3064\u30b3\u30fc\u30c9\u306e\u30c6\u30b9\u30c8\u3092\u5bb9\u6613\u306b\u3059\u308b\u5f37\u529b\u306a\u30e2\u30c3\u30af\u6a5f\u80fd\u3092\u63d0\u4f9b\uff1a<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">\/\/ \u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u63a5\u7d9a\u3092\u30e2\u30c3\u30af\u5316\u3059\u308b\u4f8b\n$mock = $this-&gt;createMock(Database::class);\n$mock-&gt;method('query')\n     -&gt;willReturn(['id' =&gt; 1, 'name' =&gt; 'Test']);<\/pre>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"i-5\">3. \u30c7\u30fc\u30bf\u30d7\u30ed\u30d0\u30a4\u30c0\u30fc\u6a5f\u80fd<\/h4>\n\n\n\n<p>\u8907\u6570\u306e\u30c6\u30b9\u30c8\u30b1\u30fc\u30b9\u3092\u52b9\u7387\u7684\u306b\u5b9f\u884c\u3067\u304d\u308b\u6a5f\u80fd\u3092\u63d0\u4f9b\uff1a<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">\/**\n * @dataProvider additionProvider\n *\/\npublic function testAdd($a, $b, $expected): void\n{\n    $this-&gt;assertEquals($expected, add($a, $b));\n}\n\npublic function additionProvider(): array\n{\n    return [\n        [1, 1, 2],\n        [0, 1, 1],\n        [-1, 1, 0]\n    ];\n}<\/pre>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"i-6\">4. \u30ab\u30d0\u30ec\u30c3\u30b8\u30ec\u30dd\u30fc\u30c8\u6a5f\u80fd<\/h4>\n\n\n\n<p>\u30c6\u30b9\u30c8\u30ab\u30d0\u30ec\u30c3\u30b8\u3092\u8996\u899a\u7684\u306b\u78ba\u8a8d\u3067\u304d\u308b\u6a5f\u80fd\u3092\u63d0\u4f9b\u3057\u3001\u30c6\u30b9\u30c8\u54c1\u8cea\u306e\u5b9a\u91cf\u7684\u306a\u8a55\u4fa1\u3092\u53ef\u80fd\u306b\u3057\u307e\u3059\u3002<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"i-7\">PHPUnit\u74b0\u5883\u69cb\u7bc9\u306e\u5b8c\u5168\u30de\u30cb\u30e5\u30a2\u30eb<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-8\">Composer\u3092\u4f7f\u7528\u3057\u305f\u6700\u65b0\u7248\u306e\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u65b9\u6cd5<\/h3>\n\n\n\n<p>PHPUnit\u3092\u958b\u767a\u30d7\u30ed\u30b8\u30a7\u30af\u30c8\u306b\u5c0e\u5165\u3059\u308b\u6700\u3082\u63a8\u5968\u3055\u308c\u308b\u65b9\u6cd5\u306f\u3001Composer\u3092\u4f7f\u7528\u3059\u308b\u3053\u3068\u3067\u3059\u3002\u4ee5\u4e0b\u306b\u3001\u6bb5\u968e\u7684\u306a\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u624b\u9806\u3092\u793a\u3057\u307e\u3059\u3002<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>\u4e8b\u524d\u6e96\u5099<\/strong><\/li>\n<\/ol>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">   # \u30d7\u30ed\u30b8\u30a7\u30af\u30c8\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u306e\u4f5c\u6210\u3068\u79fb\u52d5\n   mkdir my-project\n   cd my-project\n\n   # Composer\u30d7\u30ed\u30b8\u30a7\u30af\u30c8\u306e\u521d\u671f\u5316\n   composer init --require=\"phpunit\/phpunit:^10.0\" --dev<\/pre>\n\n\n\n<ol start=\"2\" class=\"wp-block-list\">\n<li><strong>PHPUnit\u306e\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb<\/strong><\/li>\n<\/ol>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">   # PHPUnit\u3092dev\u4f9d\u5b58\u95a2\u4fc2\u3068\u3057\u3066\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\n   composer require --dev phpunit\/phpunit ^10.0\n\n   # \u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u306e\u78ba\u8a8d\n   .\/vendor\/bin\/phpunit --version<\/pre>\n\n\n\n<ol start=\"3\" class=\"wp-block-list\">\n<li><strong>\u30d7\u30ed\u30b8\u30a7\u30af\u30c8\u69cb\u9020\u306e\u30bb\u30c3\u30c8\u30a2\u30c3\u30d7<\/strong><\/li>\n<\/ol>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">   my-project\/\n   \u251c\u2500\u2500 src\/           # \u30bd\u30fc\u30b9\u30b3\u30fc\u30c9\n   \u251c\u2500\u2500 tests\/         # \u30c6\u30b9\u30c8\u30b3\u30fc\u30c9\n   \u251c\u2500\u2500 composer.json\n   \u251c\u2500\u2500 composer.lock\n   \u2514\u2500\u2500 phpunit.xml    # PHPUnit\u8a2d\u5b9a\u30d5\u30a1\u30a4\u30eb<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-9\">\u8a2d\u5b9a\u30d5\u30a1\u30a4\u30ebphpunit.xml\u306e\u4f5c\u6210\u3068\u91cd\u8981\u306a\u8a2d\u5b9a\u9805\u76ee<\/h3>\n\n\n\n<p>PHPUnit\u306e\u52d5\u4f5c\u3092\u30ab\u30b9\u30bf\u30de\u30a4\u30ba\u3059\u308b\u305f\u3081\u306e\u8a2d\u5b9a\u30d5\u30a1\u30a4\u30eb<code>phpunit.xml<\/code>\u306e\u57fa\u672c\u69cb\u6210\u3068\u4e3b\u8981\u306a\u8a2d\u5b9a\u9805\u76ee\u3092\u89e3\u8aac\u3057\u307e\u3059\u3002<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">&lt;?xml version=\"1.0\" encoding=\"UTF-8\"?&gt;\n&lt;phpunit xmlns:xsi=\"http:\/\/www.w3.org\/2001\/XMLSchema-instance\"\n         xsi:noNamespaceSchemaLocation=\"vendor\/phpunit\/phpunit\/phpunit.xsd\"\n         bootstrap=\"vendor\/autoload.php\"\n         colors=\"true\"\n         testdox=\"true\"\n         displayDetailsOnTestsThatTriggerWarnings=\"true\"\n         displayDetailsOnTestsThatTriggerNotices=\"true\"\n         displayDetailsOnTestsThatTriggerErrors=\"true\"\n         displayDetailsOnTestsThatTriggerDeprecations=\"true\"&gt;\n\n    &lt;!-- \u30c6\u30b9\u30c8\u30b9\u30a4\u30fc\u30c8\u306e\u8a2d\u5b9a --&gt;\n    &lt;testsuites&gt;\n        &lt;testsuite name=\"Unit\"&gt;\n            &lt;directory&gt;tests\/Unit&lt;\/directory&gt;\n        &lt;\/testsuite&gt;\n        &lt;testsuite name=\"Feature\"&gt;\n            &lt;directory&gt;tests\/Feature&lt;\/directory&gt;\n        &lt;\/testsuite&gt;\n    &lt;\/testsuites&gt;\n\n    &lt;!-- \u30b3\u30fc\u30c9\u30ab\u30d0\u30ec\u30c3\u30b8\u30ec\u30dd\u30fc\u30c8\u306e\u8a2d\u5b9a --&gt;\n    &lt;coverage&gt;\n        &lt;include&gt;\n            &lt;directory suffix=\".php\"&gt;src&lt;\/directory&gt;\n        &lt;\/include&gt;\n        &lt;report&gt;\n            &lt;html outputDirectory=\"coverage\"\/&gt;\n            &lt;text outputFile=\"coverage.txt\"\/&gt;\n        &lt;\/report&gt;\n    &lt;\/coverage&gt;\n\n    &lt;!-- PHP\u8a2d\u5b9a --&gt;\n    &lt;php&gt;\n        &lt;env name=\"APP_ENV\" value=\"testing\"\/&gt;\n        &lt;ini name=\"error_reporting\" value=\"-1\"\/&gt;\n        &lt;ini name=\"memory_limit\" value=\"512M\"\/&gt;\n    &lt;\/php&gt;\n&lt;\/phpunit&gt;<\/pre>\n\n\n\n<p>\u4e3b\u8981\u306a\u8a2d\u5b9a\u9805\u76ee\u306e\u89e3\u8aac\uff1a<\/p>\n\n\n<div id=\"id-e2ffa98d-fb45-49ea-845c-fe3b7acab25a\">\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>\u8a2d\u5b9a\u9805\u76ee<\/th><th>\u8aac\u660e<\/th><th>\u63a8\u5968\u5024<\/th><\/tr><\/thead><tbody><tr><td>bootstrap<\/td><td>\u30aa\u30fc\u30c8\u30ed\u30fc\u30c0\u30fc\u306e\u6307\u5b9a<\/td><td>vendor\/autoload.php<\/td><\/tr><tr><td>colors<\/td><td>\u30c6\u30b9\u30c8\u7d50\u679c\u306e\u8272\u4ed8\u3051\u8868\u793a<\/td><td>true<\/td><\/tr><tr><td>testdox<\/td><td>\u8aad\u307f\u3084\u3059\u3044\u30c6\u30b9\u30c8\u7d50\u679c\u8868\u793a<\/td><td>true<\/td><\/tr><tr><td>memory_limit<\/td><td>\u30c6\u30b9\u30c8\u5b9f\u884c\u6642\u306e\u30e1\u30e2\u30ea\u5236\u9650<\/td><td>512M\u4ee5\u4e0a<\/td><\/tr><\/tbody><\/table><\/figure>\n<\/div>\n\n\n<h3 class=\"wp-block-heading\" id=\"i-10\">IDE\u3068\u306e\u9023\u643a\u3067\u30c6\u30b9\u30c8\u3092\u52b9\u7387\u5316\u3059\u308b\u65b9\u6cd5<\/h3>\n\n\n\n<p>\u4e3b\u8981\u306aIDE\u3067\u306ePHPUnit\u8a2d\u5b9a\u3068\u52b9\u7387\u7684\u306a\u30c6\u30b9\u30c8\u5b9f\u884c\u65b9\u6cd5\u3092\u89e3\u8aac\u3057\u307e\u3059\u3002<\/p>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"i-11\">1. PhpStorm \u3067\u306e\u8a2d\u5b9a<\/h4>\n\n\n\n<ol class=\"wp-block-list\">\n<li>\u30c6\u30b9\u30c8\u5b9f\u884c\u74b0\u5883\u306e\u8a2d\u5b9a<\/li>\n<\/ol>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">   Settings &gt; Languages &amp; Frameworks &gt; PHP &gt; Test Frameworks<\/pre>\n\n\n\n<ul class=\"wp-block-list\">\n<li>PHPUnit\u306e\u30d1\u30b9\u3092<code>vendor\/autoload.php<\/code>\u306b\u8a2d\u5b9a<\/li>\n\n\n\n<li>\u30c6\u30b9\u30c8\u8a2d\u5b9a\u30d5\u30a1\u30a4\u30eb\uff08phpunit.xml\uff09\u306e\u30d1\u30b9\u3092\u6307\u5b9a<\/li>\n<\/ul>\n\n\n\n<ol class=\"wp-block-list\">\n<li>\u30b7\u30e7\u30fc\u30c8\u30ab\u30c3\u30c8\u30ad\u30fc\u306e\u6d3b\u7528<\/li>\n<\/ol>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>Ctrl + Shift + T<\/code>\uff1a\u30c6\u30b9\u30c8\u30af\u30e9\u30b9\u306e\u4f5c\u6210<\/li>\n\n\n\n<li><code>Ctrl + Shift + F10<\/code>\uff1a\u30ab\u30fc\u30bd\u30eb\u4f4d\u7f6e\u306e\u30c6\u30b9\u30c8\u5b9f\u884c<\/li>\n\n\n\n<li><code>Alt + Shift + F10<\/code>\uff1a\u30c6\u30b9\u30c8\u5b9f\u884c\u8a2d\u5b9a\u306e\u9078\u629e<\/li>\n<\/ul>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"i-12\">2. Visual Studio Code \u3067\u306e\u8a2d\u5b9a<\/h4>\n\n\n\n<ol class=\"wp-block-list\">\n<li>\u63a8\u5968\u62e1\u5f35\u6a5f\u80fd\u306e\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb<\/li>\n<\/ol>\n\n\n\n<ul class=\"wp-block-list\">\n<li>PHP Extension Pack<\/li>\n\n\n\n<li>PHPUnit Test Explorer<\/li>\n<\/ul>\n\n\n\n<ol class=\"wp-block-list\">\n<li>settings.json\u306e\u8a2d\u5b9a\u4f8b<\/li>\n<\/ol>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">   {\n       \"php.validate.enable\": true,\n       \"phpunit.phpunit\": \".\/vendor\/bin\/phpunit\",\n       \"phpunit.args\": [\n           \"--configuration\",\n           \".\/phpunit.xml\"\n       ]\n   }<\/pre>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"i-13\">3. \u30c6\u30b9\u30c8\u5b9f\u884c\u306e\u52b9\u7387\u5316\u30c6\u30af\u30cb\u30c3\u30af<\/h4>\n\n\n\n<ol class=\"wp-block-list\">\n<li>\u30d5\u30a1\u30a4\u30eb\u30a6\u30a9\u30c3\u30c1\u30e3\u30fc\u306e\u8a2d\u5b9a<\/li>\n<\/ol>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">   # Laravel Mix\u4f7f\u7528\u6642\u306e\u4f8b\n   mix.browserSync('localhost:8000')\n      .version()\n      .watch(['tests\/**\/*.php'], () =&gt; {\n          exec('.\/vendor\/bin\/phpunit');\n      });<\/pre>\n\n\n\n<ol start=\"2\" class=\"wp-block-list\">\n<li>\u30c6\u30b9\u30c8\u30d5\u30a3\u30eb\u30bf\u30ea\u30f3\u30b0<\/li>\n<\/ol>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">   # \u7279\u5b9a\u306e\u30c6\u30b9\u30c8\u30b0\u30eb\u30fc\u30d7\u306e\u307f\u5b9f\u884c\n   .\/vendor\/bin\/phpunit --group=feature\n\n   # \u7279\u5b9a\u306e\u30c6\u30b9\u30c8\u30af\u30e9\u30b9\u306e\u307f\u5b9f\u884c\n   .\/vendor\/bin\/phpunit tests\/Unit\/UserTest.php<\/pre>\n\n\n\n<p>\u3053\u308c\u3089\u306e\u8a2d\u5b9a\u306b\u3088\u308a\u3001\u52b9\u7387\u7684\u306a\u30c6\u30b9\u30c8\u99c6\u52d5\u958b\u767a\uff08TDD\uff09\u306e\u30ef\u30fc\u30af\u30d5\u30ed\u30fc\u3092\u5b9f\u73fe\u3067\u304d\u307e\u3059\u3002<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"i-14\">\u5b9f\u8df5\u3067\u4f7f\u3048\u308b7\u3064\u306ePHPUnit\u30c6\u30b9\u30c8\u624b\u6cd5<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-15\">\u57fa\u672c\u7684\u306a\u30a2\u30b5\u30fc\u30b7\u30e7\u30f3\u3092\u4f7f\u7528\u3057\u305f\u30c6\u30b9\u30c8\u30b1\u30fc\u30b9\u4f5c\u6210<\/h3>\n\n\n\n<p>\u57fa\u672c\u7684\u306a\u30a2\u30b5\u30fc\u30b7\u30e7\u30f3\u3092\u4f7f\u7528\u3057\u305f\u30c6\u30b9\u30c8\u306f\u3001PHPUnit\u306e\u57fa\u790e\u3068\u306a\u308a\u307e\u3059\u3002\u4ee5\u4e0b\u306b\u3001\u5b9f\u8df5\u7684\u306a\u4f8b\u3092\u793a\u3057\u307e\u3059\uff1a<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">class CalculatorTest extends TestCase\n{\n    private Calculator $calculator;\n\n    protected function setUp(): void\n    {\n        $this-&gt;calculator = new Calculator();\n    }\n\n    public function testAddition(): void\n    {\n        \/\/ \u57fa\u672c\u7684\u306a\u7b49\u4fa1\u6027\u30c6\u30b9\u30c8\n        $this-&gt;assertEquals(4, $this-&gt;calculator-&gt;add(2, 2));\n\n        \/\/ \u6d6e\u52d5\u5c0f\u6570\u70b9\u6570\u306e\u6bd4\u8f03\n        $this-&gt;assertEqualsWithDelta(0.3, $this-&gt;calculator-&gt;add(0.1, 0.2), 0.0001);\n\n        \/\/ \u914d\u5217\u306e\u6bd4\u8f03\n        $this-&gt;assertSame(\n            ['total' =&gt; 4, 'operation' =&gt; 'add'],\n            $this-&gt;calculator-&gt;addWithDetails(2, 2)\n        );\n    }\n\n    public function testDivisionByZero(): void\n    {\n        \/\/ \u4f8b\u5916\u306e\u30c6\u30b9\u30c8\n        $this-&gt;expectException(DivisionByZeroException::class);\n        $this-&gt;calculator-&gt;divide(10, 0);\n    }\n}<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-16\">\u30e2\u30c3\u30af\u30aa\u30d6\u30b8\u30a7\u30af\u30c8\u3092\u6d3b\u7528\u3057\u305f\u5916\u90e8\u4f9d\u5b58\u306e\u30c6\u30b9\u30c8<\/h3>\n\n\n\n<p>\u5916\u90e8\u30b5\u30fc\u30d3\u30b9\u3084\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u306b\u4f9d\u5b58\u3059\u308b\u30b3\u30fc\u30c9\u3092\u30c6\u30b9\u30c8\u3059\u308b\u969b\u306e\u30e2\u30c3\u30af\u306e\u6d3b\u7528\u65b9\u6cd5\uff1a<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">class UserServiceTest extends TestCase\n{\n    public function testUserCreation(): void\n    {\n        \/\/ \u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u30ec\u30dd\u30b8\u30c8\u30ea\u306e\u30e2\u30c3\u30af\u4f5c\u6210\n        $repositoryMock = $this-&gt;createMock(UserRepository::class);\n\n        \/\/ \u30e2\u30c3\u30af\u306e\u632f\u308b\u821e\u3044\u3092\u5b9a\u7fa9\n        $repositoryMock-&gt;expects($this-&gt;once())\n            -&gt;method('save')\n            -&gt;with($this-&gt;callback(function($user) {\n                return $user-&gt;getEmail() === 'test@example.com';\n            }))\n            -&gt;willReturn(true);\n\n        \/\/ \u30e1\u30fc\u30eb\u9001\u4fe1\u30b5\u30fc\u30d3\u30b9\u306e\u30e2\u30c3\u30af\n        $mailerMock = $this-&gt;createMock(MailerInterface::class);\n        $mailerMock-&gt;expects($this-&gt;once())\n            -&gt;method('sendWelcomeEmail');\n\n        $service = new UserService($repositoryMock, $mailerMock);\n        $result = $service-&gt;createUser('test@example.com', 'password123');\n\n        $this-&gt;assertTrue($result);\n    }\n}<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-17\">\u30c7\u30fc\u30bf\u30d7\u30ed\u30d0\u30a4\u30c0\u30fc\u306b\u3088\u308b\u30d1\u30e9\u30e1\u30fc\u30bf\u5316\u30c6\u30b9\u30c8<\/h3>\n\n\n\n<p>\u591a\u69d8\u306a\u30c6\u30b9\u30c8\u30b1\u30fc\u30b9\u3092\u52b9\u7387\u7684\u306b\u5b9f\u884c\u3059\u308b\u305f\u3081\u306e\u30c7\u30fc\u30bf\u30d7\u30ed\u30d0\u30a4\u30c0\u30fc\u306e\u6d3b\u7528\uff1a<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">class ValidationTest extends TestCase\n{\n    \/**\n     * @dataProvider emailValidationProvider\n     *\/\n    public function testEmailValidation(string $email, bool $expectedValid): void\n    {\n        $validator = new EmailValidator();\n        $this-&gt;assertEquals($expectedValid, $validator-&gt;isValid($email));\n    }\n\n    public function emailValidationProvider(): array\n    {\n        return [\n            'valid email' =&gt; ['test@example.com', true],\n            'missing @' =&gt; ['testexample.com', false],\n            'invalid domain' =&gt; ['test@.com', false],\n            'with spaces' =&gt; ['test @example.com', false],\n            'with special chars' =&gt; ['test+filter@example.com', true]\n        ];\n    }\n}<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-18\">\u4f8b\u5916\u51e6\u7406\u306e\u30c6\u30b9\u30c8\u624b\u6cd5<\/h3>\n\n\n\n<p>\u4f8b\u5916\u51e6\u7406\u306e\u9069\u5207\u306a\u30c6\u30b9\u30c8\u65b9\u6cd5\u3068\u3001\u3088\u308a\u8a73\u7d30\u306a\u4f8b\u5916\u60c5\u5831\u306e\u691c\u8a3c\uff1a<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">class ExceptionHandlingTest extends TestCase\n{\n    public function testSpecificException(): void\n    {\n        $this-&gt;expectException(InvalidArgumentException::class);\n        $this-&gt;expectExceptionMessage('Value must be positive');\n        $this-&gt;expectExceptionCode(400);\n\n        $calculator = new Calculator();\n        $calculator-&gt;calculateSquareRoot(-1);\n    }\n\n    public function testExceptionWithContext(): void\n    {\n        try {\n            $processor = new DataProcessor();\n            $processor-&gt;process(['invalid' =&gt; 'data']);\n            $this-&gt;fail('Expected exception was not thrown');\n        } catch (ProcessingException $e) {\n            $this-&gt;assertStringContainsString('invalid data format', $e-&gt;getMessage());\n            $this-&gt;assertNotNull($e-&gt;getContext());\n            $this-&gt;assertArrayHasKey('input', $e-&gt;getContext());\n        }\n    }\n}<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-19\">\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u64cd\u4f5c\u306e\u30c6\u30b9\u30c8\u65b9\u6cd5<\/h3>\n\n\n\n<p>DBUnit\u62e1\u5f35\u3092\u4f7f\u7528\u3057\u305f\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u30c6\u30b9\u30c8\u306e\u5b9f\u88c5\uff1a<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">class UserRepositoryTest extends DatabaseTestCase\n{\n    private UserRepository $repository;\n\n    public function getDataSet(): IDataSet\n    {\n        return new YamlDataSet(dirname(__FILE__) . '\/fixtures\/users.yml');\n    }\n\n    protected function setUp(): void\n    {\n        parent::setUp();\n        $this-&gt;repository = new UserRepository($this-&gt;getConnection());\n    }\n\n    public function testFindUserById(): void\n    {\n        $user = $this-&gt;repository-&gt;find(1);\n\n        $this-&gt;assertNotNull($user);\n        $this-&gt;assertEquals('John Doe', $user-&gt;getName());\n        $this-&gt;assertEquals('john@example.com', $user-&gt;getEmail());\n    }\n\n    public function testCreateUser(): void\n    {\n        $newUser = new User('Jane Doe', 'jane@example.com');\n        $this-&gt;repository-&gt;save($newUser);\n\n        $this-&gt;assertTableRowCount('users', 2);\n        $this-&gt;assertTableContains(\n            'users',\n            ['name' =&gt; 'Jane Doe', 'email' =&gt; 'jane@example.com']\n        );\n    }\n}<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-20\">\u975e\u540c\u671f\u51e6\u7406\u306e\u30c6\u30b9\u30c8\u5b9f\u88c5<\/h3>\n\n\n\n<p>\u975e\u540c\u671f\u51e6\u7406\u3084Promise\u30d1\u30bf\u30fc\u30f3\u3092\u4f7f\u7528\u3057\u305f\u30b3\u30fc\u30c9\u306e\u30c6\u30b9\u30c8\u65b9\u6cd5\uff1a<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">class AsyncProcessTest extends TestCase\n{\n    public function testAsyncOperation(): void\n    {\n        $processor = new AsyncProcessor();\n\n        $promise = $processor-&gt;processAsync('test-data');\n\n        \/\/ \u975e\u540c\u671f\u51e6\u7406\u306e\u5b8c\u4e86\u3092\u5f85\u6a5f\n        $result = $promise-&gt;wait();\n\n        $this-&gt;assertNotNull($result);\n        $this-&gt;assertEquals('processed-test-data', $result-&gt;getData());\n    }\n\n    public function testMultipleAsyncOperations(): void\n    {\n        $processor = new AsyncProcessor();\n\n        $promises = [\n            'first' =&gt; $processor-&gt;processAsync('data1'),\n            'second' =&gt; $processor-&gt;processAsync('data2')\n        ];\n\n        \/\/ \u5168\u3066\u306e\u975e\u540c\u671f\u51e6\u7406\u306e\u5b8c\u4e86\u3092\u5f85\u6a5f\n        $results = Promise\\Utils::all($promises)-&gt;wait();\n\n        $this-&gt;assertCount(2, $results);\n        $this-&gt;assertArrayHasKey('first', $results);\n        $this-&gt;assertArrayHasKey('second', $results);\n    }\n}<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-21\">\u30d7\u30e9\u30a4\u30d9\u30fc\u30c8\u30e1\u30bd\u30c3\u30c9\u306e\u30c6\u30b9\u30c8\u30c6\u30af\u30cb\u30c3\u30af<\/h3>\n\n\n\n<p>\u30d7\u30e9\u30a4\u30d9\u30fc\u30c8\u30e1\u30bd\u30c3\u30c9\u3084\u30d7\u30ed\u30c6\u30af\u30c6\u30c3\u30c9\u30e1\u30bd\u30c3\u30c9\u306e\u30c6\u30b9\u30c8\u65b9\u6cd5\uff1a<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">class PrivateMethodTest extends TestCase\n{\n    public function testPrivateCalculation(): void\n    {\n        $calculator = new ComplexCalculator();\n\n        \/\/ \u30ea\u30d5\u30ec\u30af\u30b7\u30e7\u30f3\u3092\u4f7f\u7528\u3057\u3066\u30d7\u30e9\u30a4\u30d9\u30fc\u30c8\u30e1\u30bd\u30c3\u30c9\u306b\u30a2\u30af\u30bb\u30b9\n        $method = new ReflectionMethod(ComplexCalculator::class, 'calculateIntermediate');\n        $method-&gt;setAccessible(true);\n\n        $result = $method-&gt;invoke($calculator, 10, 5);\n        $this-&gt;assertEquals(50, $result);\n    }\n\n    public function testProtectedPropertyAccess(): void\n    {\n        $processor = new DataProcessor();\n\n        \/\/ \u30ea\u30d5\u30ec\u30af\u30b7\u30e7\u30f3\u3092\u4f7f\u7528\u3057\u3066\u30d7\u30ed\u30c6\u30af\u30c6\u30c3\u30c9\u30d7\u30ed\u30d1\u30c6\u30a3\u3092\u8a2d\u5b9a\n        $reflection = new ReflectionClass(DataProcessor::class);\n        $property = $reflection-&gt;getProperty('configuration');\n        $property-&gt;setAccessible(true);\n\n        $property-&gt;setValue($processor, ['key' =&gt; 'value']);\n\n        \/\/ \u516c\u958b\u30e1\u30bd\u30c3\u30c9\u3092\u901a\u3058\u3066\u9593\u63a5\u7684\u306b\u30c6\u30b9\u30c8\n        $result = $processor-&gt;process(['data']);\n        $this-&gt;assertTrue($result-&gt;isConfigured());\n    }\n}<\/pre>\n\n\n\n<p>\u3053\u308c\u3089\u306e\u30c6\u30b9\u30c8\u624b\u6cd5\u3092\u7d44\u307f\u5408\u308f\u305b\u308b\u3053\u3068\u3067\u3001\u5805\u7262\u306a\u30c6\u30b9\u30c8\u30b9\u30a4\u30fc\u30c8\u3092\u69cb\u7bc9\u3067\u304d\u307e\u3059\u3002\u5404\u624b\u6cd5\u306f\u72b6\u6cc1\u306b\u5fdc\u3058\u3066\u9069\u5207\u306b\u9078\u629e\u3057\u3001\u30c6\u30b9\u30c8\u306e\u4fdd\u5b88\u6027\u3068\u4fe1\u983c\u6027\u3092\u78ba\u4fdd\u3059\u308b\u3053\u3068\u304c\u91cd\u8981\u3067\u3059\u3002<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"i-22\">PHPUnit\u30c6\u30b9\u30c8\u306e\u8a2d\u8a08\u30d9\u30b9\u30c8\u30d7\u30e9\u30af\u30c6\u30a3\u30b9<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-23\">\u30c6\u30b9\u30c8\u30b1\u30fc\u30b9\u8a2d\u8a08\u306e\u539f\u5247\u3068TDD\u306e\u5b9f\u8df5\u65b9\u6cd5<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"i-24\">\u30c6\u30b9\u30c8\u99c6\u52d5\u958b\u767a\uff08TDD\uff09\u306e\u57fa\u672c\u30b5\u30a4\u30af\u30eb<\/h4>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>Red<\/strong>: \u5931\u6557\u3059\u308b\u30c6\u30b9\u30c8\u3092\u66f8\u304f<\/li>\n<\/ol>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">public function testUserRegistration(): void\n{\n    $userService = new UserService();\n    $user = $userService-&gt;register(\n        'test@example.com',\n        'password123',\n        'John Doe'\n    );\n\n    $this-&gt;assertInstanceOf(User::class, $user);\n    $this-&gt;assertEquals('test@example.com', $user-&gt;getEmail());\n    $this-&gt;assertTrue($user-&gt;isActive());\n}<\/pre>\n\n\n\n<ol start=\"2\" class=\"wp-block-list\">\n<li><strong>Green<\/strong>: \u30c6\u30b9\u30c8\u304c\u901a\u308b\u3088\u3046\u306b\u6700\u5c0f\u9650\u306e\u5b9f\u88c5\u3092\u884c\u3046<\/li>\n<\/ol>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">class UserService\n{\n    public function register(string $email, string $password, string $name): User\n    {\n        $user = new User();\n        $user-&gt;setEmail($email);\n        $user-&gt;setName($name);\n        $user-&gt;setPassword(password_hash($password, PASSWORD_BCRYPT));\n        $user-&gt;setActive(true);\n\n        return $user;\n    }\n}<\/pre>\n\n\n\n<ol start=\"3\" class=\"wp-block-list\">\n<li><strong>Refactor<\/strong>: \u30b3\u30fc\u30c9\u3092\u30ea\u30d5\u30a1\u30af\u30bf\u30ea\u30f3\u30b0\u3059\u308b<\/li>\n<\/ol>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">class UserService\n{\n    private UserRepository $repository;\n    private PasswordHasher $passwordHasher;\n\n    public function register(string $email, string $password, string $name): User\n    {\n        $user = User::create($email, $name);\n        $user-&gt;setPassword($this-&gt;passwordHasher-&gt;hash($password));\n        $user-&gt;activate();\n\n        $this-&gt;repository-&gt;save($user);\n        return $user;\n    }\n}<\/pre>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"i-25\">FIRST\u539f\u5247\u306e\u5b9f\u8df5<\/h4>\n\n\n<div id=\"id-17b9b0de-967b-451a-95e9-de494feceff8\">\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>\u539f\u5247<\/th><th>\u8aac\u660e<\/th><th>\u5b9f\u88c5\u4f8b<\/th><\/tr><\/thead><tbody><tr><td>Fast<\/td><td>\u30c6\u30b9\u30c8\u306f\u9ad8\u901f\u306b\u5b9f\u884c\u3055\u308c\u308b<\/td><td>\u5916\u90e8\u4f9d\u5b58\u3092\u30e2\u30c3\u30af\u5316<\/td><\/tr><tr><td>Isolated<\/td><td>\u30c6\u30b9\u30c8\u306f\u72ec\u7acb\u3057\u3066\u3044\u308b<\/td><td>\u30c6\u30b9\u30c8\u3054\u3068\u306b\u30c7\u30fc\u30bf\u3092\u30ea\u30bb\u30c3\u30c8<\/td><\/tr><tr><td>Repeatable<\/td><td>\u30c6\u30b9\u30c8\u306f\u4f55\u5ea6\u5b9f\u884c\u3057\u3066\u3082\u540c\u3058\u7d50\u679c<\/td><td>\u56fa\u5b9a\u306e\u30c6\u30b9\u30c8\u30c7\u30fc\u30bf\u3092\u4f7f\u7528<\/td><\/tr><tr><td>Self-validating<\/td><td>\u30c6\u30b9\u30c8\u306f\u81ea\u5df1\u691c\u8a3c\u53ef\u80fd<\/td><td>\u30a2\u30b5\u30fc\u30b7\u30e7\u30f3\u3092\u660e\u78ba\u306b\u8a18\u8ff0<\/td><\/tr><tr><td>Timely<\/td><td>\u30c6\u30b9\u30c8\u306f\u30b3\u30fc\u30c9\u3068\u540c\u6642\u306b\u66f8\u304f<\/td><td>TDD\u30b5\u30a4\u30af\u30eb\u3092\u9075\u5b88<\/td><\/tr><\/tbody><\/table><\/figure>\n<\/div>\n\n\n<h3 class=\"wp-block-heading\" id=\"i-26\">\u30c6\u30b9\u30c8\u306e\u547d\u540d\u898f\u5247\u3068\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u69cb\u9020\u306e\u6574\u7406<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"i-27\">\u63a8\u5968\u3055\u308c\u308b\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u69cb\u9020<\/h4>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">tests\/\n\u251c\u2500\u2500 Unit\/\n\u2502   \u251c\u2500\u2500 Domain\/\n\u2502   \u2502   \u251c\u2500\u2500 UserTest.php\n\u2502   \u2502   \u2514\u2500\u2500 OrderTest.php\n\u2502   \u2514\u2500\u2500 Service\/\n\u2502       \u251c\u2500\u2500 UserServiceTest.php\n\u2502       \u2514\u2500\u2500 OrderServiceTest.php\n\u251c\u2500\u2500 Integration\/\n\u2502   \u251c\u2500\u2500 Repository\/\n\u2502   \u2502   \u2514\u2500\u2500 UserRepositoryTest.php\n\u2502   \u2514\u2500\u2500 Service\/\n\u2502       \u2514\u2500\u2500 PaymentServiceTest.php\n\u251c\u2500\u2500 Feature\/\n\u2502   \u251c\u2500\u2500 UserRegistrationTest.php\n\u2502   \u2514\u2500\u2500 OrderProcessTest.php\n\u2514\u2500\u2500 TestCase.php<\/pre>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"i-28\">\u30c6\u30b9\u30c8\u30af\u30e9\u30b9\u3068\u30e1\u30bd\u30c3\u30c9\u306e\u547d\u540d\u898f\u5247<\/h4>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">\/\/ \u6a5f\u80fd\u5358\u4f4d\u3067\u306e\u30c6\u30b9\u30c8\u30af\u30e9\u30b9\u540d\nclass UserRegistrationTest extends TestCase\n{\n    \/\/ \u6b63\u5e38\u7cfb\u30c6\u30b9\u30c8\n    public function testSuccessfulRegistration(): void\n    {\n        \/\/ \u30c6\u30b9\u30c8\u30b3\u30fc\u30c9\n    }\n\n    \/\/ \u7570\u5e38\u7cfb\u30c6\u30b9\u30c8\n    public function testRegistrationFailsWithInvalidEmail(): void\n    {\n        \/\/ \u30c6\u30b9\u30c8\u30b3\u30fc\u30c9\n    }\n\n    \/\/ \u72b6\u614b\u78ba\u8a8d\u30c6\u30b9\u30c8\n    public function testUserIsInactiveByDefault(): void\n    {\n        \/\/ \u30c6\u30b9\u30c8\u30b3\u30fc\u30c9\n    }\n}\n\n\/\/ \u30c9\u30e1\u30a4\u30f3\u30e2\u30c7\u30eb\u306e\u30c6\u30b9\u30c8\u30af\u30e9\u30b9\u540d\nclass UserTest extends TestCase\n{\n    \/\/ \u632f\u308b\u821e\u3044\u30d9\u30fc\u30b9\u306e\u547d\u540d\n    public function testUserCanChangePassword(): void\n    {\n        \/\/ \u30c6\u30b9\u30c8\u30b3\u30fc\u30c9\n    }\n\n    \/\/ \u72b6\u614b\u5909\u66f4\u306e\u691c\u8a3c\n    public function testUserBecomesInactiveAfterTooManyLoginAttempts(): void\n    {\n        \/\/ \u30c6\u30b9\u30c8\u30b3\u30fc\u30c9\n    }\n}<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-29\">\u30c6\u30b9\u30c8\u30ab\u30d0\u30ec\u30c3\u30b8\u306e\u6e2c\u5b9a\u3068\u6d3b\u7528\u65b9\u6cd5<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"i-30\">\u30ab\u30d0\u30ec\u30c3\u30b8\u30ec\u30dd\u30fc\u30c8\u306e\u751f\u6210\u3068\u89e3\u6790<\/h4>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>PHPUnit\u8a2d\u5b9a\u3067\u306e\u30ab\u30d0\u30ec\u30c3\u30b8\u8a2d\u5b9a<\/strong><\/li>\n<\/ol>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">&lt;coverage processUncoveredFiles=\"true\"&gt;\n    &lt;include&gt;\n        &lt;directory suffix=\".php\"&gt;src&lt;\/directory&gt;\n    &lt;\/include&gt;\n    &lt;exclude&gt;\n        &lt;directory&gt;src\/Legacy&lt;\/directory&gt;\n        &lt;file&gt;src\/bootstrap.php&lt;\/file&gt;\n    &lt;\/exclude&gt;\n    &lt;report&gt;\n        &lt;html outputDirectory=\"coverage\"\/&gt;\n        &lt;clover outputFile=\"coverage.xml\"\/&gt;\n        &lt;text outputFile=\"coverage.txt\"\/&gt;\n    &lt;\/report&gt;\n&lt;\/coverage&gt;<\/pre>\n\n\n\n<ol start=\"2\" class=\"wp-block-list\">\n<li><strong>\u30ab\u30d0\u30ec\u30c3\u30b8\u8a08\u6e2c\u306e\u5b9f\u884c<\/strong><\/li>\n<\/ol>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\"># HTML\u30ec\u30dd\u30fc\u30c8\u751f\u6210\nXDEBUG_MODE=coverage .\/vendor\/bin\/phpunit --coverage-html coverage\/\n\n# \u30c6\u30ad\u30b9\u30c8\u30ec\u30dd\u30fc\u30c8\u751f\u6210\nXDEBUG_MODE=coverage .\/vendor\/bin\/phpunit --coverage-text<\/pre>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"i-31\">\u30ab\u30d0\u30ec\u30c3\u30b8\u76ee\u6a19\u306e\u8a2d\u5b9a\u3068\u76e3\u8996<\/h4>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">class PaymentProcessorTest extends TestCase\n{\n    \/**\n     * @coversDefaultClass \\App\\Service\\PaymentProcessor\n     * @covers ::process\n     *\/\n    public function testPaymentProcessing(): void\n    {\n        $processor = new PaymentProcessor();\n        $result = $processor-&gt;process($payment);\n\n        $this-&gt;assertTrue($result-&gt;isSuccessful());\n    }\n}<\/pre>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"i-32\">\u30ab\u30d0\u30ec\u30c3\u30b8\u54c1\u8cea\u306e\u78ba\u4fdd<\/h4>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>\u91cd\u8981\u306a\u30d3\u30b8\u30cd\u30b9\u30ed\u30b8\u30c3\u30af\u306e\u512a\u5148\u7684\u306a\u30ab\u30d0\u30fc<\/strong><\/li>\n<\/ol>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">\/**\n * @covers \\App\\Service\\OrderProcessor::calculateTotal\n * @testWith [\"standard\", 100, 110]\n *           [\"premium\", 100, 105]\n *           [\"vip\", 100, 100]\n *\/\npublic function testOrderTotalCalculation(\n    string $customerType,\n    float $baseAmount,\n    float $expectedTotal\n): void {\n    $processor = new OrderProcessor();\n    $actual = $processor-&gt;calculateTotal($customerType, $baseAmount);\n\n    $this-&gt;assertEquals($expectedTotal, $actual);\n}<\/pre>\n\n\n\n<ol start=\"2\" class=\"wp-block-list\">\n<li><strong>\u5883\u754c\u5024\u30c6\u30b9\u30c8\u306e\u91cd\u8981\u6027<\/strong><\/li>\n<\/ol>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">class DiscountCalculatorTest extends TestCase\n{\n    \/**\n     * @covers \\App\\Service\\DiscountCalculator::calculateDiscount\n     * @dataProvider discountBoundaryProvider\n     *\/\n    public function testDiscountBoundaries(\n        float $amount,\n        float $expectedDiscount\n    ): void {\n        $calculator = new DiscountCalculator();\n        $actual = $calculator-&gt;calculateDiscount($amount);\n\n        $this-&gt;assertEquals($expectedDiscount, $actual);\n    }\n\n    public function discountBoundaryProvider(): array\n    {\n        return [\n            'minimum amount' =&gt; [999.99, 0.0],\n            'discount threshold' =&gt; [1000.0, 100.0],\n            'maximum discount' =&gt; [10000.0, 500.0]\n        ];\n    }\n}<\/pre>\n\n\n\n<p>\u3053\u308c\u3089\u306e\u30d9\u30b9\u30c8\u30d7\u30e9\u30af\u30c6\u30a3\u30b9\u3092\u9069\u7528\u3059\u308b\u3053\u3068\u3067\u3001\u4fdd\u5b88\u6027\u304c\u9ad8\u304f\u3001\u4fe1\u983c\u6027\u306e\u3042\u308b\u30c6\u30b9\u30c8\u30b9\u30a4\u30fc\u30c8\u3092\u69cb\u7bc9\u3067\u304d\u307e\u3059\u3002\u30c6\u30b9\u30c8\u306e\u54c1\u8cea\u3092\u7d99\u7d9a\u7684\u306b\u76e3\u8996\u3057\u3001\u6539\u5584\u3059\u308b\u3053\u3068\u3067\u3001\u30d7\u30ed\u30b8\u30a7\u30af\u30c8\u306e\u54c1\u8cea\u5411\u4e0a\u306b\u8ca2\u732e\u3067\u304d\u307e\u3059\u3002<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"i-33\">CI\/CD\u30d1\u30a4\u30d7\u30e9\u30a4\u30f3\u306b\u304a\u3051\u308bPHPUnit\u306e\u6d3b\u7528\u6cd5<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-34\">GitHubActions\u3067\u306e\u81ea\u52d5\u30c6\u30b9\u30c8\u8a2d\u5b9a<\/h3>\n\n\n\n<p>GitHub Actions\u3092\u4f7f\u7528\u3057\u3066\u3001PHPUnit\u30c6\u30b9\u30c8\u3092\u81ea\u52d5\u5316\u3059\u308b\u5177\u4f53\u7684\u306a\u5b9f\u88c5\u65b9\u6cd5\u3092\u89e3\u8aac\u3057\u307e\u3059\u3002<\/p>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"i-35\">\u57fa\u672c\u7684\u306a\u30ef\u30fc\u30af\u30d5\u30ed\u30fc\u8a2d\u5b9a<\/h4>\n\n\n\n<p><code>.github\/workflows\/tests.yml<\/code>\u306e\u5b9f\u88c5\u4f8b\uff1a<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">name: PHP Tests\n\non:\n  push:\n    branches: [ main, develop ]\n  pull_request:\n    branches: [ main, develop ]\n\njobs:\n  test:\n    runs-on: ubuntu-latest\n    strategy:\n      matrix:\n        php-versions: ['8.1', '8.2']\n\n    services:\n      mysql:\n        image: mysql:8.0\n        env:\n          MYSQL_ROOT_PASSWORD: password\n          MYSQL_DATABASE: test_db\n        ports:\n          - 3306:3306\n        options: --health-cmd=\"mysqladmin ping\" --health-interval=10s --health-timeout=5s --health-retries=3\n\n    steps:\n    - uses: actions\/checkout@v3\n\n    - name: Setup PHP\n      uses: shivammathur\/setup-php@v2\n      with:\n        php-version: ${{ matrix.php-versions }}\n        extensions: mbstring, xml, ctype, iconv, intl, pdo_sqlite, mysql\n        coverage: xdebug\n\n    - name: Validate composer.json and composer.lock\n      run: composer validate --strict\n\n    - name: Cache Composer packages\n      id: composer-cache\n      uses: actions\/cache@v3\n      with:\n        path: vendor\n        key: ${{ runner.os }}-php-${{ hashFiles('**\/composer.lock') }}\n        restore-keys: |\n          ${{ runner.os }}-php-\n\n    - name: Install dependencies\n      run: composer install --prefer-dist --no-progress\n\n    - name: Run test suite\n      run: |\n        mkdir -p build\/logs\n        XDEBUG_MODE=coverage vendor\/bin\/phpunit --coverage-clover build\/logs\/clover.xml\n\n    - name: Upload coverage to Codecov\n      uses: codecov\/codecov-action@v3\n      with:\n        file: build\/logs\/clover.xml\n        fail_ci_if_error: true<\/pre>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"i-36\">\u30c6\u30b9\u30c8\u7d50\u679c\u306e\u53ef\u8996\u5316<\/h4>\n\n\n\n<p>GitHub\u306e\u30d7\u30eb\u30ea\u30af\u30a8\u30b9\u30c8\u306b\u81ea\u52d5\u7684\u306b\u30c6\u30b9\u30c8\u7d50\u679c\u3092\u8868\u793a\u3059\u308b\u8a2d\u5b9a\uff1a<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">    - name: Create Test Summary\n      if: always()\n      uses: test-summary\/action@v2\n      with:\n        paths: build\/logs\/junit.xml\n\n    - name: Add Coverage Comment\n      uses: marocchino\/sticky-pull-request-comment@v2\n      if: github.event_name == 'pull_request'\n      with:\n        recreate: true\n        path: build\/logs\/coverage-summary.txt<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-37\">Jenkins\u9023\u643a\u306b\u3088\u308b\u30c6\u30b9\u30c8\u81ea\u52d5\u5316\u306e\u5b9f\u73fe<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"i-38\">Jenkinsfile\u306e\u5b9f\u88c5\u4f8b<\/h4>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">pipeline {\n    agent any\n\n    environment {\n        PHP_VERSION = '8.2'\n        COMPOSER_HOME = \"${WORKSPACE}\/.composer\"\n    }\n\n    stages {\n        stage('Setup') {\n            steps {\n                sh 'composer install --no-interaction --no-progress'\n            }\n        }\n\n        stage('Static Analysis') {\n            parallel {\n                stage('PHPStan') {\n                    steps {\n                        sh 'vendor\/bin\/phpstan analyse src tests'\n                    }\n                }\n                stage('PHP_CodeSniffer') {\n                    steps {\n                        sh 'vendor\/bin\/phpcs src tests'\n                    }\n                }\n            }\n        }\n\n        stage('Unit Tests') {\n            steps {\n                sh '''\n                    mkdir -p build\/logs\n                    XDEBUG_MODE=coverage vendor\/bin\/phpunit \\\n                        --coverage-clover build\/logs\/clover.xml \\\n                        --coverage-html build\/coverage\n                '''\n            }\n            post {\n                always {\n                    publishHTML(\n                        target: [\n                            reportDir: 'build\/coverage',\n                            reportFiles: 'index.html',\n                            reportName: 'Coverage Report'\n                        ]\n                    )\n\n                    junit 'build\/logs\/junit.xml'\n                }\n            }\n        }\n    }\n\n    post {\n        success {\n            slackSend(\n                color: 'good',\n                message: \"\u30c6\u30b9\u30c8\u304c\u6210\u529f\u3057\u307e\u3057\u305f: Job '${env.JOB_NAME} [${env.BUILD_NUMBER}]'\"\n            )\n        }\n        failure {\n            slackSend(\n                color: 'danger',\n                message: \"\u30c6\u30b9\u30c8\u304c\u5931\u6557\u3057\u307e\u3057\u305f: Job '${env.JOB_NAME} [${env.BUILD_NUMBER}]'\"\n            )\n        }\n    }\n}<\/pre>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"i-39\">\u30c6\u30b9\u30c8\u54c1\u8cea\u7ba1\u7406\u306e\u81ea\u52d5\u5316<\/h4>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>\u30ab\u30d0\u30ec\u30c3\u30b8\u3057\u304d\u3044\u5024\u306e\u8a2d\u5b9a<\/strong><\/li>\n<\/ol>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">&lt;!-- phpunit.xml --&gt;\n&lt;coverage&gt;\n    &lt;report&gt;\n        &lt;clover outputFile=\"build\/logs\/clover.xml\"\/&gt;\n        &lt;html outputDirectory=\"build\/coverage\"\/&gt;\n    &lt;\/report&gt;\n&lt;\/coverage&gt;\n&lt;logging&gt;\n    &lt;junit outputFile=\"build\/logs\/junit.xml\"\/&gt;\n&lt;\/logging&gt;<\/pre>\n\n\n\n<ol start=\"2\" class=\"wp-block-list\">\n<li><strong>\u54c1\u8cea\u30b2\u30fc\u30c8\u306e\u8a2d\u5b9a<\/strong><\/li>\n<\/ol>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">stage('Quality Gate') {\n    steps {\n        script {\n            def coverageResult = sh(\n                script: '''\n                    coverage=$(grep -A 5 \"&lt;metrics\" build\/logs\/clover.xml | \\\n                    grep \"statements\" | \\\n                    cut -d'\"' -f4)\n                    echo $coverage\n                ''',\n                returnStdout: true\n            ).trim()\n\n            if (coverageResult.toFloat() &lt; 80) {\n                error \"\u30b3\u30fc\u30c9\u30ab\u30d0\u30ec\u30c3\u30b8\u304c80%\u672a\u6e80\u3067\u3059: ${coverageResult}%\"\n            }\n        }\n    }\n}<\/pre>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"i-40\">\u30d3\u30eb\u30c9\u30d1\u30a4\u30d7\u30e9\u30a4\u30f3\u306e\u6700\u9069\u5316<\/h4>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>\u4e26\u5217\u30c6\u30b9\u30c8\u5b9f\u884c<\/strong><\/li>\n<\/ol>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">stage('Parallel Tests') {\n    parallel {\n        stage('Unit Tests') {\n            steps {\n                sh 'vendor\/bin\/phpunit --testsuite unit'\n            }\n        }\n        stage('Integration Tests') {\n            steps {\n                sh 'vendor\/bin\/phpunit --testsuite integration'\n            }\n        }\n        stage('Feature Tests') {\n            steps {\n                sh 'vendor\/bin\/phpunit --testsuite feature'\n            }\n        }\n    }\n}<\/pre>\n\n\n\n<ol start=\"2\" class=\"wp-block-list\">\n<li><strong>\u30c6\u30b9\u30c8\u306e\u9ad8\u901f\u5316<\/strong><\/li>\n<\/ol>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\"># docker-compose.ci.yml\nversion: '3.8'\nservices:\n  php-test:\n    build:\n      context: .\n      dockerfile: Dockerfile.ci\n    volumes:\n      - .:\/app\n    environment:\n      - APP_ENV=testing\n      - DB_CONNECTION=sqlite\n      - DB_DATABASE=:memory:<\/pre>\n\n\n\n<p>\u3053\u308c\u3089\u306e\u8a2d\u5b9a\u306b\u3088\u308a\u3001\u4ee5\u4e0b\u306e\u3088\u3046\u306a\u7d99\u7d9a\u7684\u30a4\u30f3\u30c6\u30b0\u30ec\u30fc\u30b7\u30e7\u30f3\u30d5\u30ed\u30fc\u304c\u5b9f\u73fe\u3067\u304d\u307e\u3059\uff1a<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>\u30b3\u30fc\u30c9\u306e\u30d7\u30c3\u30b7\u30e5\/PR\u306e\u4f5c\u6210<\/li>\n\n\n\n<li>\u81ea\u52d5\u30c6\u30b9\u30c8\u306e\u5b9f\u884c<\/li>\n\n\n\n<li>\u30b3\u30fc\u30c9\u30ab\u30d0\u30ec\u30c3\u30b8\u306e\u8a08\u6e2c<\/li>\n\n\n\n<li>\u54c1\u8cea\u57fa\u6e96\u306e\u30c1\u30a7\u30c3\u30af<\/li>\n\n\n\n<li>\u30c6\u30b9\u30c8\u7d50\u679c\u306e\u30ec\u30dd\u30fc\u30c8\u751f\u6210<\/li>\n\n\n\n<li>\u901a\u77e5\u306e\u9001\u4fe1<\/li>\n<\/ol>\n\n\n\n<p>\u3053\u306e\u81ea\u52d5\u5316\u3055\u308c\u305f\u30ef\u30fc\u30af\u30d5\u30ed\u30fc\u306b\u3088\u308a\u3001\u958b\u767a\u30c1\u30fc\u30e0\u306f\u54c1\u8cea\u3092\u7dad\u6301\u3057\u306a\u304c\u3089\u3001\u52b9\u7387\u7684\u306a\u958b\u767a\u3092\u9032\u3081\u308b\u3053\u3068\u304c\u3067\u304d\u307e\u3059\u3002<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"i-41\">PHPUnit\u3067\u3088\u304f\u3042\u308b\u30a8\u30e9\u30fc\u3068\u30c8\u30e9\u30d6\u30eb\u30b7\u30e5\u30fc\u30c6\u30a3\u30f3\u30b0<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-42\">\u74b0\u5883\u69cb\u7bc9\u6642\u306e\u4e3b\u8981\u306a\u30a8\u30e9\u30fc\u5bfe\u51e6\u6cd5<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"i-43\">1. Composer\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u95a2\u9023\u306e\u30a8\u30e9\u30fc<\/h4>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">Problem 1\n    - phpunit\/phpunit[9.0.0, ..., 9.6.13] require php &gt;= 7.3 -&gt; your php version (7.2.34) does not satisfy that requirement.<\/pre>\n\n\n\n<p><strong>\u89e3\u6c7a\u7b56:<\/strong><\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\"># PHP \u30d0\u30fc\u30b8\u30e7\u30f3\u306e\u78ba\u8a8d\nphp -v\n\n# \u9069\u5207\u306aPHP\u30d0\u30fc\u30b8\u30e7\u30f3\u306e\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\uff08Ubuntu\/Debian\uff09\nsudo add-apt-repository ppa:ondrej\/php\nsudo apt-get update\nsudo apt-get install php8.2\n\n# PHPUnit\u306e\u7279\u5b9a\u30d0\u30fc\u30b8\u30e7\u30f3\u3092\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\ncomposer require --dev phpunit\/phpunit:^8.5<\/pre>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"i-44\">2. \u8a2d\u5b9a\u30d5\u30a1\u30a4\u30eb\u306e\u69cb\u6587\u30a8\u30e9\u30fc<\/h4>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">&lt;!-- \u30a8\u30e9\u30fc\u304c\u767a\u751f\u3059\u308b\u8a2d\u5b9a --&gt;\n&lt;phpunit&gt;\n    &lt;testsuites&gt;\n        &lt;testsuite&gt;  &lt;!-- name\u5c5e\u6027\u304c\u6b20\u843d --&gt;\n            &lt;directory&gt;tests&lt;\/directory&gt;\n        &lt;\/testsuite&gt;\n    &lt;\/testsuites&gt;\n&lt;\/phpunit&gt;\n\n&lt;!-- \u6b63\u3057\u3044\u8a2d\u5b9a --&gt;\n&lt;phpunit&gt;\n    &lt;testsuites&gt;\n        &lt;testsuite name=\"unit\"&gt;\n            &lt;directory&gt;tests&lt;\/directory&gt;\n        &lt;\/testsuite&gt;\n    &lt;\/testsuites&gt;\n&lt;\/phpunit&gt;<\/pre>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"i-45\">3. \u30c6\u30b9\u30c8\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u306e\u69cb\u9020\u30a8\u30e9\u30fc<\/h4>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">\/\/ \u30a8\u30e9\u30fc: \u30af\u30e9\u30b9\u540d\u3068\u30d5\u30a1\u30a4\u30eb\u540d\u304c\u4e00\u81f4\u3057\u306a\u3044\n\/\/ \u30d5\u30a1\u30a4\u30eb\u540d: UserTest.php\nclass CustomerTest extends TestCase\n{\n    \/\/ \u30c6\u30b9\u30c8\u30b3\u30fc\u30c9\n}\n\n\/\/ \u6b63\u3057\u3044\u5b9f\u88c5\n\/\/ \u30d5\u30a1\u30a4\u30eb\u540d: UserTest.php\nclass UserTest extends TestCase\n{\n    \/\/ \u30c6\u30b9\u30c8\u30b3\u30fc\u30c9\n}<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-46\">\u30c6\u30b9\u30c8\u5b9f\u884c\u6642\u306e\u30e1\u30e2\u30ea\u7ba1\u7406\u3068\u30d1\u30d5\u30a9\u30fc\u30de\u30f3\u30b9\u5411\u4e0a<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"i-47\">1. \u30e1\u30e2\u30ea\u5236\u9650\u306e\u5bfe\u51e6<\/h4>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">\/\/ \u30e1\u30e2\u30ea\u4f7f\u7528\u91cf\u3092\u76e3\u8996\u3059\u308b\u30c6\u30b9\u30c8\u30b1\u30fc\u30b9\nclass MemoryTest extends TestCase\n{\n    protected function setUp(): void\n    {\n        \/\/ \u30c6\u30b9\u30c8\u958b\u59cb\u6642\u306e\u30e1\u30e2\u30ea\u4f7f\u7528\u91cf\u3092\u8a18\u9332\n        $this-&gt;initialMemory = memory_get_usage();\n    }\n\n    protected function tearDown(): void\n    {\n        \/\/ \u30e1\u30e2\u30ea\u30ea\u30fc\u30af\u306e\u691c\u51fa\n        $memoryDiff = memory_get_usage() - $this-&gt;initialMemory;\n        if ($memoryDiff &gt; 1024 * 1024) { \/\/ 1MB\u4ee5\u4e0a\u306e\u5dee\u304c\u3042\u308b\u5834\u5408\n            $this-&gt;fail(\"\u30e1\u30e2\u30ea\u30ea\u30fc\u30af\u306e\u53ef\u80fd\u6027: {$memoryDiff} bytes\");\n        }\n    }\n\n    public function testLargeDataSet(): void\n    {\n        \/\/ \u30e1\u30e2\u30ea\u5236\u9650\u306e\u4e00\u6642\u7684\u306a\u5f15\u304d\u4e0a\u3052\n        ini_set('memory_limit', '512M');\n\n        \/\/ \u5927\u304d\u306a\u30c7\u30fc\u30bf\u30bb\u30c3\u30c8\u306e\u30c6\u30b9\u30c8\n        $largeArray = array_fill(0, 1000000, 'data');\n        $result = $this-&gt;processor-&gt;process($largeArray);\n\n        $this-&gt;assertNotEmpty($result);\n    }\n}<\/pre>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"i-48\">2. \u30d1\u30d5\u30a9\u30fc\u30de\u30f3\u30b9\u6700\u9069\u5316\u30c6\u30af\u30cb\u30c3\u30af<\/h4>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">class PerformanceTest extends TestCase\n{\n    public function testDatabaseOperations(): void\n    {\n        \/\/ \u30c8\u30e9\u30f3\u30b6\u30af\u30b7\u30e7\u30f3\u3092\u4f7f\u7528\u3057\u3066\u30c6\u30b9\u30c8\u3092\u9ad8\u901f\u5316\n        $this-&gt;connection-&gt;beginTransaction();\n\n        try {\n            \/\/ \u30c6\u30b9\u30c8\u30b3\u30fc\u30c9\n            $user = new User();\n            $user-&gt;save();\n\n            $this-&gt;assertDatabaseHas('users', [\n                'id' =&gt; $user-&gt;id\n            ]);\n        } finally {\n            \/\/ \u30c6\u30b9\u30c8\u5f8c\u306b\u30ed\u30fc\u30eb\u30d0\u30c3\u30af\n            $this-&gt;connection-&gt;rollBack();\n        }\n    }\n\n    \/**\n     * @group slow\n     *\/\n    public function testTimeConsumingOperation(): void\n    {\n        \/\/ \u6642\u9593\u306e\u304b\u304b\u308b\u30c6\u30b9\u30c8\u3092\u5206\u96e2\n        $startTime = microtime(true);\n\n        \/\/ \u30c6\u30b9\u30c8\u5b9f\u884c\n        $result = $this-&gt;service-&gt;processLargeData();\n\n        $executionTime = microtime(true) - $startTime;\n        $this-&gt;assertLessThan(\n            5.0,\n            $executionTime,\n            \"\u51e6\u7406\u306b{$executionTime}\u79d2\u304b\u304b\u308a\u307e\u3057\u305f\"\n        );\n    }\n}<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-49\">\u975e\u4e92\u63db\u6027\u306e\u89e3\u6c7a\u3068\u30d0\u30fc\u30b8\u30e7\u30f3\u30a2\u30c3\u30d7\u6642\u306e\u6ce8\u610f\u70b9<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"i-50\">1. PHPUnit 9.x\u304b\u308910.x\u3078\u306e\u79fb\u884c\u5bfe\u5fdc<\/h4>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">\/\/ PHPUnit 9.x \u3067\u306e\u66f8\u304d\u65b9\nclass LegacyTest extends TestCase\n{\n    public function testException(): void\n    {\n        $this-&gt;expectException(Exception::class);\n        throw new Exception('\u30a8\u30e9\u30fc');\n    }\n\n    public function testOutput(): void\n    {\n        $this-&gt;expectOutputString('\u671f\u5f85\u3059\u308b\u51fa\u529b');\n        echo '\u671f\u5f85\u3059\u308b\u51fa\u529b';\n    }\n}\n\n\/\/ PHPUnit 10.x \u3067\u306e\u66f8\u304d\u65b9\nclass ModernTest extends TestCase\n{\n    public function testException(): void\n    {\n        $this-&gt;expectException(Exception::class);\n        $this-&gt;expectExceptionMessage('\u30a8\u30e9\u30fc');\n        throw new Exception('\u30a8\u30e9\u30fc');\n    }\n\n    public function testOutput(): void\n    {\n        $this-&gt;expectOutputString('\u671f\u5f85\u3059\u308b\u51fa\u529b');\n        echo '\u671f\u5f85\u3059\u308b\u51fa\u529b';\n    }\n}<\/pre>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"i-51\">2. \u975e\u63a8\u5968\u6a5f\u80fd\u306e\u7f6e\u304d\u63db\u3048<\/h4>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">\/\/ \u975e\u63a8\u5968\u306e\u66f8\u304d\u65b9\nclass DeprecatedTest extends TestCase\n{\n    public function testOldStyle(): void\n    {\n        $this-&gt;assertInternalType('string', $value);\n        $this-&gt;assertAttributeEquals('expected', 'property', $object);\n    }\n}\n\n\/\/ \u63a8\u5968\u3055\u308c\u308b\u66f8\u304d\u65b9\nclass ModernTest extends TestCase\n{\n    public function testNewStyle(): void\n    {\n        $this-&gt;assertIsString($value);\n        $this-&gt;assertEquals('expected', $object-&gt;property);\n    }\n}<\/pre>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"i-52\">3. \u30d0\u30fc\u30b8\u30e7\u30f3\u30a2\u30c3\u30d7\u6642\u306e\u30c1\u30a7\u30c3\u30af\u30ea\u30b9\u30c8<\/h4>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">class VersionCompatibilityTest extends TestCase\n{\n    public function setUp(): void\n    {\n        \/\/ PHPUnit\u30d0\u30fc\u30b8\u30e7\u30f3\u306e\u78ba\u8a8d\n        if (version_compare(PHPUnit\\Runner\\Version::id(), '10.0.0', '&gt;=')) {\n            \/\/ PHPUnit 10\u4ee5\u964d\u306e\u8a2d\u5b9a\n            $this-&gt;markTestSkipped('\u3053\u306e\u30c6\u30b9\u30c8\u306fPHPUnit 10\u4ee5\u964d\u3067\u306f\u975e\u5bfe\u5fdc');\n        }\n    }\n\n    \/**\n     * @requires PHP &gt;= 8.1\n     *\/\n    public function testPhp81Feature(): void\n    {\n        \/\/ PHP 8.1\u4ee5\u964d\u306e\u6a5f\u80fd\u3092\u30c6\u30b9\u30c8\n        $result = str_contains($haystack, $needle);\n        $this-&gt;assertTrue($result);\n    }\n}<\/pre>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"i-53\">\u4e3b\u8981\u306a\u30c8\u30e9\u30d6\u30eb\u30b7\u30e5\u30fc\u30c6\u30a3\u30f3\u30b0\u306e\u30c1\u30a7\u30c3\u30af\u30ea\u30b9\u30c8<\/h4>\n\n\n\n<ol class=\"wp-block-list\">\n<li>\u30e1\u30e2\u30ea\u95a2\u9023\u306e\u554f\u984c<\/li>\n<\/ol>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u30e1\u30e2\u30ea\u5236\u9650\u306e\u78ba\u8a8d\u3068\u8abf\u6574<\/li>\n\n\n\n<li>\u5927\u304d\u306a\u30c7\u30fc\u30bf\u30bb\u30c3\u30c8\u306e\u5206\u5272\u51e6\u7406<\/li>\n\n\n\n<li>\u30ea\u30bd\u30fc\u30b9\u306e\u9069\u5207\u306a\u89e3\u653e<\/li>\n<\/ul>\n\n\n\n<ol class=\"wp-block-list\">\n<li>\u30d1\u30d5\u30a9\u30fc\u30de\u30f3\u30b9\u554f\u984c<\/li>\n<\/ol>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u30c6\u30b9\u30c8\u306e\u5206\u96e2\u3068\u4e26\u5217\u5b9f\u884c<\/li>\n\n\n\n<li>\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u30c8\u30e9\u30f3\u30b6\u30af\u30b7\u30e7\u30f3\u306e\u6d3b\u7528<\/li>\n\n\n\n<li>\u30c6\u30b9\u30c8\u30b9\u30a4\u30fc\u30c8\u306e\u6700\u9069\u306a\u69cb\u6210<\/li>\n<\/ul>\n\n\n\n<ol class=\"wp-block-list\">\n<li>\u4e92\u63db\u6027\u306e\u554f\u984c<\/li>\n<\/ol>\n\n\n\n<ul class=\"wp-block-list\">\n<li>PHP\u30d0\u30fc\u30b8\u30e7\u30f3\u306e\u78ba\u8a8d<\/li>\n\n\n\n<li>PHPUnit \u30d0\u30fc\u30b8\u30e7\u30f3\u306e\u78ba\u8a8d<\/li>\n\n\n\n<li>\u4f9d\u5b58\u30e9\u30a4\u30d6\u30e9\u30ea\u306e\u4e92\u63db\u6027\u78ba\u8a8d<\/li>\n<\/ul>\n\n\n\n<p>\u3053\u308c\u3089\u306e\u554f\u984c\u306b\u906d\u9047\u3057\u305f\u5834\u5408\u3001\u4e0a\u8a18\u306e\u89e3\u6c7a\u7b56\u3092\u9806\u6b21\u8a66\u3057\u3066\u3044\u304f\u3053\u3068\u3067\u3001\u591a\u304f\u306e\u5834\u5408\u554f\u984c\u3092\u89e3\u6c7a\u3067\u304d\u307e\u3059\u3002<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"i-54\">\u5b9f\u8df5\u7684\u306aPHPUnit\u30c6\u30b9\u30c8\u30b3\u30fc\u30c9\u4f8b\u3068\u30b5\u30f3\u30d7\u30eb\u30d7\u30ed\u30b8\u30a7\u30af\u30c8<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-55\">EC\u30b5\u30a4\u30c8\u306e\u30b7\u30e7\u30c3\u30d4\u30f3\u30b0\u30ab\u30fc\u30c8\u6a5f\u80fd\u306e\u30c6\u30b9\u30c8\u5b9f\u88c5\u4f8b<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"i-56\">1. \u30b7\u30e7\u30c3\u30d4\u30f3\u30b0\u30ab\u30fc\u30c8\u306e\u30c9\u30e1\u30a4\u30f3\u30e2\u30c7\u30eb<\/h4>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">class Cart\n{\n    private array $items = [];\n    private ?DiscountCode $discountCode = null;\n\n    public function addItem(Product $product, int $quantity): void\n    {\n        $this-&gt;items[] = new CartItem($product, $quantity);\n    }\n\n    public function removeItem(string $productId): void\n    {\n        $this-&gt;items = array_filter(\n            $this-&gt;items,\n            fn($item) =&gt; $item-&gt;getProduct()-&gt;getId() !== $productId\n        );\n    }\n\n    public function applyDiscountCode(DiscountCode $code): void\n    {\n        $this-&gt;discountCode = $code;\n    }\n\n    public function calculateTotal(): float\n    {\n        $subtotal = array_reduce(\n            $this-&gt;items,\n            fn($total, $item) =&gt; $total + $item-&gt;getSubtotal(),\n            0.0\n        );\n\n        if ($this-&gt;discountCode) {\n            return $subtotal * (1 - $this-&gt;discountCode-&gt;getDiscountRate());\n        }\n\n        return $subtotal;\n    }\n}<\/pre>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"i-57\">2. \u30ab\u30fc\u30c8\u306e\u30e6\u30cb\u30c3\u30c8\u30c6\u30b9\u30c8<\/h4>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">class CartTest extends TestCase\n{\n    private Cart $cart;\n    private Product $product;\n\n    protected function setUp(): void\n    {\n        $this-&gt;cart = new Cart();\n        $this-&gt;product = new Product(\n            'prod-001',\n            '\u30c6\u30b9\u30c8\u5546\u54c1',\n            1000,\n            10 \/\/ \u5728\u5eab\u6570\n        );\n    }\n\n    \/**\n     * @test\n     *\/\n    public function \u5546\u54c1\u3092\u8ffd\u52a0\u3067\u304d\u308b\u3053\u3068(): void\n    {\n        \/\/ \u5b9f\u884c\n        $this-&gt;cart-&gt;addItem($this-&gt;product, 2);\n\n        \/\/ \u691c\u8a3c\n        $this-&gt;assertEquals(2000, $this-&gt;cart-&gt;calculateTotal());\n    }\n\n    \/**\n     * @test\n     *\/\n    public function \u5546\u54c1\u3092\u524a\u9664\u3067\u304d\u308b\u3053\u3068(): void\n    {\n        \/\/ \u6e96\u5099\n        $this-&gt;cart-&gt;addItem($this-&gt;product, 2);\n\n        \/\/ \u5b9f\u884c\n        $this-&gt;cart-&gt;removeItem('prod-001');\n\n        \/\/ \u691c\u8a3c\n        $this-&gt;assertEquals(0, $this-&gt;cart-&gt;calculateTotal());\n    }\n\n    \/**\n     * @test\n     *\/\n    public function \u5272\u5f15\u30b3\u30fc\u30c9\u3092\u9069\u7528\u3067\u304d\u308b\u3053\u3068(): void\n    {\n        \/\/ \u6e96\u5099\n        $this-&gt;cart-&gt;addItem($this-&gt;product, 2);\n        $discountCode = new DiscountCode('SAVE10', 0.1); \/\/ 10%\u5272\u5f15\n\n        \/\/ \u5b9f\u884c\n        $this-&gt;cart-&gt;applyDiscountCode($discountCode);\n\n        \/\/ \u691c\u8a3c\n        $this-&gt;assertEquals(1800, $this-&gt;cart-&gt;calculateTotal());\n    }\n\n    \/**\n     * @test\n     *\/\n    public function \u5728\u5eab\u6570\u4ee5\u4e0a\u306e\u5546\u54c1\u306f\u8ffd\u52a0\u3067\u304d\u306a\u3044\u3053\u3068(): void\n    {\n        $this-&gt;expectException(InvalidQuantityException::class);\n        $this-&gt;cart-&gt;addItem($this-&gt;product, 11);\n    }\n}<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-58\">\u30e6\u30fc\u30b6\u30fc\u8a8d\u8a3c\u30b7\u30b9\u30c6\u30e0\u306e\u30c6\u30b9\u30c8\u30b1\u30fc\u30b9\u4f5c\u6210<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"i-59\">1. \u8a8d\u8a3c\u30b5\u30fc\u30d3\u30b9\u306e\u5b9f\u88c5<\/h4>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">class AuthenticationService\n{\n    private UserRepository $userRepository;\n    private PasswordHasher $passwordHasher;\n    private TokenGenerator $tokenGenerator;\n\n    public function __construct(\n        UserRepository $userRepository,\n        PasswordHasher $passwordHasher,\n        TokenGenerator $tokenGenerator\n    ) {\n        $this-&gt;userRepository = $userRepository;\n        $this-&gt;passwordHasher = $passwordHasher;\n        $this-&gt;tokenGenerator = $tokenGenerator;\n    }\n\n    public function authenticate(string $email, string $password): AuthResult\n    {\n        $user = $this-&gt;userRepository-&gt;findByEmail($email);\n\n        if (!$user) {\n            throw new UserNotFoundException();\n        }\n\n        if (!$this-&gt;passwordHasher-&gt;verify($password, $user-&gt;getPasswordHash())) {\n            throw new InvalidPasswordException();\n        }\n\n        if (!$user-&gt;isActive()) {\n            throw new InactiveUserException();\n        }\n\n        return new AuthResult(\n            $user,\n            $this-&gt;tokenGenerator-&gt;generate($user)\n        );\n    }\n}<\/pre>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"i-60\">2. \u8a8d\u8a3c\u30b5\u30fc\u30d3\u30b9\u306e\u30c6\u30b9\u30c8<\/h4>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">class AuthenticationServiceTest extends TestCase\n{\n    private AuthenticationService $service;\n    private MockObject $userRepository;\n    private MockObject $passwordHasher;\n    private MockObject $tokenGenerator;\n\n    protected function setUp(): void\n    {\n        $this-&gt;userRepository = $this-&gt;createMock(UserRepository::class);\n        $this-&gt;passwordHasher = $this-&gt;createMock(PasswordHasher::class);\n        $this-&gt;tokenGenerator = $this-&gt;createMock(TokenGenerator::class);\n\n        $this-&gt;service = new AuthenticationService(\n            $this-&gt;userRepository,\n            $this-&gt;passwordHasher,\n            $this-&gt;tokenGenerator\n        );\n    }\n\n    \/**\n     * @test\n     *\/\n    public function \u6b63\u3057\u3044\u8a8d\u8a3c\u60c5\u5831\u3067\u8a8d\u8a3c\u3067\u304d\u308b\u3053\u3068(): void\n    {\n        \/\/ \u6e96\u5099\n        $email = 'test@example.com';\n        $password = 'password123';\n        $hashedPassword = 'hashed_password';\n        $token = 'generated_token';\n\n        $user = new User($email, $hashedPassword);\n        $user-&gt;activate();\n\n        $this-&gt;userRepository\n            -&gt;expects($this-&gt;once())\n            -&gt;method('findByEmail')\n            -&gt;with($email)\n            -&gt;willReturn($user);\n\n        $this-&gt;passwordHasher\n            -&gt;expects($this-&gt;once())\n            -&gt;method('verify')\n            -&gt;with($password, $hashedPassword)\n            -&gt;willReturn(true);\n\n        $this-&gt;tokenGenerator\n            -&gt;expects($this-&gt;once())\n            -&gt;method('generate')\n            -&gt;with($user)\n            -&gt;willReturn($token);\n\n        \/\/ \u5b9f\u884c\n        $result = $this-&gt;service-&gt;authenticate($email, $password);\n\n        \/\/ \u691c\u8a3c\n        $this-&gt;assertInstanceOf(AuthResult::class, $result);\n        $this-&gt;assertSame($user, $result-&gt;getUser());\n        $this-&gt;assertEquals($token, $result-&gt;getToken());\n    }\n\n    \/**\n     * @test\n     *\/\n    public function \u5b58\u5728\u3057\u306a\u3044\u30e6\u30fc\u30b6\u30fc\u306e\u5834\u5408\u306f\u4f8b\u5916\u304c\u767a\u751f\u3059\u308b\u3053\u3068(): void\n    {\n        $this-&gt;userRepository\n            -&gt;method('findByEmail')\n            -&gt;willReturn(null);\n\n        $this-&gt;expectException(UserNotFoundException::class);\n        $this-&gt;service-&gt;authenticate('invalid@example.com', 'password');\n    }\n}<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-61\">API\u30a8\u30f3\u30c9\u30dd\u30a4\u30f3\u30c8\u306e\u30c6\u30b9\u30c8\u5b9f\u88c5\u65b9\u6cd5<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"i-62\">1. RESTful API\u30b3\u30f3\u30c8\u30ed\u30fc\u30e9\u30fc<\/h4>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">class ProductApiController\n{\n    private ProductRepository $repository;\n    private ProductValidator $validator;\n\n    public function create(Request $request): JsonResponse\n    {\n        try {\n            $data = $request-&gt;getJsonData();\n\n            $this-&gt;validator-&gt;validate($data);\n\n            $product = new Product(\n                $data['name'],\n                $data['price'],\n                $data['description']\n            );\n\n            $savedProduct = $this-&gt;repository-&gt;save($product);\n\n            return new JsonResponse(\n                ['id' =&gt; $savedProduct-&gt;getId()],\n                201\n            );\n        } catch (ValidationException $e) {\n            return new JsonResponse(\n                ['errors' =&gt; $e-&gt;getErrors()],\n                400\n            );\n        } catch (Exception $e) {\n            return new JsonResponse(\n                ['error' =&gt; 'Internal Server Error'],\n                500\n            );\n        }\n    }\n}<\/pre>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"i-63\">2. API\u30a8\u30f3\u30c9\u30dd\u30a4\u30f3\u30c8\u306e\u30c6\u30b9\u30c8<\/h4>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">class ProductApiControllerTest extends TestCase\n{\n    private ProductApiController $controller;\n    private MockObject $repository;\n    private MockObject $validator;\n\n    protected function setUp(): void\n    {\n        $this-&gt;repository = $this-&gt;createMock(ProductRepository::class);\n        $this-&gt;validator = $this-&gt;createMock(ProductValidator::class);\n        $this-&gt;controller = new ProductApiController(\n            $this-&gt;repository,\n            $this-&gt;validator\n        );\n    }\n\n    \/**\n     * @test\n     *\/\n    public function \u6b63\u5e38\u306a\u5546\u54c1\u767b\u9332\u304c\u3067\u304d\u308b\u3053\u3068(): void\n    {\n        \/\/ \u6e96\u5099\n        $requestData = [\n            'name' =&gt; '\u30c6\u30b9\u30c8\u5546\u54c1',\n            'price' =&gt; 1000,\n            'description' =&gt; '\u5546\u54c1\u306e\u8aac\u660e'\n        ];\n\n        $request = new Request();\n        $request-&gt;setJsonData($requestData);\n\n        $savedProduct = new Product(\n            $requestData['name'],\n            $requestData['price'],\n            $requestData['description']\n        );\n        $savedProduct-&gt;setId('prod-001');\n\n        $this-&gt;validator\n            -&gt;expects($this-&gt;once())\n            -&gt;method('validate')\n            -&gt;with($requestData);\n\n        $this-&gt;repository\n            -&gt;expects($this-&gt;once())\n            -&gt;method('save')\n            -&gt;willReturn($savedProduct);\n\n        \/\/ \u5b9f\u884c\n        $response = $this-&gt;controller-&gt;create($request);\n\n        \/\/ \u691c\u8a3c\n        $this-&gt;assertEquals(201, $response-&gt;getStatusCode());\n        $this-&gt;assertEquals(\n            ['id' =&gt; 'prod-001'],\n            $response-&gt;getJsonData()\n        );\n    }\n\n    \/**\n     * @test\n     *\/\n    public function \u30d0\u30ea\u30c7\u30fc\u30b7\u30e7\u30f3\u30a8\u30e9\u30fc\u6642\u306f400\u30a8\u30e9\u30fc\u3092\u8fd4\u3059\u3053\u3068(): void\n    {\n        \/\/ \u6e96\u5099\n        $requestData = [\n            'name' =&gt; '', \/\/ \u7a7a\u306e\u540d\u524d\u306f\u7121\u52b9\n            'price' =&gt; -100, \/\/ \u8ca0\u306e\u4fa1\u683c\u306f\u7121\u52b9\n            'description' =&gt; 'OK'\n        ];\n\n        $request = new Request();\n        $request-&gt;setJsonData($requestData);\n\n        $this-&gt;validator\n            -&gt;method('validate')\n            -&gt;willThrowException(new ValidationException([\n                'name' =&gt; ['\u5546\u54c1\u540d\u306f\u5fc5\u9808\u3067\u3059'],\n                'price' =&gt; ['\u4fa1\u683c\u306f0\u4ee5\u4e0a\u3067\u3042\u308b\u5fc5\u8981\u304c\u3042\u308a\u307e\u3059']\n            ]));\n\n        \/\/ \u5b9f\u884c\n        $response = $this-&gt;controller-&gt;create($request);\n\n        \/\/ \u691c\u8a3c\n        $this-&gt;assertEquals(400, $response-&gt;getStatusCode());\n        $this-&gt;assertArrayHasKey('errors', $response-&gt;getJsonData());\n    }\n}<\/pre>\n\n\n\n<p>\u3053\u308c\u3089\u306e\u5b9f\u88c5\u4f8b\u306f\u3001\u5b9f\u969b\u306e\u30d7\u30ed\u30b8\u30a7\u30af\u30c8\u3067\u3088\u304f\u4f7f\u7528\u3055\u308c\u308b\u6a5f\u80fd\u306e\u30c6\u30b9\u30c8\u30d1\u30bf\u30fc\u30f3\u3092\u793a\u3057\u3066\u3044\u307e\u3059\u3002\u30c6\u30b9\u30c8\u30b3\u30fc\u30c9\u306f\u3001\u6a5f\u80fd\u306e\u4ed5\u69d8\u3092\u660e\u78ba\u306b\u793a\u3059\u30c9\u30ad\u30e5\u30e1\u30f3\u30c8\u3068\u3057\u3066\u3082\u6a5f\u80fd\u3057\u3001\u65b0\u3057\u3044\u30c1\u30fc\u30e0\u30e1\u30f3\u30d0\u30fc\u306e\u53c2\u8003\u8cc7\u6599\u3068\u3057\u3066\u3082\u6d3b\u7528\u3067\u304d\u307e\u3059\u3002<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Warning: Undefined array key &#8220;is_admin&#8221; in \/home\/xs392991\/dexall.co.jp\/public_html\/articles\/wp-content\/themes\/ &#8230; <\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[12],"tags":[],"class_list":{"0":"post-2460","1":"post","2":"type-post","3":"status-publish","4":"format-standard","6":"category-php","7":"nothumb"},"_links":{"self":[{"href":"https:\/\/dexall.co.jp\/articles\/index.php?rest_route=\/wp\/v2\/posts\/2460","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/dexall.co.jp\/articles\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/dexall.co.jp\/articles\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/dexall.co.jp\/articles\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/dexall.co.jp\/articles\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=2460"}],"version-history":[{"count":2,"href":"https:\/\/dexall.co.jp\/articles\/index.php?rest_route=\/wp\/v2\/posts\/2460\/revisions"}],"predecessor-version":[{"id":2462,"href":"https:\/\/dexall.co.jp\/articles\/index.php?rest_route=\/wp\/v2\/posts\/2460\/revisions\/2462"}],"wp:attachment":[{"href":"https:\/\/dexall.co.jp\/articles\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=2460"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/dexall.co.jp\/articles\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=2460"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/dexall.co.jp\/articles\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=2460"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}