{"id":1235,"date":"2025-03-24T08:52:31","date_gmt":"2025-03-23T23:52:31","guid":{"rendered":"https:\/\/dexall.co.jp\/articles\/?p=1235"},"modified":"2025-03-24T08:52:31","modified_gmt":"2025-03-23T23:52:31","slug":"%e3%80%90%e4%bf%9d%e5%ad%98%e7%89%88%e3%80%91ruby-on-rails%e3%81%aerspec%e3%83%86%e3%82%b9%e3%83%88%e5%ae%9f%e8%a3%85%e5%ae%8c%e5%85%a8%e3%82%ac%e3%82%a4%e3%83%89%ef%bc%81%e7%8f%be%e5%a0%b4%e3%81%a7","status":"publish","type":"post","link":"https:\/\/dexall.co.jp\/articles\/?p=1235","title":{"rendered":"\u3010\u4fdd\u5b58\u7248\u3011Ruby on Rails\u306eRSpec\u30c6\u30b9\u30c8\u5b9f\u88c5\u5b8c\u5168\u30ac\u30a4\u30c9\uff01\u73fe\u5834\u3067\u4f7f\u3048\u308b15\u306e\u30d9\u30b9\u30c8\u30d7\u30e9\u30af\u30c6\u30a3\u30b9"},"content":{"rendered":"\n<h1 class=\"wp-block-heading\" id=\"i-0\">RSpec\u3068\u306f\uff1fRails \u30d7\u30ed\u30b8\u30a7\u30af\u30c8\u306b\u5fc5\u8981\u306a\u30c6\u30b9\u30c8\u30d5\u30ec\u30fc\u30e0\u30ef\u30fc\u30af<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">Ruby on Rails\u306e\u958b\u767a\u306b\u304a\u3044\u3066\u3001\u54c1\u8cea\u306e\u9ad8\u3044\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u3092\u7d99\u7d9a\u7684\u306b\u63d0\u4f9b\u3059\u308b\u305f\u3081\u306b\u306f\u3001\u9069\u5207\u306a\u30c6\u30b9\u30c8\u6226\u7565\u304c\u4e0d\u53ef\u6b20\u3067\u3059\u3002\u305d\u306e\u4e2d\u3067\u3082RSpec\u306f\u3001Ruby\u30b3\u30df\u30e5\u30cb\u30c6\u30a3\u3067\u6700\u3082\u4eba\u6c17\u306e\u3042\u308b\u30c6\u30b9\u30c8\u30d5\u30ec\u30fc\u30e0\u30ef\u30fc\u30af\u3068\u3057\u3066\u77e5\u3089\u308c\u3066\u3044\u307e\u3059\u3002<\/p>\n\n\n\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\">RSpec\u3068\u306f\uff1fRails \u30d7\u30ed\u30b8\u30a7\u30af\u30c8\u306b\u5fc5\u8981\u306a\u30c6\u30b9\u30c8\u30d5\u30ec\u30fc\u30e0\u30ef\u30fc\u30af<\/a>    <ul class=\"menu_level_1\">      <li class=\"first\">        <a href=\"#i-1\">RSpec\u304c\u9078\u3070\u308c\u308b3\u3064\u306e\u7406\u7531<\/a>      <\/li>      <li class=\"last\">        <a href=\"#i-5\">RSpec\u3068Minitest\u3001\u3069\u3061\u3089\u3092\u9078\u3076\u3079\u304d\u304b<\/a>      <\/li>    <\/ul>  <\/li>  <li>    <a href=\"#i-6\">RSpec\u306e\u57fa\u672c\u30bb\u30c3\u30c8\u30a2\u30c3\u30d7\u3068\u5b9f\u884c\u74b0\u5883\u306e\u69cb\u7bc9<\/a>    <ul class=\"menu_level_1\">      <li class=\"first\">        <a href=\"#i-7\">Gemfile\u306e\u8a2d\u5b9a\u3068\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u624b\u9806<\/a>      <\/li>      <li>        <a href=\"#i-8\">\u30c6\u30b9\u30c8\u306e\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u306e\u6e96\u5099\u3068\u8a2d\u5b9a<\/a>      <\/li>      <li class=\"last\">        <a href=\"#i-12\">\u52b9\u7387\u7684\u306a\u30c6\u30b9\u30c8\u5b9f\u884c\u306e\u305f\u3081\u306e\u74b0\u5883\u5909\u6570\u8a2d\u5b9a<\/a>      <\/li>    <\/ul>  <\/li>  <li>    <a href=\"#i-16\">\u73fe\u5834\u3067\u4f7f\u3048\u308bRSpec\u30c6\u30b9\u30c8\u30b3\u30fc\u30c9\u4f5c\u6210\u306e\u5177\u4f53\u4f8b<\/a>    <ul class=\"menu_level_1\">      <li class=\"first\">        <a href=\"#i-17\">\u30e2\u30c7\u30eb\u30b9\u30da\u30c3\u30af\u306e\u66f8\u304d\u65b9\u3068\u30d0\u30ea\u30c7\u30fc\u30b7\u30e7\u30f3\u30c6\u30b9\u30c8<\/a>      <\/li>      <li>        <a href=\"#i-19\">\u30b3\u30f3\u30c8\u30ed\u30fc\u30e9\u30b9\u30da\u30c3\u30af\u306b\u3088\u308b\u30a2\u30af\u30b7\u30e7\u30f3\u5358\u4f4d\u306e\u30c6\u30b9\u30c8<\/a>      <\/li>      <li class=\"last\">        <a href=\"#i-21\">\u30b7\u30b9\u30c6\u30e0\u30b9\u30da\u30c3\u30af\u3067\u306e\u30e6\u30fc\u30b6\u30fc\u64cd\u4f5c\u30b7\u30df\u30e5\u30ec\u30fc\u30b7\u30e7\u30f3<\/a>      <\/li>    <\/ul>  <\/li>  <li>    <a href=\"#i-23\">\u30c6\u30b9\u30c8\u518d\u73fe\u6027\u3092\u9ad8\u3081\u308b\u5b9f\u8df5\u30c6\u30af\u30cb\u30c3\u30af<\/a>    <ul class=\"menu_level_1\">      <li class=\"first\">        <a href=\"#i-24\">FactoryBot\u3092\u6d3b\u7528\u3057\u305f\u30c6\u30b9\u30c8\u30c7\u30fc\u30bf\u7ba1\u7406<\/a>      <\/li>      <li>        <a href=\"#i-27\">\u5171\u901a\u5316\u3067\u304d\u308b\u30c6\u30b9\u30c8\u30b3\u30fc\u30c9\u3068shared_examples<\/a>      <\/li>      <li class=\"last\">        <a href=\"#i-30\">\u30e2\u30c3\u30af\u30fb\u30b9\u30bf\u30d6\u3092\u4f7f\u3063\u305f\u5916\u90e8\u4f9d\u5b58\u306e\u5236\u5fa1<\/a>      <\/li>    <\/ul>  <\/li>  <li>    <a href=\"#i-33\">\u30c6\u30b9\u30c8\u30d1\u30d5\u30a9\u30fc\u30de\u30f3\u30b9\u3092\u6539\u5584\u3059\u308b\u5b9f\u88c5\u306e\u30b3\u30c4<\/a>    <ul class=\"menu_level_1\">      <li class=\"first\">        <a href=\"#i-34\">\u30c6\u30b9\u30c8\u6642\u9593\u309250%\u524a\u6e1b\u3059\u308b\u8a2d\u5b9a\u30c6\u30af\u30cb\u30c3\u30af<\/a>      <\/li>      <li>        <a href=\"#i-38\">\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u6226\u7565\u306e\u6700\u9069\u5316<\/a>      <\/li>      <li class=\"last\">        <a href=\"#i-42\">\u30dc\u30fc\u30c0\u30fc\u30c6\u30b9\u30c8\u5b9f\u884c\u306e\u5c0e\u5165\u3068\u6ce8\u610f\u70b9<\/a>      <\/li>    <\/ul>  <\/li>  <li class=\"last\">    <a href=\"#i-45\">\u5b9f\u8df5\u7684\u306a\u30c6\u30b9\u30c8\u30b1\u30fc\u30b9\u30b9\u30bf\u30c7\u30a3<\/a>    <ul class=\"menu_level_1\">      <li class=\"first\">        <a href=\"#i-46\">API\u8a8d\u8a3c\u6a5f\u80fd\u306e\u30c6\u30b9\u30c8\u30b3\u30fc\u30c9\u5b9f\u88c5\u4f8b<\/a>      <\/li>      <li>        <a href=\"#i-48\">\u975e\u540c\u671f\u51e6\u7406\u3092\u542b\u3080\u30b8\u30e7\u30d6\u306e\u30c6\u30b9\u30c8\u65b9\u6cd5<\/a>      <\/li>      <li class=\"last\">        <a href=\"#i-50\">\u8907\u96d1\u306a\u691c\u7d22\u6a5f\u80fd\u306e\u30c6\u30b9\u30c8\u30a2\u30d7\u30ed\u30fc\u30c1<\/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-1\">RSpec\u304c\u9078\u3070\u308c\u308b3\u3064\u306e\u7406\u7531<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-2\">1. \u76f4\u611f\u7684\u306a\u6587\u6cd5\u3068\u9ad8\u3044\u53ef\u8aad\u6027<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">RSpec\u306e\u6700\u5927\u306e\u7279\u5fb4\u306f\u3001\u305d\u306e\u8aad\u307f\u3084\u3059\u3055\u306b\u3042\u308a\u307e\u3059\u3002\u30c6\u30b9\u30c8\u30b3\u30fc\u30c9\u304c\u81ea\u7136\u8a00\u8a9e\u306b\u8fd1\u3044\u5f62\u3067\u8a18\u8ff0\u3067\u304d\u308b\u305f\u3081\u3001\u30c6\u30b9\u30c8\u306e\u610f\u56f3\u304c\u660e\u78ba\u306b\u4f1d\u308f\u308a\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=\"\">describe User do\n  it \"is valid with a name and email\" do\n    user = User.new(\n      name: \"\u5c71\u7530\u592a\u90ce\",\n      email: \"taro@example.com\"\n    )\n    expect(user).to be_valid\n  end\nend<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">\u3053\u306e\u4f8b\u304b\u3089\u308f\u304b\u308b\u3088\u3046\u306b\u3001\u300c\u4f55\u3092\u30c6\u30b9\u30c8\u3057\u3066\u3044\u308b\u304b\u300d\u304c\u82f1\u8a9e\u306e\u6587\u7ae0\u3068\u3057\u3066\u7406\u89e3\u3067\u304d\u307e\u3059\u3002\u3053\u308c\u306b\u3088\u308a\uff1a<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u30c6\u30b9\u30c8\u306e\u4fdd\u5b88\u6027\u304c\u9ad8\u307e\u308b<\/li>\n\n\n\n<li>\u30c1\u30fc\u30e0\u5185\u3067\u306e\u30b3\u30fc\u30c9\u30ec\u30d3\u30e5\u30fc\u304c\u52b9\u7387\u5316\u3055\u308c\u308b<\/li>\n\n\n\n<li>\u65b0\u898f\u30e1\u30f3\u30d0\u30fc\u306e\u5b66\u7fd2\u30b3\u30b9\u30c8\u304c\u4f4e\u6e1b\u3055\u308c\u308b<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-3\">2. \u8c4a\u5bcc\u306a\u30de\u30c3\u30c1\u30e3\u30fc\u3068\u30d8\u30eb\u30d1\u30fc<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">RSpec\u306b\u306f\u3001\u69d8\u3005\u306a\u30c6\u30b9\u30c8\u30b7\u30ca\u30ea\u30aa\u306b\u5bfe\u5fdc\u3067\u304d\u308b\u8c4a\u5bcc\u306a\u30de\u30c3\u30c1\u30e3\u30fc\u304c\u7528\u610f\u3055\u308c\u3066\u3044\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=\"\"># \u7b49\u4fa1\u6027\u306e\u30c6\u30b9\u30c8\nexpect(user.name).to eq(\"\u5c71\u7530\u592a\u90ce\")\n\n# \u771f\u507d\u5024\u306e\u30c6\u30b9\u30c8\nexpect(user.admin?).to be_truthy\n\n# \u30a8\u30e9\u30fc\u306e\u767a\u751f\u3092\u78ba\u8a8d\nexpect { user.save! }.to raise_error(ActiveRecord::RecordInvalid)\n\n# \u30b3\u30ec\u30af\u30b7\u30e7\u30f3\u306e\u5185\u5bb9\u78ba\u8a8d\nexpect(users).to include(user)<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-4\">3. \u5f37\u529b\u306a\u30e2\u30c3\u30af\u30fb\u30b9\u30bf\u30d6\u6a5f\u80fd<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">\u5916\u90e8\u30b5\u30fc\u30d3\u30b9\u3068\u306e\u9023\u643a\u3084\u8907\u96d1\u306a\u4f9d\u5b58\u95a2\u4fc2\u3092\u6301\u3064\u30b3\u30fc\u30c9\u306e\u30c6\u30b9\u30c8\u3082\u3001RSpec\u306a\u3089\u7c21\u5358\u306b\u5b9f\u73fe\u3067\u304d\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=\"\"># \u30e2\u30c3\u30af\u306e\u4f8b\nallow(PaymentGateway).to receive(:charge).and_return(true)\n\n# \u30b9\u30bf\u30d6\u306e\u4f8b\nallow(user).to receive(:premium?).and_return(true)<\/pre>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"i-5\">RSpec\u3068Minitest\u3001\u3069\u3061\u3089\u3092\u9078\u3076\u3079\u304d\u304b<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Rails\u306e\u30c7\u30d5\u30a9\u30eb\u30c8\u30c6\u30b9\u30c8\u30d5\u30ec\u30fc\u30e0\u30ef\u30fc\u30af\u3067\u3042\u308bMinitest\u3068RSpec\u306e\u6bd4\u8f03\u8868\uff1a<\/p>\n\n\n<div id=\"id-7493a60b-aae7-40dc-a095-64667ea23933\">\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>\u6a5f\u80fd<\/th><th>RSpec<\/th><th>Minitest<\/th><\/tr><\/thead><tbody><tr><td>\u6587\u6cd5<\/td><td>BDD\u98a8\u306e\u81ea\u7136\u306a\u8a18\u8ff0<\/td><td>\u3088\u308aRuby\u3089\u3057\u3044\u7c21\u6f54\u306a\u8a18\u8ff0<\/td><\/tr><tr><td>\u5b66\u7fd2\u66f2\u7dda<\/td><td>\u3084\u3084\u6025\uff08\u6a5f\u80fd\u304c\u8c4a\u5bcc\uff09<\/td><td>\u7de9\u3084\u304b\uff08\u30b7\u30f3\u30d7\u30eb\uff09<\/td><\/tr><tr><td>\u30bb\u30c3\u30c8\u30a2\u30c3\u30d7<\/td><td>\u8ffd\u52a0\u306e\u8a2d\u5b9a\u304c\u5fc5\u8981<\/td><td>Rails\u6a19\u6e96\u3067\u5229\u7528\u53ef\u80fd<\/td><\/tr><tr><td>\u30b3\u30df\u30e5\u30cb\u30c6\u30a3<\/td><td>\u5927\u304d\u304f\u3001\u60c5\u5831\u304c\u8c4a\u5bcc<\/td><td>\u4e2d\u898f\u6a21\u3060\u304c\u6210\u9577\u4e2d<\/td><\/tr><tr><td>\u5b9f\u884c\u901f\u5ea6<\/td><td>\u82e5\u5e72\u9045\u3044<\/td><td>\u9ad8\u901f<\/td><\/tr><tr><td>\u6a5f\u80fd\u306e\u8c4a\u5bcc\u3055<\/td><td>\u975e\u5e38\u306b\u8c4a\u5bcc<\/td><td>\u5fc5\u8981\u6700\u5c0f\u9650<\/td><\/tr><\/tbody><\/table><\/figure>\n<\/div>\n\n\n<p class=\"wp-block-paragraph\">\u9078\u629e\u306e\u5224\u65ad\u57fa\u6e96\uff1a<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>RSpec\u3092\u9078\u3076\u3079\u304d\u5834\u5408\uff1a<\/li>\n<\/ol>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u3088\u308a\u8868\u73fe\u529b\u8c4a\u304b\u306a\u30c6\u30b9\u30c8\u3092\u66f8\u304d\u305f\u3044<\/li>\n\n\n\n<li>\u30c1\u30fc\u30e0\u5168\u4f53\u3067\u30c6\u30b9\u30c8\u306e\u53ef\u8aad\u6027\u3092\u91cd\u8996\u3057\u3066\u3044\u308b<\/li>\n\n\n\n<li>\u30e2\u30c3\u30af\u30fb\u30b9\u30bf\u30d6\u3092\u591a\u7528\u3059\u308b\u8907\u96d1\u306a\u30c6\u30b9\u30c8\u304c\u5fc5\u8981<\/li>\n<\/ul>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Minitest\u3092\u9078\u3076\u3079\u304d\u5834\u5408\uff1a<\/li>\n<\/ol>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u3088\u308a\u30b7\u30f3\u30d7\u30eb\u306a\u69cb\u6210\u3092\u597d\u3080<\/li>\n\n\n\n<li>\u5b9f\u884c\u901f\u5ea6\u3092\u6700\u512a\u5148\u3059\u308b<\/li>\n\n\n\n<li>Rails\u306e\u30c7\u30d5\u30a9\u30eb\u30c8\u6a5f\u80fd\u3067\u5341\u5206<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">\u591a\u304f\u306e\u73fe\u5834\u3067\u306f\u3001\u4ee5\u4e0b\u306e\u7406\u7531\u304b\u3089RSpec\u304c\u9078\u3070\u308c\u308b\u50be\u5411\u306b\u3042\u308a\u307e\u3059\uff1a<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u30c6\u30b9\u30c8\u30b3\u30fc\u30c9\u306e\u610f\u56f3\u304c\u660e\u78ba\u3067\u4fdd\u5b88\u3057\u3084\u3059\u3044<\/li>\n\n\n\n<li>\u8c4a\u5bcc\u306a\u30a8\u30b3\u30b7\u30b9\u30c6\u30e0\u3068\u30b3\u30df\u30e5\u30cb\u30c6\u30a3\u30b5\u30dd\u30fc\u30c8<\/li>\n\n\n\n<li>\u3088\u308a\u8a73\u7d30\u306a\u30c6\u30b9\u30c8\u30b7\u30ca\u30ea\u30aa\u306e\u8a18\u8ff0\u304c\u53ef\u80fd<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">\u7279\u306b\u5927\u898f\u6a21\u306a\u30d7\u30ed\u30b8\u30a7\u30af\u30c8\u3084\u3001\u54c1\u8cea\u8981\u4ef6\u306e\u53b3\u3057\u3044\u30d7\u30ed\u30b8\u30a7\u30af\u30c8\u3067\u306f\u3001RSpec\u306e\u5229\u70b9\u304c\u6d3b\u304d\u3066\u304d\u307e\u3059\u3002<\/p>\n\n\n\n<h1 class=\"wp-block-heading\" id=\"i-6\">RSpec\u306e\u57fa\u672c\u30bb\u30c3\u30c8\u30a2\u30c3\u30d7\u3068\u5b9f\u884c\u74b0\u5883\u306e\u69cb\u7bc9<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">\u52b9\u7387\u7684\u306a\u30c6\u30b9\u30c8\u99c6\u52d5\u958b\u767a\u3092\u5b9f\u73fe\u3059\u308b\u305f\u3081\u306b\u3001\u9069\u5207\u306aRSpec\u74b0\u5883\u306e\u69cb\u7bc9\u306f\u975e\u5e38\u306b\u91cd\u8981\u3067\u3059\u3002\u3053\u3053\u3067\u306f\u3001\u5b9f\u52d9\u3067\u4f7f\u3048\u308b\u672c\u683c\u7684\u306aRSpec\u74b0\u5883\u306e\u69cb\u7bc9\u624b\u9806\u3092\u8a73\u3057\u304f\u89e3\u8aac\u3057\u307e\u3059\u3002<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"i-7\">Gemfile\u306e\u8a2d\u5b9a\u3068\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u624b\u9806<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">\u307e\u305a\u3001\u5fc5\u8981\u306agem\u3092Gemfile\u306b\u8ffd\u52a0\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=\"\">group :development, :test do\n  # RSpec\u672c\u4f53\n  gem 'rspec-rails', '~&gt; 6.0.0'\n\n  # \u30c6\u30b9\u30c8\u30c7\u30fc\u30bf\u306e\u4f5c\u6210\n  gem 'factory_bot_rails'\n\n  # \u30c6\u30b9\u30c8\u30c7\u30fc\u30bf\u306e\u30af\u30ea\u30fc\u30f3\u30a2\u30c3\u30d7\n  gem 'database_cleaner'\n\n  # \u30c6\u30b9\u30c8\u306e\u30a8\u30e9\u30fc\u8868\u793a\u3092\u898b\u3084\u3059\u304f\n  gem 'spring-commands-rspec'\n\n  # \u30b3\u30fc\u30c9\u30ab\u30d0\u30ec\u30c3\u30b8\u306e\u8a08\u6e2c\n  gem 'simplecov', require: false\nend<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u624b\u9806\uff1a<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Bundler\u3067gem\u3092\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\uff1a<\/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=\"\">bundle install<\/pre>\n\n\n\n<ol start=\"2\" class=\"wp-block-list\">\n<li>RSpec\u306e\u521d\u671f\u8a2d\u5b9a\u3092\u5b9f\u884c\uff1a<\/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=\"\">rails generate rspec:install<\/pre>\n\n\n\n<ol start=\"3\" class=\"wp-block-list\">\n<li>\u751f\u6210\u3055\u308c\u305f\u8a2d\u5b9a\u30d5\u30a1\u30a4\u30eb\u306e\u78ba\u8a8d\uff1a<\/li>\n<\/ol>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>spec\/spec_helper.rb<\/code><\/li>\n\n\n\n<li><code>spec\/rails_helper.rb<\/code><\/li>\n\n\n\n<li><code>.rspec<\/code><\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"i-8\">\u30c6\u30b9\u30c8\u306e\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u306e\u6e96\u5099\u3068\u8a2d\u5b9a<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-9\">1. database.yml\u306e\u8a2d\u5b9a<\/h3>\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=\"\">test:\n  adapter: postgresql  # \u307e\u305f\u306f\u4f7f\u7528\u3059\u308bDB\u306b\u5fdc\u3058\u3066\u5909\u66f4\n  database: your_app_test\n  host: localhost\n  pool: 5\n  timeout: 5000<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-10\">2. \u30c6\u30b9\u30c8\u7528\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u306e\u30bb\u30c3\u30c8\u30a2\u30c3\u30d7<\/h3>\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\u7528DB\u306e\u4f5c\u6210\nrails db:create RAILS_ENV=test\n\n# \u30de\u30a4\u30b0\u30ec\u30fc\u30b7\u30e7\u30f3\u306e\u5b9f\u884c\nrails db:migrate RAILS_ENV=test<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-11\">3. DatabaseCleaner\u306e\u8a2d\u5b9a\uff08spec\/rails_helper.rb\uff09<\/h3>\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=\"\">RSpec.configure do |config|\n  config.before(:suite) do\n    DatabaseCleaner.strategy = :transaction\n    DatabaseCleaner.clean_with(:truncation)\n  end\n\n  config.around(:each) do |example|\n    DatabaseCleaner.cleaning do\n      example.run\n    end\n  end\nend<\/pre>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"i-12\">\u52b9\u7387\u7684\u306a\u30c6\u30b9\u30c8\u5b9f\u884c\u306e\u305f\u3081\u306e\u74b0\u5883\u5909\u6570\u8a2d\u5b9a<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-13\">1. .env.test\u30d5\u30a1\u30a4\u30eb\u306e\u4f5c\u6210<\/h3>\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=\"\"># .env.test\nRAILS_ENV=test\nRACK_ENV=test\nDATABASE_URL=postgresql:\/\/localhost\/your_app_test<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-14\">2. config\/environments\/test.rb\u306e\u6700\u9069\u5316<\/h3>\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=\"\">Rails.application.configure do\n  # \u30c6\u30b9\u30c8\u306e\u5b9f\u884c\u901f\u5ea6\u3092\u4e0a\u3052\u308b\u305f\u3081\u306e\u8a2d\u5b9a\n  config.cache_classes = true\n  config.eager_load = false\n  config.public_file_server.enabled = true\n  config.cache_store = :null_store\n\n  # \u30a2\u30bb\u30c3\u30c8\u306e\u30b3\u30f3\u30d1\u30a4\u30eb\u3092\u7121\u52b9\u5316\n  config.assets.debug = false\n  config.assets.digest = false\n\n  # \u30ed\u30b0\u51fa\u529b\u3092\u6700\u5c0f\u9650\u306b\n  config.log_level = :warn\nend<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-15\">3. spec_helper.rb\u306e\u63a8\u5968\u8a2d\u5b9a<\/h3>\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=\"\">RSpec.configure do |config|\n  # \u30c6\u30b9\u30c8\u306e\u5b9f\u884c\u9806\u5e8f\u3092\u30e9\u30f3\u30c0\u30e0\u306b\n  config.order = :random\n\n  # \u30c6\u30b9\u30c8\u5931\u6557\u6642\u306e\u30d0\u30c3\u30af\u30c8\u30ec\u30fc\u30b9\u3092\u898b\u3084\u3059\u304f\n  config.full_backtrace = false\n\n  # \u30d5\u30a9\u30fc\u30ab\u30b9\u3055\u308c\u305f\u30c6\u30b9\u30c8\u306e\u307f\u5b9f\u884c\u53ef\u80fd\u306b\n  config.filter_run_when_matching :focus\n\n  # \u30b3\u30fc\u30c9\u30ab\u30d0\u30ec\u30c3\u30b8\u306e\u8a2d\u5b9a\n  if ENV['COVERAGE']\n    require 'simplecov'\n    SimpleCov.start 'rails'\n  end\nend<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">\u3053\u308c\u3089\u306e\u8a2d\u5b9a\u306b\u3088\u308a\u3001\u4ee5\u4e0b\u306e\u30e1\u30ea\u30c3\u30c8\u304c\u5f97\u3089\u308c\u307e\u3059\uff1a<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u30c6\u30b9\u30c8\u306e\u5b9f\u884c\u901f\u5ea6\u304c\u5411\u4e0a<\/li>\n\n\n\n<li>\u74b0\u5883\u306b\u3088\u308b\u9055\u3044\u3092\u6700\u5c0f\u9650\u306b\u6291\u5236<\/li>\n\n\n\n<li>\u30c7\u30d0\u30c3\u30b0\u4f5c\u696d\u306e\u52b9\u7387\u5316<\/li>\n\n\n\n<li>\u30c1\u30fc\u30e0\u5168\u4f53\u3067\u306e\u4e00\u8cab\u6027\u306e\u3042\u308b\u958b\u767a\u74b0\u5883\u306e\u5b9f\u73fe<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">\u307e\u305f\u3001\u4ee5\u4e0b\u306e\u3088\u3046\u306a\u30a8\u30a4\u30ea\u30a2\u30b9\u3092<code>.bash_profile<\/code>\u3084<code>.zshrc<\/code>\u306b\u8ffd\u52a0\u3059\u308b\u3068\u3001\u65e5\u5e38\u7684\u306a\u30c6\u30b9\u30c8\u5b9f\u884c\u304c\u52b9\u7387\u5316\u3055\u308c\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=\"\">alias rspec='bundle exec rspec'\nalias rs='bundle exec rspec spec\/'\nalias rsf='bundle exec rspec --only-failures'<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">\u3053\u308c\u3067\u57fa\u672c\u7684\u306aRSpec\u74b0\u5883\u306e\u69cb\u7bc9\u306f\u5b8c\u4e86\u3067\u3059\u3002\u3053\u306e\u8a2d\u5b9a\u3092\u57fa\u306b\u3001\u30d7\u30ed\u30b8\u30a7\u30af\u30c8\u306e\u8981\u4ef6\u306b\u5fdc\u3058\u3066\u5fc5\u8981\u306a\u8abf\u6574\u3092\u52a0\u3048\u3066\u3044\u304f\u3053\u3068\u304c\u3067\u304d\u307e\u3059\u3002<\/p>\n\n\n\n<h1 class=\"wp-block-heading\" id=\"i-16\">\u73fe\u5834\u3067\u4f7f\u3048\u308bRSpec\u30c6\u30b9\u30c8\u30b3\u30fc\u30c9\u4f5c\u6210\u306e\u5177\u4f53\u4f8b<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">\u5b9f\u969b\u306eRails\u30d7\u30ed\u30b8\u30a7\u30af\u30c8\u3067\u306f\u3001\u69d8\u3005\u306a\u30b1\u30fc\u30b9\u306b\u5bfe\u5fdc\u3057\u305f\u30c6\u30b9\u30c8\u30b3\u30fc\u30c9\u3092\u66f8\u304f\u5fc5\u8981\u304c\u3042\u308a\u307e\u3059\u3002\u3053\u3053\u3067\u306f\u3001\u73fe\u5834\u3067\u5373\u4f7f\u3048\u308b\u5b9f\u8df5\u7684\u306a\u30c6\u30b9\u30c8\u30b3\u30fc\u30c9\u306e\u4f8b\u3092\u7d39\u4ecb\u3057\u307e\u3059\u3002<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"i-17\">\u30e2\u30c7\u30eb\u30b9\u30da\u30c3\u30af\u306e\u66f8\u304d\u65b9\u3068\u30d0\u30ea\u30c7\u30fc\u30b7\u30e7\u30f3\u30c6\u30b9\u30c8<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-18\">\u57fa\u672c\u7684\u306a\u30e2\u30c7\u30eb\u30b9\u30da\u30c3\u30af<\/h3>\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=\"\"># spec\/models\/user_spec.rb\nRSpec.describe User, type: :model do\n  # FactoryBot\u3092\u4f7f\u7528\u3057\u305f\u30c6\u30b9\u30c8\u30c7\u30fc\u30bf\u306e\u4f5c\u6210\n  let(:user) { build(:user) }\n\n  describe '\u30d0\u30ea\u30c7\u30fc\u30b7\u30e7\u30f3' do\n    it '\u6709\u52b9\u306a\u5c5e\u6027\u5024\u306e\u5834\u5408\u306f\u6709\u52b9\u3067\u3042\u308b' do\n      expect(user).to be_valid\n    end\n\n    context '\u540d\u524d\u304c\u306a\u3044\u5834\u5408' do\n      it '\u7121\u52b9\u3067\u3042\u308b' do\n        user.name = nil\n        expect(user).not_to be_valid\n        expect(user.errors[:name]).to include(\"\u3092\u5165\u529b\u3057\u3066\u304f\u3060\u3055\u3044\")\n      end\n    end\n\n    context '\u30e1\u30fc\u30eb\u30a2\u30c9\u30ec\u30b9\u304c\u91cd\u8907\u3057\u3066\u3044\u308b\u5834\u5408' do\n      before do\n        create(:user, email: 'test@example.com')\n        user.email = 'test@example.com'\n      end\n\n      it '\u7121\u52b9\u3067\u3042\u308b' do\n        expect(user).not_to be_valid\n        expect(user.errors[:email]).to include(\"\u306f\u3059\u3067\u306b\u5b58\u5728\u3057\u307e\u3059\")\n      end\n    end\n  end\n\n  describe '\u30b9\u30b3\u30fc\u30d7' do\n    it 'active\u30e6\u30fc\u30b6\u30fc\u306e\u307f\u3092\u53d6\u5f97\u3059\u308b' do\n      active_user = create(:user, status: 'active')\n      inactive_user = create(:user, status: 'inactive')\n\n      expect(User.active).to include(active_user)\n      expect(User.active).not_to include(inactive_user)\n    end\n  end\nend<\/pre>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"i-19\">\u30b3\u30f3\u30c8\u30ed\u30fc\u30e9\u30b9\u30da\u30c3\u30af\u306b\u3088\u308b\u30a2\u30af\u30b7\u30e7\u30f3\u5358\u4f4d\u306e\u30c6\u30b9\u30c8<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-20\">RESTful\u30a2\u30af\u30b7\u30e7\u30f3\u306e\u30c6\u30b9\u30c8\u4f8b<\/h3>\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=\"\"># spec\/controllers\/posts_controller_spec.rb\nRSpec.describe PostsController, type: :controller do\n  let(:user) { create(:user) }\n  let(:valid_attributes) { attributes_for(:post) }\n\n  describe 'GET #index' do\n    before do\n      sign_in user  # Devise\u3092\u4f7f\u7528\u3057\u3066\u3044\u308b\u5834\u5408\n      get :index\n    end\n\n    it '\u6210\u529f\u3057\u3066\u30ec\u30b9\u30dd\u30f3\u30b9\u3092\u8fd4\u3059' do\n      expect(response).to be_successful\n    end\n\n    it 'posts\u3092\u30a2\u30b5\u30a4\u30f3\u3059\u308b' do\n      expect(assigns(:posts)).not_to be_nil\n    end\n  end\n\n  describe 'POST #create' do\n    context '\u6709\u52b9\u306a\u30d1\u30e9\u30e1\u30fc\u30bf\u306e\u5834\u5408' do\n      it '\u65b0\u3057\u3044\u6295\u7a3f\u3092\u4f5c\u6210\u3059\u308b' do\n        sign_in user\n        expect {\n          post :create, params: { post: valid_attributes }\n        }.to change(Post, :count).by(1)\n      end\n\n      it '\u4f5c\u6210\u5f8c\u306b\u6295\u7a3f\u8a73\u7d30\u30da\u30fc\u30b8\u306b\u30ea\u30c0\u30a4\u30ec\u30af\u30c8\u3059\u308b' do\n        sign_in user\n        post :create, params: { post: valid_attributes }\n        expect(response).to redirect_to(Post.last)\n      end\n    end\n\n    context '\u7121\u52b9\u306a\u30d1\u30e9\u30e1\u30fc\u30bf\u306e\u5834\u5408' do\n      it '\u65b0\u3057\u3044\u6295\u7a3f\u3092\u4f5c\u6210\u3057\u306a\u3044' do\n        sign_in user\n        expect {\n          post :create, params: { post: { title: '' } }\n        }.not_to change(Post, :count)\n      end\n\n      it '\u65b0\u898f\u4f5c\u6210\u30d5\u30a9\u30fc\u30e0\u3092\u518d\u8868\u793a\u3059\u308b' do\n        sign_in user\n        post :create, params: { post: { title: '' } }\n        expect(response).to render_template(:new)\n      end\n    end\n  end\nend<\/pre>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"i-21\">\u30b7\u30b9\u30c6\u30e0\u30b9\u30da\u30c3\u30af\u3067\u306e\u30e6\u30fc\u30b6\u30fc\u64cd\u4f5c\u30b7\u30df\u30e5\u30ec\u30fc\u30b7\u30e7\u30f3<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-22\">\u30e6\u30fc\u30b6\u30fc\u767b\u9332\u30d5\u30ed\u30fc\u306e\u30c6\u30b9\u30c8<\/h3>\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=\"\"># spec\/system\/user_registration_spec.rb\nRSpec.describe '\u30e6\u30fc\u30b6\u30fc\u767b\u9332', type: :system do\n  before do\n    driven_by(:rack_test)\n  end\n\n  scenario '\u30e6\u30fc\u30b6\u30fc\u304c\u65b0\u898f\u767b\u9332\u3067\u304d\u308b' do\n    visit new_user_registration_path\n\n    fill_in '\u30e6\u30fc\u30b6\u30fc\u540d', with: '\u5c71\u7530\u592a\u90ce'\n    fill_in '\u30e1\u30fc\u30eb\u30a2\u30c9\u30ec\u30b9', with: 'taro@example.com'\n    fill_in '\u30d1\u30b9\u30ef\u30fc\u30c9', with: 'password123'\n    fill_in '\u30d1\u30b9\u30ef\u30fc\u30c9\uff08\u78ba\u8a8d\uff09', with: 'password123'\n\n    expect {\n      click_button '\u767b\u9332\u3059\u308b'\n    }.to change(User, :count).by(1)\n\n    expect(page).to have_content('\u30a2\u30ab\u30a6\u30f3\u30c8\u767b\u9332\u304c\u5b8c\u4e86\u3057\u307e\u3057\u305f')\n    expect(current_path).to eq root_path\n  end\n\n  scenario '\u7121\u52b9\u306a\u60c5\u5831\u3067\u306f\u767b\u9332\u3067\u304d\u306a\u3044' do\n    visit new_user_registration_path\n\n    fill_in '\u30e6\u30fc\u30b6\u30fc\u540d', with: ''\n    fill_in '\u30e1\u30fc\u30eb\u30a2\u30c9\u30ec\u30b9', with: 'invalid-email'\n    fill_in '\u30d1\u30b9\u30ef\u30fc\u30c9', with: 'short'\n    fill_in '\u30d1\u30b9\u30ef\u30fc\u30c9\uff08\u78ba\u8a8d\uff09', with: 'different'\n\n    expect {\n      click_button '\u767b\u9332\u3059\u308b'\n    }.not_to change(User, :count)\n\n    expect(page).to have_content('\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f')\n    expect(page).to have_content('\u30e1\u30fc\u30eb\u30a2\u30c9\u30ec\u30b9\u306f\u4e0d\u6b63\u306a\u5024\u3067\u3059')\n    expect(page).to have_content('\u30d1\u30b9\u30ef\u30fc\u30c9\u306f6\u6587\u5b57\u4ee5\u4e0a\u3067\u5165\u529b\u3057\u3066\u304f\u3060\u3055\u3044')\n  end\nend<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">\u5b9f\u8df5\u7684\u306a\u30c6\u30b9\u30c8\u3092\u66f8\u304f\u969b\u306e\u91cd\u8981\u306a\u30dd\u30a4\u30f3\u30c8\uff1a<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>\u30c6\u30b9\u30c8\u306e\u69cb\u9020\u5316<\/li>\n<\/ol>\n\n\n\n<ul class=\"wp-block-list\">\n<li>describe\u3067\u30c6\u30b9\u30c8\u5bfe\u8c61\u3092\u660e\u78ba\u306b<\/li>\n\n\n\n<li>context\u3067\u6761\u4ef6\u3092\u660e\u78ba\u306b<\/li>\n\n\n\n<li>it\u3067\u671f\u5f85\u3059\u308b\u52d5\u4f5c\u3092\u660e\u78ba\u306b<\/li>\n<\/ul>\n\n\n\n<ol class=\"wp-block-list\">\n<li>\u53ef\u8aad\u6027\u306e\u5411\u4e0a<\/li>\n<\/ol>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u9069\u5207\u306a\u540d\u524d\u4ed8\u3051<\/li>\n\n\n\n<li>\u30c6\u30b9\u30c8\u306e\u610f\u56f3\u304c\u660e\u78ba\u306a\u8a18\u8ff0<\/li>\n\n\n\n<li>\u5fc5\u8981\u6700\u5c0f\u9650\u306e\u30c6\u30b9\u30c8\u30b1\u30fc\u30b9<\/li>\n<\/ul>\n\n\n\n<ol class=\"wp-block-list\">\n<li>\u30c6\u30b9\u30c8\u306e\u72ec\u7acb\u6027<\/li>\n<\/ol>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u30c6\u30b9\u30c8\u9593\u306e\u4f9d\u5b58\u95a2\u4fc2\u3092\u907f\u3051\u308b<\/li>\n\n\n\n<li>before\/after\u30d6\u30ed\u30c3\u30af\u306e\u9069\u5207\u306a\u4f7f\u7528<\/li>\n\n\n\n<li>\u30c7\u30fc\u30bf\u306e\u30af\u30ea\u30fc\u30f3\u30a2\u30c3\u30d7<\/li>\n<\/ul>\n\n\n\n<ol class=\"wp-block-list\">\n<li>\u30d1\u30d5\u30a9\u30fc\u30de\u30f3\u30b9\u306e\u8003\u616e<\/li>\n<\/ol>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u5fc5\u8981\u306a\u30c7\u30fc\u30bf\u306e\u307f\u3092\u4f5c\u6210<\/li>\n\n\n\n<li>\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u30a2\u30af\u30bb\u30b9\u306e\u6700\u5c0f\u5316<\/li>\n\n\n\n<li>\u30c8\u30e9\u30f3\u30b6\u30af\u30b7\u30e7\u30f3\u306e\u9069\u5207\u306a\u4f7f\u7528<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">\u3053\u308c\u3089\u306e\u30c6\u30b9\u30c8\u30b3\u30fc\u30c9\u306f\u3001\u5b9f\u969b\u306e\u30d7\u30ed\u30b8\u30a7\u30af\u30c8\u3067\u3059\u3050\u306b\u6d3b\u7528\u3067\u304d\u308b\u5b9f\u8df5\u7684\u306a\u4f8b\u3068\u306a\u3063\u3066\u3044\u307e\u3059\u3002\u30d7\u30ed\u30b8\u30a7\u30af\u30c8\u306e\u8981\u4ef6\u306b\u5fdc\u3058\u3066\u3001\u9069\u5b9c\u30ab\u30b9\u30bf\u30de\u30a4\u30ba\u3057\u3066\u4f7f\u7528\u3057\u3066\u304f\u3060\u3055\u3044\u3002<\/p>\n\n\n\n<h1 class=\"wp-block-heading\" id=\"i-23\">\u30c6\u30b9\u30c8\u518d\u73fe\u6027\u3092\u9ad8\u3081\u308b\u5b9f\u8df5\u30c6\u30af\u30cb\u30c3\u30af<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">\u30c6\u30b9\u30c8\u306e\u4fe1\u983c\u6027\u3068\u4fdd\u5b88\u6027\u3092\u9ad8\u3081\u308b\u305f\u3081\u306b\u3001\u73fe\u5834\u3067\u6d3b\u7528\u3067\u304d\u308b\u5b9f\u8df5\u7684\u306a\u30c6\u30af\u30cb\u30c3\u30af\u3092\u7d39\u4ecb\u3057\u307e\u3059\u3002<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"i-24\">FactoryBot\u3092\u6d3b\u7528\u3057\u305f\u30c6\u30b9\u30c8\u30c7\u30fc\u30bf\u7ba1\u7406<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-25\">\u57fa\u672c\u7684\u306a\u30d5\u30a1\u30af\u30c8\u30ea\u306e\u5b9a\u7fa9<\/h3>\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=\"\"># spec\/factories\/users.rb\nFactoryBot.define do\n  factory :user do\n    sequence(:email) { |n| \"user#{n}@example.com\" }\n    name { \"\u30c6\u30b9\u30c8\u30e6\u30fc\u30b6\u30fc\" }\n    password { \"password123\" }\n\n    # \u30c8\u30ec\u30a4\u30c8\u3092\u4f7f\u7528\u3057\u305f\u6761\u4ef6\u4ed8\u304d\u30c7\u30fc\u30bf\n    trait :admin do\n      role { \"admin\" }\n      admin { true }\n    end\n\n    trait :with_posts do\n      after(:create) do |user|\n        create_list(:post, 3, user: user)\n      end\n    end\n  end\nend<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-26\">\u52b9\u7387\u7684\u306a\u30d5\u30a1\u30af\u30c8\u30ea\u306e\u4f7f\u7528\u65b9\u6cd5<\/h3>\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=\"\">RSpec.describe User, type: :model do\n  # \u57fa\u672c\u7684\u306a\u4f7f\u7528\u65b9\u6cd5\n  let(:user) { create(:user) }\n\n  # \u30c8\u30ec\u30a4\u30c8\u306e\u7d44\u307f\u5408\u308f\u305b\n  let(:admin_with_posts) { create(:user, :admin, :with_posts) }\n\n  # \u5c5e\u6027\u306e\u30aa\u30fc\u30d0\u30fc\u30e9\u30a4\u30c9\n  let(:custom_user) { \n    create(:user, \n      name: \"\u30ab\u30b9\u30bf\u30e0\u540d\",\n      email: \"custom@example.com\"\n    ) \n  }\n\n  # \u95a2\u9023\u4ed8\u3051\u3092\u542b\u3080\u30d5\u30a1\u30af\u30c8\u30ea\n  let(:user_with_posts) {\n    create(:user) do |user|\n      create(:post, user: user)\n    end\n  }\nend<\/pre>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"i-27\">\u5171\u901a\u5316\u3067\u304d\u308b\u30c6\u30b9\u30c8\u30b3\u30fc\u30c9\u3068shared_examples<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-28\">\u5171\u901a\u306e\u30c6\u30b9\u30c8\u30b1\u30fc\u30b9\u5b9a\u7fa9<\/h3>\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=\"\"># spec\/support\/shared_examples\/api_authenticatable.rb\nRSpec.shared_examples \"API\u8a8d\u8a3c\u304c\u5fc5\u8981\" do\n  context '\u8a8d\u8a3c\u30c8\u30fc\u30af\u30f3\u304c\u306a\u3044\u5834\u5408' do\n    before do\n      request.headers['Authorization'] = nil\n    end\n\n    it '401\u30a8\u30e9\u30fc\u3092\u8fd4\u3059' do\n      subject\n      expect(response).to have_http_status(:unauthorized)\n      expect(JSON.parse(response.body)).to include(\n        'error' =&gt; '\u8a8d\u8a3c\u304c\u5fc5\u8981\u3067\u3059'\n      )\n    end\n  end\nend\n\n# \u4f7f\u7528\u4f8b\nRSpec.describe Api::V1::PostsController, type: :controller do\n  describe 'GET #index' do\n    subject { get :index }\n    it_behaves_like \"API\u8a8d\u8a3c\u304c\u5fc5\u8981\"\n  end\nend<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-29\">\u30b3\u30f3\u30c6\u30ad\u30b9\u30c8\u5171\u6709\u306e\u6d3b\u7528<\/h3>\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=\"\">RSpec.shared_context \"\u30ed\u30b0\u30a4\u30f3\u6e08\u307f\u30e6\u30fc\u30b6\u30fc\" do\n  let(:current_user) { create(:user) }\n  before { sign_in current_user }\nend\n\nRSpec.describe PostsController, type: :controller do\n  include_context \"\u30ed\u30b0\u30a4\u30f3\u6e08\u307f\u30e6\u30fc\u30b6\u30fc\"\n\n  describe 'POST #create' do\n    it '\u30ed\u30b0\u30a4\u30f3\u30e6\u30fc\u30b6\u30fc\u3068\u3057\u3066\u6295\u7a3f\u3092\u4f5c\u6210\u3067\u304d\u308b' do\n      # \u30c6\u30b9\u30c8\u30b3\u30fc\u30c9\n    end\n  end\nend<\/pre>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"i-30\">\u30e2\u30c3\u30af\u30fb\u30b9\u30bf\u30d6\u3092\u4f7f\u3063\u305f\u5916\u90e8\u4f9d\u5b58\u306e\u5236\u5fa1<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-31\">\u52b9\u679c\u7684\u306a\u30e2\u30c3\u30af\u306e\u4f7f\u7528\u4f8b<\/h3>\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=\"\">RSpec.describe PaymentService do\n  describe '#process_payment' do\n    let(:payment_gateway) { class_double(PaymentGateway) }\n    let(:order) { create(:order) }\n\n    before do\n      allow(PaymentGateway).to receive(:new).and_return(payment_gateway)\n    end\n\n    context '\u652f\u6255\u3044\u304c\u6210\u529f\u3059\u308b\u5834\u5408' do\n      before do\n        allow(payment_gateway).to receive(:charge).and_return(\n          success: true,\n          transaction_id: 'tx_123'\n        )\n      end\n\n      it '\u652f\u6255\u3044\u51e6\u7406\u304c\u5b8c\u4e86\u3059\u308b' do\n        result = subject.process_payment(order)\n        expect(result).to be_success\n        expect(order.reload).to be_paid\n      end\n    end\n\n    context '\u652f\u6255\u3044\u304c\u5931\u6557\u3059\u308b\u5834\u5408' do\n      before do\n        allow(payment_gateway).to receive(:charge).and_return(\n          success: false,\n          error: '\u30ab\u30fc\u30c9\u304c\u62d2\u5426\u3055\u308c\u307e\u3057\u305f'\n        )\n      end\n\n      it '\u30a8\u30e9\u30fc\u3092\u8fd4\u3059' do\n        result = subject.process_payment(order)\n        expect(result).not_to be_success\n        expect(order.reload).not_to be_paid\n      end\n    end\n  end\nend<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-32\">\u30b9\u30bf\u30d6\u306e\u9069\u5207\u306a\u4f7f\u7528\u65b9\u6cd5<\/h3>\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=\"\">RSpec.describe UserNotifierService do\n  describe '#notify_admin' do\n    let(:admin) { create(:user, :admin) }\n    let(:mailer) { double('AdminMailer') }\n\n    before do\n      # \u30e1\u30fc\u30eb\u9001\u4fe1\u3092\u30b9\u30bf\u30d6\u5316\n      allow(AdminMailer).to receive(:notification)\n        .with(admin, anything)\n        .and_return(mailer)\n      allow(mailer).to receive(:deliver_later)\n    end\n\n    it '\u7ba1\u7406\u8005\u306b\u901a\u77e5\u30e1\u30fc\u30eb\u3092\u9001\u4fe1\u3059\u308b' do\n      subject.notify_admin('\u91cd\u8981\u306a\u30e1\u30c3\u30bb\u30fc\u30b8')\n\n      expect(AdminMailer).to have_received(:notification)\n        .with(admin, '\u91cd\u8981\u306a\u30e1\u30c3\u30bb\u30fc\u30b8')\n      expect(mailer).to have_received(:deliver_later)\n    end\n  end\nend<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">\u5b9f\u8df5\u7684\u306a\u30c6\u30af\u30cb\u30c3\u30af\u3092\u4f7f\u7528\u3059\u308b\u969b\u306e\u91cd\u8981\u306a\u30dd\u30a4\u30f3\u30c8\uff1a<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>\u30d5\u30a1\u30af\u30c8\u30ea\u306e\u8a2d\u8a08<\/li>\n<\/ol>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u5fc5\u8981\u6700\u5c0f\u9650\u306e\u30c7\u30fc\u30bf\u306e\u307f\u3092\u5b9a\u7fa9<\/li>\n\n\n\n<li>\u30c8\u30ec\u30a4\u30c8\u3092\u6d3b\u7528\u3057\u3066\u67d4\u8edf\u6027\u3092\u78ba\u4fdd<\/li>\n\n\n\n<li>\u95a2\u9023\u30c7\u30fc\u30bf\u306e\u9069\u5207\u306a\u751f\u6210<\/li>\n<\/ul>\n\n\n\n<ol class=\"wp-block-list\">\n<li>\u5171\u901a\u5316\u306e\u5224\u65ad\u57fa\u6e96<\/li>\n<\/ol>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u8907\u6570\u306e\u5834\u6240\u3067\u4f7f\u7528\u3055\u308c\u308b\u540c\u3058\u3088\u3046\u306a\u30c6\u30b9\u30c8<\/li>\n\n\n\n<li>\u632f\u308b\u821e\u3044\u306e\u30d1\u30bf\u30fc\u30f3\u304c\u660e\u78ba\u306a\u5834\u5408<\/li>\n\n\n\n<li>\u30e1\u30f3\u30c6\u30ca\u30f3\u30b9\u30b3\u30b9\u30c8\u306e\u524a\u6e1b\u304c\u898b\u8fbc\u3081\u308b\u5834\u5408<\/li>\n<\/ul>\n\n\n\n<ol class=\"wp-block-list\">\n<li>\u30e2\u30c3\u30af\u30fb\u30b9\u30bf\u30d6\u306e\u4f7f\u7528\u57fa\u6e96<\/li>\n<\/ol>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u5916\u90e8\u30b5\u30fc\u30d3\u30b9\u3068\u306e\u901a\u4fe1<\/li>\n\n\n\n<li>\u6642\u9593\u304c\u304b\u304b\u308b\u51e6\u7406<\/li>\n\n\n\n<li>\u526f\u4f5c\u7528\u306e\u3042\u308b\u51e6\u7406<\/li>\n\n\n\n<li>\u30c6\u30b9\u30c8\u5bfe\u8c61\u5916\u306e\u4f9d\u5b58\u95a2\u4fc2<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">\u3053\u308c\u3089\u306e\u30c6\u30af\u30cb\u30c3\u30af\u3092\u9069\u5207\u306b\u7d44\u307f\u5408\u308f\u305b\u308b\u3053\u3068\u3067\u3001\u3088\u308a\u4fe1\u983c\u6027\u306e\u9ad8\u3044\u30c6\u30b9\u30c8\u30b9\u30a4\u30fc\u30c8\u3092\u69cb\u7bc9\u3067\u304d\u307e\u3059\u3002<\/p>\n\n\n\n<h1 class=\"wp-block-heading\" id=\"i-33\">\u30c6\u30b9\u30c8\u30d1\u30d5\u30a9\u30fc\u30de\u30f3\u30b9\u3092\u6539\u5584\u3059\u308b\u5b9f\u88c5\u306e\u30b3\u30c4<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">\u30c6\u30b9\u30c8\u30b9\u30a4\u30fc\u30c8\u306e\u5b9f\u884c\u6642\u9593\u306f\u3001\u958b\u767a\u52b9\u7387\u306b\u76f4\u63a5\u5f71\u97ff\u3092\u4e0e\u3048\u307e\u3059\u3002\u3053\u3053\u3067\u306f\u3001RSpec\u30c6\u30b9\u30c8\u306e\u5b9f\u884c\u6642\u9593\u3092\u5927\u5e45\u306b\u77ed\u7e2e\u3059\u308b\u305f\u3081\u306e\u5b9f\u8df5\u7684\u306a\u65b9\u6cd5\u3092\u7d39\u4ecb\u3057\u307e\u3059\u3002<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"i-34\">\u30c6\u30b9\u30c8\u6642\u9593\u309250%\u524a\u6e1b\u3059\u308b\u8a2d\u5b9a\u30c6\u30af\u30cb\u30c3\u30af<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-35\">1. Spring preloader\u306e\u6d3b\u7528<\/h3>\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=\"\"># Gemfile\ngroup :development do\n  gem 'spring'\n  gem 'spring-commands-rspec'\nend<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">\u8a2d\u5b9a\u624b\u9806\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=\"\"># Spring binstub\u306e\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\nbundle exec spring binstub rspec\n\n# .bash_profile\u3084.zshrc\u306b\u8ffd\u52a0\nalias rspec='bin\/rspec'<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-36\">2. \u4e26\u5217\u30c6\u30b9\u30c8\u306e\u8a2d\u5b9a<\/h3>\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=\"\"># spec\/spec_helper.rb\nrequire 'parallel_tests'\n\nRSpec.configure do |config|\n  # \u30c6\u30b9\u30c8\u306e\u4e26\u5217\u5b9f\u884c\u3092\u6709\u52b9\u5316\n  config.parallel = true\n\n  # \u4e26\u5217\u5b9f\u884c\u3059\u308b\u30d7\u30ed\u30bb\u30b9\u6570\u3092\u6307\u5b9a\n  config.parallel_processor_count = [\n    Parallel.processor_count,\n    5 # \u6700\u5927\u30d7\u30ed\u30bb\u30b9\u6570\n  ].min\nend<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-37\">3. \u30c6\u30b9\u30c8\u306e\u5b9f\u884c\u9806\u5e8f\u306e\u6700\u9069\u5316<\/h3>\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=\"\"># spec\/spec_helper.rb\nRSpec.configure do |config|\n  # \u6700\u3082\u6642\u9593\u306e\u304b\u304b\u308b\u30c6\u30b9\u30c8\u3092\u5148\u306b\u5b9f\u884c\n  config.order = :slowest\n\n  # \u30c6\u30b9\u30c8\u306e\u30d7\u30ed\u30d5\u30a1\u30a4\u30ea\u30f3\u30b0\u3092\u6709\u52b9\u5316\n  config.profile_examples = 10\nend<\/pre>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"i-38\">\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u6226\u7565\u306e\u6700\u9069\u5316<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-39\">1. \u30c8\u30e9\u30f3\u30b6\u30af\u30b7\u30e7\u30f3\u306e\u52b9\u7387\u7684\u306a\u4f7f\u7528<\/h3>\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=\"\"># spec\/rails_helper.rb\nRSpec.configure do |config|\n  config.use_transactional_fixtures = true\n\n  config.around(:each) do |example|\n    ActiveRecord::Base.transaction do\n      example.run\n      raise ActiveRecord::Rollback\n    end\n  end\nend<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-40\">2. \u30a4\u30f3\u30e1\u30e2\u30ea\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u306e\u6d3b\u7528<\/h3>\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=\"\"># config\/database.yml\ntest:\n  adapter: sqlite3\n  database: \":memory:\"\n  pool: 5\n  timeout: 5000<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-41\">3. \u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u30af\u30ea\u30fc\u30ca\u30fc\u306e\u6700\u9069\u5316<\/h3>\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=\"\"># spec\/rails_helper.rb\nRSpec.configure do |config|\n  config.before(:suite) do\n    DatabaseCleaner.clean_with(:truncation)\n    DatabaseCleaner.strategy = :transaction\n  end\n\n  config.around(:each) do |example|\n    DatabaseCleaner.cleaning do\n      example.run\n    end\n  end\n\n  # \u30b7\u30b9\u30c6\u30e0\u30b9\u30da\u30c3\u30af\u7528\u306e\u8a2d\u5b9a\n  config.before(:each, type: :system) do\n    DatabaseCleaner.strategy = :truncation\n  end\nend<\/pre>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"i-42\">\u30dc\u30fc\u30c0\u30fc\u30c6\u30b9\u30c8\u5b9f\u884c\u306e\u5c0e\u5165\u3068\u6ce8\u610f\u70b9<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-43\">1. \u30c6\u30b9\u30c8\u30d5\u30a1\u30a4\u30eb\u306e\u5206\u985e<\/h3>\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=\"\"># .rspec\n--tag ~slow<\/pre>\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=\"\"># spec\/spec_helper.rb\nRSpec.configure do |config|\n  # \u6642\u9593\u306e\u304b\u304b\u308b\u30c6\u30b9\u30c8\u306b\u30bf\u30b0\u3092\u4ed8\u3051\u308b\n  config.define_derived_metadata do |meta|\n    meta[:slow] = true if meta[:type] == :system\n  end\nend<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-44\">2. \u30ab\u30b9\u30bf\u30e0\u30c6\u30b9\u30c8\u30e9\u30f3\u30ca\u30fc\u306e\u5b9f\u88c5<\/h3>\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=\"\"># lib\/tasks\/rspec.rake\nnamespace :spec do\n  task :quick do\n    system \"bundle exec rspec --tag ~slow\"\n  end\n\n  task :full do\n    system \"bundle exec rspec\"\n  end\n\n  task :parallel do\n    system \"bundle exec parallel_rspec spec\/\"\n  end\nend<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">\u30d1\u30d5\u30a9\u30fc\u30de\u30f3\u30b9\u6700\u9069\u5316\u306e\u30d9\u30b9\u30c8\u30d7\u30e9\u30af\u30c6\u30a3\u30b9\uff1a<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>\u30c6\u30b9\u30c8\u30c7\u30fc\u30bf\u306e\u6700\u9069\u5316<\/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=\"\"># \u826f\u3044\u4f8b\uff1a\u5fc5\u8981\u6700\u5c0f\u9650\u306e\u30c7\u30fc\u30bf\u4f5c\u6210\nlet(:user) { create(:user, :minimal) }\n\n# \u60aa\u3044\u4f8b\uff1a\u4e0d\u8981\u306a\u30c7\u30fc\u30bf\u307e\u3067\u4f5c\u6210\nlet(:user) { create(:user, :with_full_profile, :with_posts, :with_comments) }<\/pre>\n\n\n\n<ol start=\"2\" class=\"wp-block-list\">\n<li>\u30ec\u30b9\u30dd\u30f3\u30b9\u306e\u30e2\u30c3\u30af\u5316<\/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=\"\"># \u5916\u90e8API\u30b3\u30fc\u30eb\u306e\u30e2\u30c3\u30af\nbefore do\n  allow(ExternalService).to receive(:fetch_data).and_return({\n    status: 'success',\n    data: { id: 1 }\n  })\nend<\/pre>\n\n\n\n<ol start=\"3\" class=\"wp-block-list\">\n<li>\u5171\u901a\u30bb\u30c3\u30c8\u30a2\u30c3\u30d7\u306e\u6700\u9069\u5316<\/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=\"\"># spec\/support\/setup_helper.rb\nmodule SetupHelper\n  def setup_required_data\n    @user = create(:user)\n    @role = create(:role)\n    @permission = create(:permission)\n  end\nend\n\nRSpec.configure do |config|\n  config.include SetupHelper, type: :controller\nend<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">\u5b9f\u884c\u6642\u9593\u306e\u524a\u6e1b\u52b9\u679c\uff1a<\/p>\n\n\n<div id=\"id-ab9698b8-6660-43dd-b7f2-bb56f5159944\">\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>\u6700\u9069\u5316\u624b\u6cd5<\/th><th>\u671f\u5f85\u3055\u308c\u308b\u6539\u5584\u7387<\/th><\/tr><\/thead><tbody><tr><td>Spring preloader<\/td><td>20-30%<\/td><\/tr><tr><td>\u4e26\u5217\u30c6\u30b9\u30c8\u5b9f\u884c<\/td><td>40-60%<\/td><\/tr><tr><td>\u30c8\u30e9\u30f3\u30b6\u30af\u30b7\u30e7\u30f3\u6700\u9069\u5316<\/td><td>10-20%<\/td><\/tr><tr><td>\u30a4\u30f3\u30e1\u30e2\u30eaDB<\/td><td>30-40%<\/td><\/tr><tr><td>\u30c6\u30b9\u30c8\u5206\u985e<\/td><td>50-70%<\/td><\/tr><\/tbody><\/table><\/figure>\n<\/div>\n\n\n<p class=\"wp-block-paragraph\">\u3053\u308c\u3089\u306e\u6700\u9069\u5316\u3092\u7d44\u307f\u5408\u308f\u305b\u308b\u3053\u3068\u3067\u3001\u30c6\u30b9\u30c8\u30b9\u30a4\u30fc\u30c8\u306e\u5b9f\u884c\u6642\u9593\u3092\u5927\u5e45\u306b\u77ed\u7e2e\u3067\u304d\u307e\u3059\u3002\u305f\u3060\u3057\u3001\u4ee5\u4e0b\u306e\u70b9\u306b\u6ce8\u610f\u304c\u5fc5\u8981\u3067\u3059\uff1a<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u30c6\u30b9\u30c8\u306e\u4fe1\u983c\u6027\u3092\u640d\u306a\u308f\u306a\u3044\u3053\u3068<\/li>\n\n\n\n<li>\u30c7\u30d0\u30c3\u30b0\u306e\u3057\u3084\u3059\u3055\u3092\u7dad\u6301\u3059\u308b\u3053\u3068<\/li>\n\n\n\n<li>\u30c1\u30fc\u30e0\u5168\u4f53\u3067\u306e\u4e00\u8cab\u6027\u3092\u4fdd\u3064\u3053\u3068<\/li>\n<\/ul>\n\n\n\n<h1 class=\"wp-block-heading\" id=\"i-45\">\u5b9f\u8df5\u7684\u306a\u30c6\u30b9\u30c8\u30b1\u30fc\u30b9\u30b9\u30bf\u30c7\u30a3<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">\u5b9f\u969b\u306e\u30d7\u30ed\u30b8\u30a7\u30af\u30c8\u3067\u906d\u9047\u3059\u308b\u8907\u96d1\u306a\u30c6\u30b9\u30c8\u30b7\u30ca\u30ea\u30aa\u306b\u3064\u3044\u3066\u3001\u5177\u4f53\u7684\u306a\u5b9f\u88c5\u4f8b\u3092\u4ea4\u3048\u3066\u89e3\u8aac\u3057\u307e\u3059\u3002<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"i-46\">API\u8a8d\u8a3c\u6a5f\u80fd\u306e\u30c6\u30b9\u30c8\u30b3\u30fc\u30c9\u5b9f\u88c5\u4f8b<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-47\">JWT\u3092\u4f7f\u7528\u3057\u305f\u8a8d\u8a3c\u306e\u30c6\u30b9\u30c8<\/h3>\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=\"\"># spec\/requests\/api\/v1\/authentication_spec.rb\nRSpec.describe 'API Authentication', type: :request do\n  let(:user) { create(:user) }\n  let(:valid_credentials) do\n    {\n      email: user.email,\n      password: 'password123'\n    }\n  end\n\n  describe 'POST \/api\/v1\/auth\/login' do\n    context '\u6709\u52b9\u306a\u8a8d\u8a3c\u60c5\u5831\u306e\u5834\u5408' do\n      it 'JWT\u30c8\u30fc\u30af\u30f3\u3092\u8fd4\u3059' do\n        post '\/api\/v1\/auth\/login', params: valid_credentials\n\n        expect(response).to have_http_status(:success)\n        expect(json_response).to include('token')\n        expect(json_response['token']).to be_present\n      end\n    end\n\n    context '\u7121\u52b9\u306a\u8a8d\u8a3c\u60c5\u5831\u306e\u5834\u5408' do\n      it '\u30a8\u30e9\u30fc\u3092\u8fd4\u3059' do\n        post '\/api\/v1\/auth\/login', params: {\n          email: user.email,\n          password: 'wrong_password'\n        }\n\n        expect(response).to have_http_status(:unauthorized)\n        expect(json_response['error']).to eq('\u8a8d\u8a3c\u306b\u5931\u6557\u3057\u307e\u3057\u305f')\n      end\n    end\n  end\n\n  describe 'Protected Endpoints' do\n    let(:protected_path) { '\/api\/v1\/protected_resource' }\n    let(:valid_token) { JWT.encode({user_id: user.id}, Rails.application.secrets.secret_key_base) }\n\n    context '\u6709\u52b9\u306a\u30c8\u30fc\u30af\u30f3\u306e\u5834\u5408' do\n      it '\u30a2\u30af\u30bb\u30b9\u3092\u8a31\u53ef\u3059\u308b' do\n        get protected_path, headers: {\n          'Authorization': \"Bearer #{valid_token}\"\n        }\n\n        expect(response).to have_http_status(:success)\n      end\n    end\n\n    context '\u7121\u52b9\u306a\u30c8\u30fc\u30af\u30f3\u306e\u5834\u5408' do\n      it '\u30a2\u30af\u30bb\u30b9\u3092\u62d2\u5426\u3059\u308b' do\n        get protected_path, headers: {\n          'Authorization': 'Bearer invalid_token'\n        }\n\n        expect(response).to have_http_status(:unauthorized)\n      end\n    end\n  end\nend<\/pre>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"i-48\">\u975e\u540c\u671f\u51e6\u7406\u3092\u542b\u3080\u30b8\u30e7\u30d6\u306e\u30c6\u30b9\u30c8\u65b9\u6cd5<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-49\">ActiveJob\u3092\u4f7f\u7528\u3057\u305f\u975e\u540c\u671f\u51e6\u7406\u306e\u30c6\u30b9\u30c8<\/h3>\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=\"\"># spec\/jobs\/notification_job_spec.rb\nRSpec.describe NotificationJob, type: :job do\n  let(:user) { create(:user) }\n  let(:notification_data) { { message: \"\u30c6\u30b9\u30c8\u901a\u77e5\" } }\n\n  describe '#perform' do\n    it '\u30b8\u30e7\u30d6\u304c\u30a8\u30f3\u30ad\u30e5\u30fc\u3055\u308c\u308b' do\n      expect {\n        NotificationJob.perform_later(user.id, notification_data)\n      }.to have_enqueued_job(NotificationJob)\n        .with(user.id, notification_data)\n        .on_queue('notifications')\n    end\n\n    it '\u6307\u5b9a\u3055\u308c\u305f\u6642\u9593\u5f8c\u306b\u5b9f\u884c\u3055\u308c\u308b' do\n      expect {\n        NotificationJob.set(wait: 1.hour)\n                      .perform_later(user.id, notification_data)\n      }.to have_enqueued_job(NotificationJob)\n        .with(user.id, notification_data)\n        .on_queue('notifications')\n        .at(1.hour.from_now)\n    end\n  end\n\n  describe '\u30b8\u30e7\u30d6\u306e\u5b9f\u884c' do\n    include ActiveJob::TestHelper\n\n    before do\n      allow(NotificationService).to receive(:send)\n    end\n\n    it '\u901a\u77e5\u30b5\u30fc\u30d3\u30b9\u3092\u547c\u3073\u51fa\u3059' do\n      perform_enqueued_jobs do\n        NotificationJob.perform_later(user.id, notification_data)\n      end\n\n      expect(NotificationService)\n        .to have_received(:send)\n        .with(user.id, notification_data)\n    end\n\n    context '\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u305f\u5834\u5408' do\n      before do\n        allow(NotificationService)\n          .to receive(:send)\n          .and_raise(NotificationService::DeliveryError)\n      end\n\n      it '\u30b8\u30e7\u30d6\u3092\u518d\u8a66\u884c\u3059\u308b' do\n        expect {\n          perform_enqueued_jobs do\n            NotificationJob.perform_later(user.id, notification_data)\n          end\n        }.to raise_error(NotificationService::DeliveryError)\n\n        expect(NotificationJob).to have_been_enqueued.at_least(:once)\n      end\n    end\n  end\nend<\/pre>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"i-50\">\u8907\u96d1\u306a\u691c\u7d22\u6a5f\u80fd\u306e\u30c6\u30b9\u30c8\u30a2\u30d7\u30ed\u30fc\u30c1<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-51\">Elasticsearch\u3092\u4f7f\u7528\u3057\u305f\u691c\u7d22\u6a5f\u80fd\u306e\u30c6\u30b9\u30c8<\/h3>\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=\"\"># spec\/models\/concerns\/searchable_spec.rb\nRSpec.describe Searchable, elasticsearch: true do\n  let(:index_name) { 'test_products' }\n  let(:product_class) do\n    Class.new do\n      include Elasticsearch::Model\n      include Searchable\n\n      index_name 'test_products'\n      document_type 'product'\n\n      def self.name\n        'Product'\n      end\n    end\n  end\n\n  before do\n    product_class.__elasticsearch__.create_index!(force: true)\n  end\n\n  after do\n    product_class.__elasticsearch__.delete_index!\n  end\n\n  describe '.search' do\n    let!(:product1) { create(:product, name: 'Ruby Programming Book') }\n    let!(:product2) { create(:product, name: 'Python Guide') }\n\n    before do\n      product_class.import\n      product_class.__elasticsearch__.refresh_index!\n    end\n\n    context '\u5b8c\u5168\u4e00\u81f4\u691c\u7d22' do\n      it '\u8a72\u5f53\u3059\u308b\u5546\u54c1\u3092\u8fd4\u3059' do\n        results = product_class.search('Ruby Programming Book')\n        expect(results.results.total).to eq(1)\n        expect(results.results.first._source.name)\n          .to eq('Ruby Programming Book')\n      end\n    end\n\n    context '\u30d1\u30fc\u30b7\u30e3\u30eb\u30de\u30c3\u30c1' do\n      it '\u90e8\u5206\u4e00\u81f4\u3059\u308b\u5546\u54c1\u3092\u8fd4\u3059' do\n        results = product_class.search('Ruby')\n        expect(results.results.total).to eq(1)\n      end\n    end\n\n    context '\u30d5\u30a1\u30bb\u30c3\u30c8\u691c\u7d22' do\n      it '\u30ab\u30c6\u30b4\u30ea\u30fc\u3067\u30d5\u30a3\u30eb\u30bf\u30ea\u30f3\u30b0\u3067\u304d\u308b' do\n        results = product_class.search(\n          query: '*',\n          filters: { category: 'programming' }\n        )\n        expect(results.results.total).to eq(2)\n      end\n    end\n\n    context '\u30bd\u30fc\u30c8\u6a5f\u80fd' do\n      it '\u4fa1\u683c\u9806\u3067\u30bd\u30fc\u30c8\u3067\u304d\u308b' do\n        results = product_class.search(\n          query: '*',\n          sort: { price: 'desc' }\n        )\n        prices = results.map { |r| r._source.price }\n        expect(prices).to eq(prices.sort.reverse)\n      end\n    end\n  end\nend<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">\u5b9f\u8df5\u7684\u306a\u30c6\u30b9\u30c8\u3092\u66f8\u304f\u969b\u306e\u91cd\u8981\u306a\u30dd\u30a4\u30f3\u30c8\uff1a<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>API\u8a8d\u8a3c\u30c6\u30b9\u30c8<\/li>\n<\/ol>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u30c8\u30fc\u30af\u30f3\u306e\u751f\u6210\u3068\u691c\u8a3c<\/li>\n\n\n\n<li>\u30a8\u30e9\u30fc\u30b1\u30fc\u30b9\u306e\u7db2\u7f85<\/li>\n\n\n\n<li>\u30bb\u30ad\u30e5\u30ea\u30c6\u30a3\u306e\u8003\u616e<\/li>\n<\/ul>\n\n\n\n<ol class=\"wp-block-list\">\n<li>\u975e\u540c\u671f\u51e6\u7406\u30c6\u30b9\u30c8<\/li>\n<\/ol>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u30b8\u30e7\u30d6\u306e\u30a8\u30f3\u30ad\u30e5\u30fc\u78ba\u8a8d<\/li>\n\n\n\n<li>\u5b9f\u884c\u30bf\u30a4\u30df\u30f3\u30b0\u306e\u691c\u8a3c<\/li>\n\n\n\n<li>\u30a8\u30e9\u30fc\u30cf\u30f3\u30c9\u30ea\u30f3\u30b0<\/li>\n<\/ul>\n\n\n\n<ol class=\"wp-block-list\">\n<li>\u691c\u7d22\u6a5f\u80fd\u30c6\u30b9\u30c8<\/li>\n<\/ol>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u306e\u6e96\u5099<\/li>\n\n\n\n<li>\u591a\u69d8\u306a\u691c\u7d22\u30d1\u30bf\u30fc\u30f3<\/li>\n\n\n\n<li>\u30d1\u30d5\u30a9\u30fc\u30de\u30f3\u30b9\u306e\u8003\u616e<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">\u3053\u308c\u3089\u306e\u5b9f\u8df5\u7684\u306a\u30c6\u30b9\u30c8\u30b1\u30fc\u30b9\u3092\u53c2\u8003\u306b\u3001\u30d7\u30ed\u30b8\u30a7\u30af\u30c8\u306e\u8981\u4ef6\u306b\u5408\u308f\u305b\u3066\u9069\u5207\u306a\u30c6\u30b9\u30c8\u6226\u7565\u3092\u7d44\u307f\u7acb\u3066\u308b\u3053\u3068\u304c\u3067\u304d\u307e\u3059\u3002<\/p>\n","protected":false},"excerpt":{"rendered":"<p>RSpec\u3068\u306f\uff1fRails \u30d7\u30ed\u30b8\u30a7\u30af\u30c8\u306b\u5fc5\u8981\u306a\u30c6\u30b9\u30c8\u30d5\u30ec\u30fc\u30e0\u30ef\u30fc\u30af Ruby on Rails\u306e\u958b\u767a\u306b\u304a\u3044\u3066\u3001\u54c1\u8cea\u306e\u9ad8\u3044\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u3092\u7d99\u7d9a\u7684\u306b\u63d0\u4f9b\u3059\u308b\u305f\u3081\u306b\u306f\u3001\u9069\u5207\u306a\u30c6\u30b9\u30c8\u6226\u7565\u304c\u4e0d\u53ef\u6b20\u3067\u3059\u3002\u305d\u306e\u4e2d\u3067\u3082RSpec\u306f\u3001 &#8230; <\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[3],"tags":[],"class_list":["post-1235","post","type-post","status-publish","format-standard","category-ruby","nothumb"],"_links":{"self":[{"href":"https:\/\/dexall.co.jp\/articles\/index.php?rest_route=\/wp\/v2\/posts\/1235","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=1235"}],"version-history":[{"count":1,"href":"https:\/\/dexall.co.jp\/articles\/index.php?rest_route=\/wp\/v2\/posts\/1235\/revisions"}],"predecessor-version":[{"id":1236,"href":"https:\/\/dexall.co.jp\/articles\/index.php?rest_route=\/wp\/v2\/posts\/1235\/revisions\/1236"}],"wp:attachment":[{"href":"https:\/\/dexall.co.jp\/articles\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1235"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/dexall.co.jp\/articles\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1235"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/dexall.co.jp\/articles\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1235"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}