めもめも。

この記事はRubyもRailsもよくわかっていない人が自分のためのメモとしてだらだら書きました。リファレンスがよくわからなかったので、動かして試してみた感じです。

RSpecは(Railsに限らず)Rubyで動くテストフレームワーク。Railsに最初から入ってるTest::Unitよりも色々と良いらしい……けどそっちも使った事がないので比較はできません。

RubyじゃなくてRailsから利用する視点から俺用にまとめます。

環境

$ ruby -v
ruby 1.9.2p290 (2011-07-09 revision 32553) [i686-linux]
$ rails -v
Rails 3.2.1

インストール

Gemfileに記述。

gem 'rspec-rails'

でbundleすると、関連Gemもまとめて入る。

あとRSpecの共通ファイルを用意させる必要がある。

rails g rspec:install

インストールはこれでおわり。

scaffold

テストユニットが自動でRSpecに変更されてるみたい。scaffoldすると、既存のtest/には何も作られないで、代わりにspec/配下にあれこれテストが作成された。

rails g scaffold item name:string price:integer description:text on_sales:boolean
rake db:migrate
spec/
 + controllers/
   + items_controller_spec.rb
 + helpers/
   + items_helper_spec.rb
 + models/
   + item_spec.rb
 + requests/
   + items_spec.rb
 + routing/
   + items_routing_spec.rb
 + spec_helper.rb
 + views/
   + items/
     + edit.html.erb_spec.rb
     + new.html.erb_spec.rb
     + index.html.erb_spec.rb
     + show.html.erb_spec.rb

fixtureがないね。

scaffoldじゃなくて、個別にcontrollerやmodelを作成したときも同じような感じで(必要な分だけ)作られるみたい。

テスト実行

rakeから実行します。

rake spec

**............................ Pending: Item add some examples to (or delete) /.../spec/models/item_spec.rb # No reason given # ./spec/models/item_spec.rb:4 ItemsHelper add some examples to (or delete) /.../spec/helpers/items_helper_spec.rb # No reason given # ./spec/helpers/items_helper_spec.rb:14 Finished in 0.75908 seconds 30 examples, 0 failures, 2 pending

……だ、そうです。

pendingって?

【形容詞】
1. 未決定で,係争中で; 宙ぶらりんで.

テストに失敗はしてないけど、まだ合格ってほどでもない状態、かな。

  • spec/models/item_spec.rb
describe Item do
  pending "add some examples to (or delete) #{__FILE__}"
end

そういえばTest::Unitの方もModelの試験は最初は空だったよなあ。モデルがどう振る舞うかってのはscaffoldの時点ではまだわからないから、かな。Helperもわからないね。

ModelとHelperの試験を空に(pendingを削除)すると、オールグリーンになる。

............................

Finished in 0.84017 seconds
28 examples, 0 failures

なるほど。

「実装の途中でリファクタリングが残ってるけど今書ける分の試験だけとりあえず全部書いたよ」ってときに、最後にpending付けておくと、漏れがなくて良いんじゃないだろうか。この機能、QUnitにも欲しい……。

試験を見てみる

の前に。

RSpecの試験の基本的な書き方

見た感じ、こんな風に書くっぽい。

describe 'What be tested' do
  it 'will should do' do
    any.status.should value
  end
end

It will should doのitが差すもの、つまり試験の主語はdescribeに与えたものであるらしい。

日本語的に書くとこうかな?

describe '自動販売機' do
  it '(に)お金を入れると商品が出てくる' do
    出てきたもの = 自動販売機.お金を入れる(120円)
    出てきたもの.数.は 1個
  end
end

Controllerの試験を見てみる

  • spec/controllers/items_controller_spec.rb

なんか冒頭に長々と説明が……。

# This spec was generated by rspec-rails when you ran the scaffold generator.
# It demonstrates how one might use RSpec to specify the controller code that
# was generated by Rails when you ran the scaffold generator.
#
# It assumes that the implementation code is generated by the rails scaffold
# generator.  If you are using any extension libraries to generate different
# controller code, this generated spec may or may not pass.
#
# It only uses APIs available in rails and/or rspec-rails.  There are a number
# of tools you can use to make these specs even more expressive, but we're
# sticking to rails and rspec-rails APIs to keep things simple and stable.
#
# Compared to earlier versions of this generator, there is very limited use of
# stubs and message expectations in this spec.  Stubs are only used when there
# is no simpler way to get a handle on the object needed for the example.
# Message expectations are only used when there is no simpler way to specify
# that an instance is receiving a specific message.

