{"id":160915,"date":"2012-11-30T21:19:04","date_gmt":"2012-11-30T17:19:04","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=160915"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=160915","title":{"rendered":"<span class=\"post_title\">\u041f\u0440\u0438\u043c\u0435\u043d\u0435\u043d\u0438\u0435 \u043f\u0440\u0438\u043d\u0446\u0438\u043f\u0430 DRY \u0432 RSpec<\/span>"},"content":{"rendered":"<div class=\"content html_format\">   \t<img decoding=\"async\" src=\"http:\/\/habrastorage.org\/storage2\/456\/5c2\/334\/4565c2334f270cdd738fdce586e81bd1.jpg\"\/><\/p>\n<p>  DRY(Don\u2019t Repeat Yourself) \u2014 \u043e\u0434\u0438\u043d \u0438\u0437 \u043a\u0440\u0430\u0435\u0443\u0433\u043e\u043b\u044c\u043d\u044b\u0445 \u043f\u0440\u0438\u043d\u0446\u0438\u043f\u043e\u0432 \u0441\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438, \u0430 \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e \u0432 \u0441\u0440\u0435\u0434\u0435 ruby-\u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0441\u0442\u043e\u0432. \u041d\u043e \u0435\u0441\u043b\u0438 \u043f\u0440\u0438 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u0438 \u043e\u0431\u044b\u0447\u043d\u043e\u0433\u043e \u043a\u043e\u0434\u0430 \u043f\u043e\u0432\u0442\u043e\u0440\u044f\u044e\u0449\u0438\u0435\u0441\u044f \u0444\u0440\u0430\u0433\u043c\u0435\u043d\u0442\u044b \u043e\u0431\u044b\u0447\u043d\u043e \u043b\u0435\u0433\u043a\u043e \u043c\u043e\u0436\u043d\u043e \u0441\u0433\u0440\u0443\u043f\u043f\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0432 \u043c\u0435\u0442\u043e\u0434\u044b \u0438\u043b\u0438 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0435 \u043c\u043e\u0434\u0443\u043b\u0438, \u0442\u043e \u043f\u0440\u0438 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u0438 \u0442\u0435\u0441\u0442\u043e\u0432, \u0433\u0434\u0435 \u043f\u043e\u0432\u0442\u043e\u0440\u044f\u044e\u0449\u0435\u0433\u043e\u0441\u044f \u043a\u043e\u0434\u0430 \u043f\u043e\u0440\u043e\u0439 \u0435\u0449\u0435 \u0431\u043e\u043b\u044c\u0448\u0435, \u044d\u0442\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u043d\u0435 \u0432\u0441\u0435\u0433\u0434\u0430 \u043f\u0440\u043e\u0441\u0442\u043e. \u0412 \u0434\u0430\u043d\u043d\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442\u0441\u044f \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0439 \u043e\u0431\u0437\u043e\u0440 \u0441\u0440\u0435\u0434\u0441\u0442\u0432 \u0440\u0435\u0448\u0435\u043d\u0438\u044f \u043f\u043e\u0434\u043e\u0431\u043d\u044b\u0445 \u043f\u0440\u043e\u0431\u043b\u0435\u043c \u043f\u0440\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0438 BDD-\u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a\u0430 RSpec.<br \/>  <a name=\"habracut\"><\/a>  <\/p>\n<h4>1. Shared Examples<\/h4>\n<p>  \u0421\u0430\u043c\u044b\u0439 \u0438\u0437\u0432\u0435\u0441\u0442\u043d\u044b\u0439 \u0438 \u0447\u0430\u0441\u0442\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u044b\u0439 \u043c\u0435\u0442\u043e\u0434 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u043c\u043d\u043e\u0433\u043e\u043a\u0440\u0430\u0442\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u043e\u0433\u043e \u043a\u043e\u0434\u0430 \u0434\u043b\u044f Rspec. \u041e\u0442\u043b\u0438\u0447\u043d\u043e \u043f\u043e\u0434\u0445\u043e\u0434\u0438\u0442 \u0434\u043b\u044f \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043d\u0430\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u043d\u0438\u044f \u043a\u043b\u0430\u0441\u0441\u043e\u0432 \u0438 \u0432\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0439 \u043c\u043e\u0434\u0443\u043b\u0435\u0439.<\/p>\n<pre><code class=\"ruby\">shared_examples &quot;coolable&quot; do   let(:target){described_class.new}    it &quot;should make cool&quot; do     target.make_cool     target.should be_cool   end end  describe User do   it_should_behave_like &quot;coolable&quot; end <\/code><\/pre>\n<p>  \u041a\u0440\u043e\u043c\u0435 \u0442\u043e\u0433\u043e Shared Example Groups \u043e\u0431\u043b\u0430\u0434\u0430\u044e\u0442 \u0438 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u043c \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u043c \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u043e\u043c, \u0447\u0442\u043e \u0434\u0435\u043b\u0430\u0435\u0442 \u0438\u0445 \u0433\u043e\u0440\u0430\u0437\u0434\u043e \u0431\u043e\u043b\u0435\u0435 \u0433\u0438\u0431\u043a\u0438\u043c\u0438 \u0432 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0438: \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0430 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432, \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0430 \u0431\u043b\u043e\u043a\u0430 \u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 let \u0432 \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u0441\u043a\u043e\u0439 \u0433\u0440\u0443\u043f\u043f\u0435 \u0434\u043b\u044f \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u044f \u043c\u0435\u0442\u043e\u0434\u043e\u0432.<\/p>\n<pre><code class=\"ruby\">shared_examples &quot;coolable&quot; do |target_name|   it &quot;should make #{ target_name } cool&quot; do     target.make_cool     target.should be_cool   end end  describe User do   it_should_behave_like &quot;coolable&quot;, &quot;target user&quot; do     let(:target){User.new}   end end <\/code><\/pre>\n<p>  \u041f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0435 \u043e \u0442\u043e\u043c, \u0433\u0434\u0435 \u0438 \u043a\u0430\u043a \u0431\u0443\u0434\u0443\u0442 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u0435 \u043c\u0435\u0442\u043e\u0434\u044b, \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u043e\u0447\u0438\u0442\u0430\u0442\u044c \u0443 \u0414\u044d\u0432\u0438\u0434\u0430 \u0427\u0435\u043b\u0438\u043c\u0441\u043a\u0438[2].<\/p>\n<h4>2. Shared Contexts<\/h4>\n<p>  \u0414\u0430\u043d\u043d\u0430\u044f \u0444\u0438\u0447\u0430 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043c\u0430\u043b\u043e\u0438\u0437\u0432\u0435\u0441\u0442\u043d\u0430 \u0432 \u0441\u0438\u043b\u0443 \u0441\u0432\u043e\u0435\u0439 \u043e\u0442\u043d\u043e\u0441\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0439 \u043d\u043e\u0432\u0438\u0437\u043d\u044b(\u043f\u043e\u044f\u0432\u0438\u043b\u0430\u0441\u044c \u0432 RSpec 2.6) \u0438 \u0443\u0437\u043a\u043e\u0439 \u043e\u0431\u043b\u0430\u0441\u0442\u0438 \u043f\u0440\u0438\u043c\u0435\u043d\u0435\u043d\u0438\u044f. \u041d\u0430\u0438\u0431\u043e\u043b\u0435\u0435 \u043f\u043e\u0434\u0445\u043e\u0434\u044f\u0449\u0435\u0439 \u0441\u0438\u0442\u0443\u0430\u0446\u0438\u0435\u0439 \u0434\u043b\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f shared contexts \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043d\u0430\u043b\u0438\u0447\u0438\u0435 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u0441\u043f\u0435\u043a\u043e\u0432, \u0434\u043b\u044f \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u043d\u0443\u0436\u043d\u044b \u043e\u0434\u0438\u043d\u0430\u043a\u043e\u0432\u044b\u0435 \u043d\u0430\u0447\u0430\u043b\u044c\u043d\u044b\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0438\u043b\u0438 \u0437\u0430\u0432\u0435\u0440\u0448\u0430\u044e\u0449\u0438\u0435 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f, \u043e\u0431\u044b\u0447\u043d\u043e \u0437\u0430\u0434\u0430\u0432\u0430\u0435\u043c\u044b\u0435 \u0432 \u0431\u043b\u043e\u043a\u0430\u0445 before \u0438 after. \u041d\u0430 \u044d\u0442\u043e \u043d\u0430\u043c\u0435\u043a\u0430\u0435\u0442 \u0438 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044f:<\/p>\n<pre><code class=\"ruby\">shared_context &quot;shared stuff&quot;, :a =&gt; :b do   before { @some_var = :some_value }   def shared_method     &quot;it works&quot;   end   let(:shared_let) { {'arbitrary' =&gt; 'object'} }   subject do     'this is the subject'   end end <\/code><\/pre>\n<p>  \u041e\u0447\u0435\u043d\u044c \u0443\u0434\u043e\u0431\u043d\u043e\u0439 \u0432\u0435\u0449\u044c\u044e \u0432 shared_context \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0438\u0445 \u0432\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u043f\u043e \u043c\u0435\u0442\u0430\u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438, \u0437\u0430\u0434\u0430\u043d\u043d\u043e\u0439 \u0432 \u0431\u043b\u043e\u043a\u0435 describe:<\/p>\n<pre><code class=\"ruby\">shared_context &quot;shared with somevar&quot;, :need_values =&gt; 'some_var' do   before { @some_var = :some_value } end  describe &quot;need som_var&quot;, :need_values =&gt; 'some_var' do   it \u201cshould have som_var\u201d do     @some_var.should_not be_nil   end end <\/code><\/pre>\n<h4>3. \u0424\u0430\u0431\u0440\u0438\u043a\u0438 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432<\/h4>\n<p>  \u0415\u0449\u0435 \u043e\u0434\u0438\u043d \u043f\u0440\u043e\u0441\u0442\u043e\u0439, \u043d\u043e \u043e\u0447\u0435\u043d\u044c \u0432\u0430\u0436\u043d\u044b\u0439 \u043f\u0443\u043d\u043a\u0442.<\/p>\n<pre><code class=\"ruby\">@user = User.create(   :email =&gt; \u2018example@example.com\u2019,   :login =&gt; \u2018login1\u2019,   :password =&gt; \u2018password\u2019,   :status =&gt; 1,   \u2026 ) <\/code><\/pre>\n<p>  \u0412\u043c\u0435\u0441\u0442\u043e \u043c\u043d\u043e\u0433\u043e\u043a\u0440\u0430\u0442\u043d\u043e\u0433\u043e \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u043f\u043e\u0434\u043e\u0431\u043d\u044b\u0445 \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u0439 \u0441\u043b\u0435\u0434\u0443\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0433\u0435\u043c <a href=\"https:\/\/github.com\/thoughtbot\/factory_girl\">factory_girl<\/a> \u0438\u043b\u0438 \u0435\u0433\u043e \u0430\u043d\u0430\u043b\u043e\u0433\u0438. \u041f\u0440\u0435\u0438\u043c\u0443\u0449\u0435\u0441\u0442\u0432\u0430 \u043e\u0447\u0435\u0432\u0438\u0434\u043d\u044b: \u0443\u043c\u0435\u043d\u044c\u0448\u0430\u0435\u0442\u0441\u044f \u043e\u0431\u044a\u0435\u043c \u043a\u043e\u0434\u0430 \u0438 \u043d\u0435 \u043d\u0443\u0436\u043d\u043e \u043f\u0435\u0440\u0435\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c \u0432\u0441\u0435 \u0441\u043f\u0435\u043a\u0438, \u0435\u0441\u043b\u0438 \u0432\u044b \u0440\u0435\u0448\u0438\u043b\u0438 \u043f\u043e\u043c\u0435\u043d\u044f\u0442\u044c status \u043d\u0430 status_code.<\/p>\n<h4>4. \u0421\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0435 \u043c\u0430\u0442\u0447\u0435\u0440\u044b<\/h4>\n<p>  \u0412\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0442\u044c \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0435 \u043c\u0430\u0442\u0447\u0435\u0440\u044b \u2014 \u043e\u0434\u043d\u0430 \u0438\u0437 \u0441\u0430\u043c\u044b\u0445 \u043a\u0440\u0443\u0442\u044b\u0445 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0435\u0439 \u0432 RSpec, \u0431\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u044f \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u043c\u043e\u0436\u043d\u043e \u043d\u0435\u0440\u0435\u0430\u043b\u044c\u043d\u043e \u043f\u043e\u0432\u044b\u0441\u0438\u0442\u044c \u0447\u0438\u0442\u0430\u0431\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u0438 \u044d\u043b\u0435\u0433\u0430\u043d\u0442\u043d\u043e\u0441\u0442\u044c \u0432\u0430\u0448\u0438\u0445 \u0441\u043f\u0435\u043a\u043e\u0432. \u0421\u0440\u0430\u0437\u0443 \u043f\u0440\u0438\u043c\u0435\u0440.<br \/>  \u0414\u043e:  <\/p>\n<pre><code class=\"ruby\">it \u201cshould make user cool\u201d do   make_cool(user)   user.coolness.should &gt; 100   user.rating.should &gt; 10   user.cool_things.count.should == 1 end <\/code><\/pre>\n<p>  \u041f\u043e\u0441\u043b\u0435:  <\/p>\n<pre><code class=\"ruby\">RSpec::Matchers.define :be_cool do   match do |actual|            actual.coolness.should &gt; 100 && actual.rating.should &gt; 10 && actual.cool_things.count.should == 1   end end  it \u201cshould make user cool\u201d do   make_cool(user)   user.should be_cool end <\/code><\/pre>\n<p>  \u0421\u043e\u0433\u043b\u0430\u0441\u0438\u0442\u0435\u0441\u044c, \u0441\u0442\u0430\u043b\u043e \u0432 \u0440\u0430\u0437\u044b \u043b\u0443\u0447\u0448\u0435.<br \/>  RSpec \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0437\u0430\u0434\u0430\u0432\u0430\u0442\u044c \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u043e\u0431 \u043e\u0448\u0438\u0431\u043a\u0430\u0445 \u0434\u043b\u044f \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0445 \u043c\u0430\u0442\u0447\u0435\u0440\u043e\u0432, \u0432\u044b\u0432\u043e\u0434\u0438\u0442\u044c \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c \u0447\u0435\u0439\u043d\u0438\u043d\u0433, \u0447\u0442\u043e \u0434\u0435\u043b\u0430\u0435\u0442 \u043c\u0430\u0442\u0447\u0435\u0440\u044b \u0433\u0438\u0431\u043a\u0438\u043c\u0438 \u043d\u0430\u0441\u0442\u043e\u043b\u044c\u043a\u043e, \u0447\u0442\u043e \u043e\u043d\u0438 \u043f\u0440\u043e\u0441\u0442\u043e \u043d\u0438\u0447\u0435\u043c \u043d\u0435 \u043e\u0442\u043b\u0438\u0447\u0430\u044e\u0442\u0441\u044f \u043e\u0442 \u0432\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u044b\u0445. \u0414\u043b\u044f \u043e\u0441\u043e\u0437\u043d\u0430\u043d\u0438\u044f \u0432\u0441\u0435\u0439 \u0438\u0445 \u043c\u043e\u0449\u0438, \u043f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u044e \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u043f\u0440\u0438\u043c\u0435\u0440[1]:<\/p>\n<pre><code class=\"ruby\">RSpec::Matchers.define :have_errors_on do |attribute|   chain :with_message do |message|     @message = message   end   match do |model|     model.valid?     @has_errors = model.errors.key?(attribute)     if @message       @has_errors && model.errors[attribute].include?(@message)     else       @has_errors     end   end   failure_message_for_should do |model|     if @message       &quot;Validation errors #{model.errors[attribute].inspect} should include #{@message.inspect}&quot;     else       &quot;#{model.class} should have errors on attribute #{attribute.inspect}&quot;     end   end   failure_message_for_should_not do |model|     &quot;#{model.class} should not have an error on attribute #{attribute.inspect}&quot;   end end <\/code><\/pre>\n<h4>5. \u041e\u0434\u043d\u043e\u0441\u0442\u0440\u043e\u0447\u043d\u0438\u043a\u0438<\/h4>\n<p>  RSpec \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u043e\u0434\u043d\u043e\u0441\u0442\u0440\u043e\u0447\u043d\u043e\u0433\u043e \u0441\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0441\u0430 \u043f\u0440\u0438 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u0438 \u043f\u0440\u043e\u0441\u0442\u044b\u0445 \u0441\u043f\u0435\u043a\u043e\u0432.<\/p>\n<p>  \u041f\u0440\u0438\u043c\u0435\u0440 \u0438\u0437 \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u0433\u043e opensource-\u043f\u0440\u043e\u0435\u043a\u0442\u0430(<a href=\"https:\/\/github.com\/amatsuda\/kaminari\">kaminari<\/a>):  <\/p>\n<pre><code class=\"ruby\">context 'page 1' do   subject { User.page 1 }     it { should be_a Mongoid::Criteria }     its(:current_page) { should == 1 }     its(:limit_value) { should == 25 }     its(:total_pages) { should == 2 }     it { should skip(0) }   end end <\/code><\/pre>\n<p>  \u042f\u0432\u043d\u043e \u0433\u043e\u0440\u0430\u0437\u0434\u043e \u043b\u0443\u0447\u0448\u0435, \u0447\u0435\u043c:  <\/p>\n<pre><code class=\"ruby\">context 'page 1' do   before :each do     @page = User.page 1   end           it  \u201cshould be a Mongoid criteria\u201d do     @page.should be_a Mongoid::Criteria   end    it \u201cshould have current page set to 1\u201d do     @page.current_page.should == 1   end    \u2026.   #etc <\/code><\/pre>\n<h4>6. \u0414\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u0438 \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0435\u043c\u044b\u0435 \u0441\u043f\u0435\u043a\u0438<\/h4>\n<p>  \u041a\u043b\u044e\u0447\u0435\u0432\u044b\u043c \u043c\u043e\u043c\u0435\u043d\u0442\u043e\u043c \u0437\u0434\u0435\u0441\u044c \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0442\u043e, \u0447\u0442\u043e \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u044f it (\u043a\u0430\u043a \u0432\u043f\u0440\u043e\u0447\u0435\u043c \u0438 context \u0438 describe) \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0432\u0441\u0435\u0433\u043e \u043b\u0438\u0448\u044c \u043c\u0435\u0442\u043e\u0434\u043e\u043c, \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u044e\u0449\u0438\u043c \u0431\u043b\u043e\u043a \u043a\u043e\u0434\u0430 \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u0433\u043e \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u0430. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u0438\u0445 \u043c\u043e\u0436\u043d\u043e \u0432\u044b\u0437\u044b\u0432\u0430\u0442\u044c \u0438 \u0432 \u0446\u0438\u043a\u043b\u0430\u0445, \u0438 \u0432 \u0443\u0441\u043b\u043e\u0432\u0438\u044f\u0445, \u0438 \u0434\u0430\u0436\u0435 \u0441\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0442\u044c \u043f\u043e\u0434\u043e\u0431\u043d\u044b\u0435 \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u0438:<\/p>\n<pre><code class=\"ruby\">it(it(&quot;should process +&quot;){(2+3).should == 5}) do   (3-2).should == 1 end <\/code><\/pre>\n<p>  \u041e\u0431\u0430 \u0441\u043f\u0435\u043a\u0430 \u043a\u0441\u0442\u0430\u0442\u0438 \u043f\u0440\u043e\u0445\u043e\u0434\u044f\u0442 \u0443\u0441\u043f\u0435\u0448\u043d\u043e, \u043d\u043e \u0441\u0442\u0440\u0430\u0448\u043d\u043e \u0434\u0430\u0436\u0435 \u043f\u043e\u0434\u0443\u043c\u0430\u0442\u044c, \u0433\u0434\u0435 \u0442\u0430\u043a\u043e\u0435 \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u0438\u043c\u0435\u043d\u0438\u0442\u044c, \u0432 \u043e\u0442\u043b\u0438\u0447\u0438\u0435 \u043e\u0442 \u0442\u0435\u0445 \u0436\u0435 \u0446\u0438\u043a\u043b\u043e\u0432 \u0438 \u0438\u0442\u0435\u0440\u0430\u0442\u043e\u0440\u043e\u0432. \u041f\u0440\u0438\u043c\u0435\u0440 \u0438\u0437 \u0442\u043e\u0439 \u0436\u0435 Kaminari:<\/p>\n<pre><code class=\"ruby\">[User, Admin, GemDefinedModel].each do |model_class|   context &quot;for #{model_class}&quot; do     describe '#page' do       context 'page 1' do         subject { model_class.page 1 }           it_should_behave_like 'the first page'         end        \u2026      end   end end <\/code><\/pre>\n<p>  \u0418\u043b\u0438 \u0436\u0435 \u043f\u0440\u0438\u043c\u0435\u0440 \u0441 \u0443\u0441\u043b\u043e\u0432\u0438\u044f\u043c\u0438:<\/p>\n<pre><code class=\"ruby\">if Mongoid::VERSION =~ \/^3\/   its(:selector) { should == {'salary' =&gt; 1} } else   its(:selector) { should == {:salary =&gt; 1} } end <\/code><\/pre>\n<h4>7. \u041c\u0430\u043a\u0440\u043e\u0441\u044b<\/h4>\n<p>  \u0412 2010 \u0433\u043e\u0434\u0443, \u043f\u043e\u0441\u043b\u0435 \u0432\u0432\u0435\u0434\u0435\u043d\u0438\u044f \u043d\u043e\u0432\u043e\u0433\u043e \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u0430 shared examples, \u0414\u044d\u0432\u0438\u0434 \u0427\u0435\u043b\u0438\u043c\u0441\u043a\u0438 \u0437\u0430\u044f\u0432\u0438\u043b, \u0447\u0442\u043e \u043c\u0430\u043a\u0440\u043e\u0441\u044b \u0431\u043e\u043b\u044c\u0448\u0435 \u043d\u0435 \u043d\u0443\u0436\u043d\u044b. \u041e\u0434\u043d\u0430\u043a\u043e \u0435\u0441\u043b\u0438 \u0432\u044b \u0432\u0441\u0435 \u0436\u0435 \u0441\u0447\u0438\u0442\u0430\u0435\u0442\u0435, \u0447\u0442\u043e \u044d\u0442\u043e \u043d\u0430\u0438\u0431\u043e\u043b\u0435\u0435 \u043f\u043e\u0434\u0445\u043e\u0434\u044f\u0449\u0438\u0439 \u0441\u043f\u043e\u0441\u043e\u0431 \u0443\u043b\u0443\u0447\u0448\u0438\u0442\u044c \u043a\u043e\u0434 \u0432\u0430\u0448\u0438\u0445 \u0441\u043f\u0435\u043a\u043e\u0432, \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0438\u0445 \u043f\u0440\u0438\u043c\u0435\u0440\u043d\u043e \u0442\u0430\u043a:<\/p>\n<pre><code class=\"ruby\">module SumMacro   def it_should_process_sum(s1, s2, result)     it &quot;should process sum of #{s1} and #{s2}&quot; do       (s1+s2).should == result     end   end end  describe &quot;sum&quot; do   extend SumMacro    it_should_process_sum 2, 3, 5 end <\/code><\/pre>\n<p>  \u0411\u043e\u043b\u0435\u0435 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e \u043e\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0442\u044c\u0441\u044f \u043d\u0430 \u044d\u0442\u043e\u043c \u043f\u0443\u043d\u043a\u0442\u0435 \u0441\u043c\u044b\u0441\u043b\u0430 \u043d\u0435 \u0432\u0438\u0436\u0443, \u043d\u043e \u0435\u0441\u043b\u0438 \u0432\u0430\u043c \u0437\u0430\u0445\u043e\u0447\u0435\u0442\u0441\u044f, \u0442\u043e \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u0447\u0438\u0442\u0430\u0442\u044c [4].<\/p>\n<h4>8. Let \u0438 Subject<\/h4>\n<p>  \u041a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u0438 let \u0438 subject \u043d\u0443\u0436\u043d\u044b \u0434\u043b\u044f \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u0445 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439 \u043f\u0435\u0440\u0435\u0434 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435\u043c \u0441\u043f\u0435\u043a\u043e\u0432. \u041a\u043e\u043d\u0435\u0447\u043d\u043e \u0432\u0441\u0435 \u0438 \u0442\u0430\u043a \u0432 \u043a\u0443\u0440\u0441\u0435, \u0447\u0442\u043e \u043f\u0438\u0441\u0430\u0442\u044c \u0442\u0430\u043a \u0432 \u043a\u0430\u0436\u0434\u043e\u043c \u0441\u043f\u0435\u043a\u0435:  <\/p>\n<pre><code class=\"ruby\">it \u201cshould do something\u201d do   user = User.new   \u2026 end <\/code><\/pre>\n<p>  \u0441\u043e\u0432\u0441\u0435\u043c \u043d\u0435 \u0437\u0434\u043e\u0440\u043e\u0432\u043e, \u043d\u043e \u043e\u0431\u044b\u0447\u043d\u043e \u0432\u0441\u0435 \u043f\u0438\u0445\u0430\u044e\u0442 \u044d\u0442\u043e\u0442 \u043a\u043e\u0434 \u0432 before:<\/p>\n<pre><code class=\"ruby\">before :each do   @user = user.new end <\/code><\/pre>\n<p>  \u0445\u043e\u0442\u044f \u0441\u043b\u0435\u0434\u043e\u0432\u0430\u043b\u043e \u0431\u044c \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c subject. \u0418 \u0435\u0441\u043b\u0438 \u0440\u0430\u043d\u044c\u0448\u0435 subject \u0431\u044b\u043b \u0438\u0441\u043a\u043b\u044e\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u201c\u0431\u0435\u0437\u044b\u043c\u044f\u043d\u043d\u044b\u043c\u201d, \u0442\u043e \u0442\u0435\u043f\u0435\u0440\u044c \u0435\u0433\u043e \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0438 \u0432 \u044f\u0432\u043d\u043e\u043c \u0432\u0438\u0434\u0435, \u0437\u0430\u0434\u0430\u0432\u0430\u044f \u0438\u043c\u044f \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u043c\u043e\u0439 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439:<\/p>\n<pre><code class=\"ruby\">describe &quot;number&quot; do   subject(:number){ 5 }    it &quot;should eql 5&quot; do     number.should == 5   end end <\/code><\/pre>\n<p>  Let \u0441\u0445\u043e\u0436 \u0441 subject\u2019\u043e\u043c, \u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0434\u043b\u044f \u043e\u0431\u044a\u044f\u0432\u043b\u0435\u043d\u0438\u044f \u043c\u0435\u0442\u043e\u0434\u043e\u0432.<\/p>\n<h4>\u0414\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u0441\u0441\u044b\u043b\u043a\u0438<\/h4>\n<p>  1. Custom RSpec-2 Matchers<br \/>  <a href=\"http:\/\/solnic.eu\/2011\/01\/14\/custom-rspec-2-matchers.html\">solnic.eu\/2011\/01\/14\/custom-rspec-2-matchers.html<\/a><br \/>  2. David Chelimsky \u2014 Specifying mixins with shared example groups in RSpec-2<br \/>  <a href=\"http:\/\/blog.davidchelimsky.net\/2010\/11\/07\/specifying-mixins-with-shared-example-groups-in-rspec-2\/\">blog.davidchelimsky.net\/2010\/11\/07\/specifying-mixins-with-shared-example-groups-in-rspec-2\/<\/a><br \/>  3. Ben Scheirman \u2014 Dry Up Your Rspec Files With Subject &#038; Let Blocks<br \/>  <a href=\"http:\/\/benscheirman.com\/2011\/05\/dry-up-your-rspec-files-with-subject-let-blocks\">benscheirman.com\/2011\/05\/dry-up-your-rspec-files-with-subject-let-blocks<\/a><br \/>  4. Ben Mabey \u2014 Writing Macros in RSpec<br \/>  <a href=\"http:\/\/benmabey.com\/2008\/06\/08\/writing-macros-in-rspec.html\">benmabey.com\/2008\/06\/08\/writing-macros-in-rspec.html<\/a><\/p>\n<p>  \u0410 \u0432 \u0437\u0430\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 \u043c\u043e\u0433\u0443 \u0442\u043e\u043b\u044c\u043a\u043e \u0441\u043a\u0430\u0437\u0430\u0442\u044c \u043c\u043e\u0433\u0443 \u0442\u043e\u043b\u044c\u043a\u043e \u0441\u043a\u0430\u0437\u0430\u0442\u044c \u2014 \u0441\u0442\u0430\u0440\u0430\u0439\u0442\u0435\u0441\u044c \u043c\u0435\u043d\u044c\u0448\u0435 \u043f\u043e\u0432\u0442\u043e\u0440\u044f\u0442\u044c\u0441\u044f.    \t   \t<\/p>\n<div class=\"clear\"><\/div>\n<\/p><\/div>\n<p> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"http:\/\/habrahabr.ru\/post\/160915\/\"> http:\/\/habrahabr.ru\/post\/160915\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<div class=\"content html_format\">   \t<img decoding=\"async\" src=\"http:\/\/habrastorage.org\/storage2\/456\/5c2\/334\/4565c2334f270cdd738fdce586e81bd1.jpg\"\/><\/p>\n<p>  DRY(Don\u2019t Repeat Yourself) \u2014 \u043e\u0434\u0438\u043d \u0438\u0437 \u043a\u0440\u0430\u0435\u0443\u0433\u043e\u043b\u044c\u043d\u044b\u0445 \u043f\u0440\u0438\u043d\u0446\u0438\u043f\u043e\u0432 \u0441\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438, \u0430 \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e \u0432 \u0441\u0440\u0435\u0434\u0435 ruby-\u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0441\u0442\u043e\u0432. \u041d\u043e \u0435\u0441\u043b\u0438 \u043f\u0440\u0438 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u0438 \u043e\u0431\u044b\u0447\u043d\u043e\u0433\u043e \u043a\u043e\u0434\u0430 \u043f\u043e\u0432\u0442\u043e\u0440\u044f\u044e\u0449\u0438\u0435\u0441\u044f \u0444\u0440\u0430\u0433\u043c\u0435\u043d\u0442\u044b \u043e\u0431\u044b\u0447\u043d\u043e \u043b\u0435\u0433\u043a\u043e \u043c\u043e\u0436\u043d\u043e \u0441\u0433\u0440\u0443\u043f\u043f\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0432 \u043c\u0435\u0442\u043e\u0434\u044b \u0438\u043b\u0438 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0435 \u043c\u043e\u0434\u0443\u043b\u0438, \u0442\u043e \u043f\u0440\u0438 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u0438 \u0442\u0435\u0441\u0442\u043e\u0432, \u0433\u0434\u0435 \u043f\u043e\u0432\u0442\u043e\u0440\u044f\u044e\u0449\u0435\u0433\u043e\u0441\u044f \u043a\u043e\u0434\u0430 \u043f\u043e\u0440\u043e\u0439 \u0435\u0449\u0435 \u0431\u043e\u043b\u044c\u0448\u0435, \u044d\u0442\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u043d\u0435 \u0432\u0441\u0435\u0433\u0434\u0430 \u043f\u0440\u043e\u0441\u0442\u043e. \u0412 \u0434\u0430\u043d\u043d\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442\u0441\u044f \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0439 \u043e\u0431\u0437\u043e\u0440 \u0441\u0440\u0435\u0434\u0441\u0442\u0432 \u0440\u0435\u0448\u0435\u043d\u0438\u044f \u043f\u043e\u0434\u043e\u0431\u043d\u044b\u0445 \u043f\u0440\u043e\u0431\u043b\u0435\u043c \u043f\u0440\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0438 BDD-\u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a\u0430 RSpec.  <\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-160915","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/160915","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=160915"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/160915\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=160915"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=160915"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=160915"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}