ええと、何なに?

  • これはscaffoldで作られたspecです。
  • scaffoldで生成される一通りのコードに対応してます。
  • あーでもプラグインとか使ってたら、合格するかどうかわかんないです。
  • コードはRailsとRSpec-RailsのAPIだけを使ってます。
    • (他のライブラリーに依存していないということ?)
  • 以前のバージョンと比べて、スタブやメッセージはあんまり使わなくなりました。

これで合ってる?

GET index

ヘルパー的な?メソッドは飛ばすと、最初の試験はこれ。

describe ItemsController do

  ...

  describe "GET index" do
    it "assigns all items as @items" do
      item = Item.create! valid_attributes
      get :index, {}, valid_session
      assigns(:items).should eq([item])
    end
  end

  ...

へえdescribeて入れ子にできるんだ。試験のタイトルは全部繋がってItemsController GET index assigns all items as @itemsになった。「ItemsControllerのGET indexは、全ての項目を@itemsに割り当てる」のだそうだ。

最初の行で試験用のデータからitemsを生成して、GET indexのリクエストを投げてみて、結果として@itemsに対し、(さっき作った)itemsと同じものが割り振られていれば、合格という事か。

assigns(:hoge).shouldで@hogeの中身を試験できるって事かな? RDocでassignsってメソッドが見つけられない……。Railsの方から探したら同じ名前のがあったけど、これかな?

self.classがRSpec::Core::ExampleGroup::Nested_3::Nested_1になってたから、同じような別物、かな。わからない。

ええと、気を取り直して。

valid_attributesとvalid_sessionは{}を返すメソッドと(上の方で)定義されていた。

Fixtureみたいなもの? 複数ある場合はどうやって指定するんだろう? ……と思ったけど、よくみるとItem.create!というメソッドなので、これは「newしてすぐsaveする」というものなので、ここで作っていた。複数作るならこれを複数やる必要があるのか。

別途Fixtureを使うやり方もありそうだけど、まだわからない。

プロパティはそのまま参照できる

と言ってしまうのには違和感がありますが、まあ扱うのは違和感なくできるみたいです。

例えば「最近の10件を表示」なんてときはこんな風に試験書いたらよさそうかな。

    it 'assigns latest 10 items as @item' do
      attr = valid_attributes.clone
      1.step(15,1) do |i|
        attr[:name] = "Item#{i}"
        Item.create! attr
      end

      get :index, {}, valid_session
      assigns(:items).size.should eq(10)
      assigns(:items)[0].name.should eq('Item15')
    end

GET show

だいたいGET indexと同じだけど、パラメーターを与えている。

  describe "GET show" do
    it "assigns the requested item as @item" do
      item = Item.create! valid_attributes
      get :show, {:id => item.to_param}, valid_session
      assigns(:item).should eq(item)
    end
  end

getの引数、さっきは:indexと{}だったのが:showと{:id => item.to_param}になってる。なるほど第2引数でパラメーターを与えられるのか。第3引数は、書いてある通りセッションだな。

Get new

  describe "GET new" do
    it "assigns a new item as @item" do
      get :new, {}, valid_session
      assigns(:item).should be_a_new(Item)
    end
  end

eqでなくbe_a_newときた。これをeqに書き換えてみると、試験が不合格になる。

      assigns(:item).should eq(Item.new)
Failures:

  1) ItemsController GET new assigns a new item as @item
     Failure/Error: assigns(:item).should eq(Item.new)

       expected: #<Item id: nil, name: nil, price: nil, description: nil, on_sales: nil, created_at: nil, updated_at: nil>
            got: #<Item id: nil, name: nil, price: nil, description: nil, on_sales: nil, created_at: nil, updated_at: nil>

       (compared using ==)

まあオブジェクト同士を==で比較したらfalseになるのは当然。

ん、じゃあさっきGET showでeq(item)がtrueになったのは??

  describe "GET show" do
    it "assigns the requested item as @item" do
      item = Item.create! valid_attributes
      get :show, {:id => item.to_param}, valid_session
      assigns(:item).should eq(item)

      item2 = Item.new
      item2.id = item.id
      assigns(:item).should eq(item2)
    end
  end

なるほど、IDがある場合はIDが合致するかで確認してるのね。IDがnilの場合はそうしないから、be_a_newで確認する必要がある、と。

GET edit

特に見所なし。GET showとやる事は一緒だものね。

POST create

おお、これはなんかややこしい感じになってる。


  describe "POST create" do
    describe "with valid params" do
      it "creates a new Item" do
        expect {
          post :create, {:item => valid_attributes}, valid_session
        }.to change(Item, :count).by(1)
      end

      it "assigns a newly created item as @item" do
        post :create, {:item => valid_attributes}, valid_session
        assigns(:item).should be_a(Item)
        assigns(:item).should be_persisted
      end

      it "redirects to the created item" do
        post :create, {:item => valid_attributes}, valid_session
        response.should redirect_to(Item.last)
      end
    end

    describe "with invalid params" do
      it "assigns a newly created but unsaved item as @item" do
        # Trigger the behavior that occurs when invalid params are submitted
        Item.any_instance.stub(:save).and_return(false)
        post :create, {:item => {}}, valid_session
        assigns(:item).should be_a_new(Item)
      end

      it "re-renders the 'new' template" do
        # Trigger the behavior that occurs when invalid params are submitted
        Item.any_instance.stub(:save).and_return(false)
        post :create, {:item => {}}, valid_session
        response.should render_template("new")
      end
    end
  end

順に見て行こうかね。

DBに追加

    describe "with valid params" do
      it "creates a new Item" do
        expect {
          post :create, {:item => valid_attributes}, valid_session
        }.to change(Item, :count).by(1)
      end

postするとItemの数が1増える、という内容だと思う。byは「いくつになるか」ではなく「いくつ増えるか」を書く。だから先にItem.createを何度やっていたとしても、by(1)。あとexpect内でいくつ増えるか、を確認してる。

      it "creates a new Item" do
        Item.create! valid_attributes
        Item.create! valid_attributes
        expect {
          Item.create! valid_attributes
          post :create, {:item => valid_attributes}, valid_session
        }.to change(Item, :count).by(2)
      end

はい次。

オブジェクト作成

      it "assigns a newly created item as @item" do
        post :create, {:item => valid_attributes}, valid_session
        assigns(:item).should be_a(Item)
        assigns(:item).should be_persisted
      end

be_aとbe_persistedが初出なくらいか。be_persistedて何? persistで「(消えずに)在る」て意味だから、nilじゃないかって確認? でもそれならbe_a(Item)が通るなら無意味では?

どうやら「DBに在る」という確認であるらしい。

be_xxx

be_xxxでobj.xxx?に相当するらしい。

つまりbe_persistedはActiveRecord::Persistence – persisted?()を実行する。

似たもので、has_xxx?を実行するhave_xxxというのもあるらしい。

リダイレクト

      it "redirects to the created item" do
        post :create, {:item => valid_attributes}, valid_session
        response.should redirect_to(Item.last)
      end

読めばわかる。

ここまで、with valid paramsなときについてのdescription。

ここからは不正な入力についてです。

    describe "with invalid params" do

不正な入力のときは、DBに保存されていない@itemを新しく作る

      it "assigns a newly created but unsaved item as @item" do
        # Trigger the behavior that occurs when invalid params are submitted
        Item.any_instance.stub(:save).and_return(false)
        post :create, {:item => {}}, valid_session
        assigns(:item).should be_a_new(Item)
      end

謎の呪文Item.any_instance.stub(:save).and_return(false)が怖いです。他は良いかな。

読むとなんとなくわかる。きっと「Itemのどのインスタンスでも、saveメソッドはfalseを返すスタブに置き換える」ってな意味なんだろう。

で、saveが失敗したときに@itemがちゃんと作られている事を確認する。どんなときに失敗するか、はControllerじゃなくてModelの管理下だな。

{:item => {}}はよくわからない。{}でもいいんじゃないの? 実際にそれでも試験は合格になる。それとも{:item => { name: 'MyName' }}にしてassigns(:item).name.should eq('MyName')みたいにするために用意してあるんだろうか。

不正な入力のときは、newのテンプレートで出力される

      it "re-renders the 'new' template" do
        # Trigger the behavior that occurs when invalid params are submitted
        Item.any_instance.stub(:save).and_return(false)
        post :create, {:item => {}}, valid_session
        response.should render_template("new")
      end

アクションと対応しないテンプレートを出力するときはrender_templateで確認、と。ふむふむ。

これでPOST createの試験はおわり。ふうー。

POT update

これもまた長い。

  describe "PUT update" do
    describe "with valid params" do
      it "updates the requested item" do
        item = Item.create! valid_attributes
        # Assuming there are no other items in the database, this
        # specifies that the Item created on the previous line
        # receives the :update_attributes message with whatever params are
        # submitted in the request.
        Item.any_instance.should_receive(:update_attributes).with({'these' => 'params'})
        put :update, {:id => item.to_param, :item => {'these' => 'params'}}, valid_session
      end

      it "assigns the requested item as @item" do
        item = Item.create! valid_attributes
        put :update, {:id => item.to_param, :item => valid_attributes}, valid_session
        assigns(:item).should eq(item)
      end

      it "redirects to the item" do
        item = Item.create! valid_attributes
        put :update, {:id => item.to_param, :item => valid_attributes}, valid_session
        response.should redirect_to(item)
      end
    end

    describe "with invalid params" do
      it "assigns the item as @item" do
        item = Item.create! valid_attributes
        # Trigger the behavior that occurs when invalid params are submitted
        Item.any_instance.stub(:save).and_return(false)
        put :update, {:id => item.to_param, :item => {}}, valid_session
        assigns(:item).should eq(item)
      end

      it "re-renders the 'edit' template" do
        item = Item.create! valid_attributes
        # Trigger the behavior that occurs when invalid params are submitted
        Item.any_instance.stub(:save).and_return(false)
        put :update, {:id => item.to_param, :item => {}}, valid_session
        response.should render_template("edit")
      end
    end
  end

更新成功

なんかコメントが。

# Assuming there are no other items in the database, this
# specifies that the Item created on the previous line
# receives the :update_attributes message with whatever params are
# submitted in the request.

ええと?

  • DBには他の項目がないものとして、上の行で作ったItemオブジェクトはどんなパラメーター(リクエストで飛んできたやつ)でも:update_attributesで受け取る、という事を確認します。

DBに他の項目があってもいいんじゃないの?

まあそれは置いておいて、ともかくどんなパラメーターでも:update_attributesという名前のメッセージ(OOP的な表現だけど、詰まる所メソッド)で受け取る、と。theseなんてカラムは定義してないけれど、受け取るだけ受け取ってますよという事かな。

ここで確認するのは、DBを更新するメソッドを呼ぶところまで。実際にDBが更新される事の確認はModelの試験で。

リクエスト通りの@itemを作成

      it "assigns the requested item as @item" do
        item = Item.create! valid_attributes
        put :update, {:id => item.to_param, :item => valid_attributes}, valid_session
        assigns(:item).should eq(item)
      end

GET showと概ね同じか。

リダイレクト

特に見るところはないっす。うっす。

不正な入力のときでも、@itemが作られる

特に見るところはないっす。うっすうっす。

不正な入力のときは、editのテンプレートで出力される

特にうっす。

DELETE destroy

ひゃーやっとControllerの最後だ。

<

div>

  describe &quot;DELETE destroy&quot; do
    it &quot;destroys the requested item&quot; do
      item = Item.create! valid_attributes
      expect {
        delete :destroy, {:id =&gt; item.to_param}, valid_session
      }.to change(Item, :count).by(-1)
    end</p>

<pre><code>it &amp;quot;redirects to the items list&amp;quot; do
  item = Item.create! valid_attributes
  delete :destroy, {:id =&amp;gt; item.to_param}, valid_session
  response.should redirect_to(items_url)
end
</code></pre>

<p>end

ここまで見てくると、もう「へえーなるほど」てな感じ。

おつかれさまでした。全28個中、16個のexamplesがControllerにあるという事か。

リクエストの試験

Named routesの試験という事なのかな?

  • spec/requests/items_spec.rb
describe "Items" do
  describe "GET /items" do
    it "works! (now write some real specs)" do
      # Run the generator again with the --webrat flag if you want to use webrat methods/matchers
      get items_path
      response.status.should be(200)
    end
  end
end

items_pathをgetしたらHTTPのステータスコードが200になる、なんだけど、このパスでリクエストを投げたらitems#indexが実行する事も確かめなくちゃいけないような。いやそれはルーティングの試験だから別(次項)か。

items_pathが/itemsを返す事はどうやって確認するんだろう?

ルーティングの試験

  • spec/routing/items_routing_spec.rb
describe ItemsController do
  describe "routing" do

    it "routes to #index" do
      get("/items").should route_to("items#index")
    end

    it "routes to #new" do
      get("/items/new").should route_to("items#new")
    end

    it "routes to #show" do
      get("/items/1").should route_to("items#show", :id => "1")
    end

    it "routes to #edit" do
      get("/items/1/edit").should route_to("items#edit", :id => "1")
    end

    it "routes to #create" do
      post("/items").should route_to("items#create")
    end

    it "routes to #update" do
      put("/items/1").should route_to("items#update", :id => "1")
    end

    it "routes to #destroy" do
      delete("/items/1").should route_to("items#destroy", :id => "1")
    end

  end
end

route_toだって。

これだけ見ると阿呆っぽいけど(resourceの試験みたいだし)、routes.rbを本気でいじりだしたら便利かも。

こっちはリクエストの試験と違って、items_pathじゃなくて`”/items”みたいにパスが直接書かれているんだけど、どういう使い分けなんだろうか……。

indexのView

describe "items/index" do
  before(:each) do
    assign(:items, [
      stub_model(Item,
        :name => "Name",
        :price => 1,
        :description => "MyText",
        :on_sales => false
      ),
      stub_model(Item,
        :name => "Name",
        :price => 1,
        :description => "MyText",
        :on_sales => false
      )
    ])
  end

  it "renders a list of items" do
    render
    # Run the generator again with the --webrat flag if you want to use webrat matchers
    assert_select "tr>td", :text => "Name".to_s, :count => 2
    # Run the generator again with the --webrat flag if you want to use webrat matchers
    assert_select "tr>td", :text => 1.to_s, :count => 2
    # Run the generator again with the --webrat flag if you want to use webrat matchers
    assert_select "tr>td", :text => "MyText".to_s, :count => 2
    # Run the generator again with the --webrat flag if you want to use webrat matchers
    assert_select "tr>td", :text => false.to_s, :count => 2
  end
end

beforeとassignとstub_modelが目新しい感じ。

beforeだって。引数にitに与えた名前(ここなら"renders a list of items")を与える事で個別に指定できるみたい。あと同じようにafterというものもあった。

で、やってる処理はassign。さっき出てきたassignsはインスタンス変数を取ってきたけど、ここのは逆に変数に値を与える事ができるみたい。

stub_modelはその名の通りモデルのスタブを作るメソッドか。

カラム名にあたるシンボルは、元のモデルに縛られないみたい。適当な名前で値を渡しても、通る。また省略した場合も元々あるものは出力される。(:name =>を:hoge =>にすると、Viewではnameもhogeも使える。) その場合、代入されていないカラムはnilになってるっぽい。

renderはHTMLを出力するやつですね。format.jsonとか、HTML以外のときはどうするのかなあ。

assert_select

これはRailsの方のメソッドみたい。

:countは確認項目(assertion)だけど:textの方は絞り込みの条件(narrowing)であるらしい。*argsはこんな感じか。

*args := [container_element,] selector [, condition [, ...]]

selectorはcontainer_element自体にも有効であるらしい。つまりE内で.cとしたらE.cとE .cを探す。

:textには正規表現も使えるらしい。

で、入れ子に出来る。例えばフォームに使うlabel要素には全てhogeクラスが与えられている、という確認を考える。

it 'renders all labels with `hoge` class' do
  assert_select 'form#myform label' do
    assert_select '.hoge'
  end
end

label要素を全部探してきて、それぞれについて.hogeにマッチする事を確認すると。

数がわかっていればlabel.hogeに:countでも良さそうだけど、でもそれだと.hogeが与えられていないlabelがあると困る。

ええと、そういうわけで、

assert_select "tr>td", :text => "Name".to_s, :count => 2

これ↑は、

  • セレクターtr>tdにマッチし、
  • かつ内容の文字列が"Name"であるものが、
  • 2個ある

↑という確認です。

webrat??

# Run the generator again with the --webrat flag if you want to use webrat matchers

なんかCucumberってのと組み合わせて、良い感じに試験項目を記述できるツールらしい。

  シナリオ: 新しいエントリの登録
    前提 エントリ新規作成ページを表示している
    かつ "タイトル"に"Webratがスゴい(続:Cucumberがアツい)"と入力する
    かつ "本文"に"Railsアプリのテストを高い抽象度で・・・"と入力する。
    かつ "Create"ボタンをクリックする
    ならば "Webratがスゴい"と表示されていること

うおおおおおおおおなにこれすごいやばい超便利じゃね? これならプログラミングが全くできない人でも理解できる。(プログラミングでも必要な論理思考力は必要そうだけど。) 次はこれ見てみないと。

でも次ね。RSpec見終わってからね。

showのView

describe "items/show" do
  before(:each) do
    @item = assign(:item, stub_model(Item,
      :name => "Name",
      :price => 1,
      :description => "MyText",
      :on_sales => false
    ))
  end

  it "renders attributes in <p>" do
    render
    # Run the generator again with the --webrat flag if you want to use webrat matchers
    rendered.should match(/Name/)
    # Run the generator again with the --webrat flag if you want to use webrat matchers
    rendered.should match(/1/)
    # Run the generator again with the --webrat flag if you want to use webrat matchers
    rendered.should match(/MyText/)
    # Run the generator again with the --webrat flag if you want to use webrat matchers
    rendered.should match(/false/)
  end
end

renderedはStringで、出力されたHTMLがまるごと入ってるようです。ただブラウザーに送信されるHTMLではなくこのViewが担当している部分だけ。

editのView

describe "items/edit" do
  before(:each) do
    @item = assign(:item, stub_model(Item,
      :name => "MyString",
      :price => 1,
      :description => "MyText",
      :on_sales => false
    ))
  end

  it "renders the edit item form" do
    render

    # Run the generator again with the --webrat flag if you want to use webrat matchers
    assert_select "form", :action => items_path(@item), :method => "post" do
      assert_select "input#item_name", :name => "item[name]"
      assert_select "input#item_price", :name => "item[price]"
      assert_select "textarea#item_description", :name => "item[description]"
      assert_select "input#item_on_sales", :name => "item[on_sales]"
    end
  end
end

お、assert_selectを活用してる。:action, :method, :nameというものがあるのか。いやHTMLの要素を指定できるだけ?

じゃあ、inputのvalueを確認するのにこういうのはどうだ?

assert_select "input#item_name", :name => "item[name]", :value => 'hoge'

当然Failureをなる事を期待したんだが、ならなかった。ううむ。

assert_select "input#item_name", :name => "item[name]" do
  assert_select "[value=#{@item.name}]"
end

こっちの書き方なら使える。(セレクターはもちろんまとめても同じ結果になるんだけど、分けた方が読みやすいかなと。)(あと、本当はエスケープしないとセレクターが崩壊するよ。) ううむ、入力値を確認する方法は別途用意されているのかな。

newのView

ほとんどeditと同じ。

違うのは試験用の@itemを作成せず、Viewの方で@itemに割り当てられるものにas_new_recordする、というあたり。

describe "items/new" do
  before(:each) do
    assign(:item, stub_model(Item,
      :name => "MyString",
      :price => 1,
      :description => "MyText",
      :on_sales => false
    ).as_new_record)
  end

新規作成なんだから、インスタンス変数の値は軒並みnilであるべきなんじゃないか?

ええと、これで一通り見たかな。

まとめ

  • すっげえ便利そう。
  • 書式は英語的に読みやすい、たぶん。がんばれ俺(日本人)。
  • リファレンス的なものが見づらい、というかどこかにあるの??
    • 公式サイトにDocumentationという事でRDocにリンクがあるけど、ここに載ってないのもある……。
    • Controllerの試験のbe_xxxなんかは自動生成ぽいから、文書には未掲載なんだろうと思う。
    • RSpecのメソッドなのかRailsのメソッドなのか、もしかしてRuby標準のメソッドなのか区別が付かない。(勘が足りない)
  • Railsに限らずRubyで便利そう。
    • でも-bash: rspec: command not foundて言われる。 (´・ω・`)
  • webratすごそう、早く試したい。
  • Named routesの試験方法はよくわかんない。

とっぴんぱらりのぷう。