আরএসপেক: একাধিক পরিবর্তনের প্রত্যাশা


86

কোনও বৈশিষ্ট্যে বর্ণিত ফর্ম জমা দেওয়ার সময় আমি কোনও মডেলটিতে অনেক পরিবর্তন পরীক্ষা করতে চাই। উদাহরণস্বরূপ, আমি নিশ্চিত করতে চাই যে ব্যবহারকারীর নামটি X থেকে Y এ পরিবর্তিত হয়েছে এবং এনক্রিপ্ট হওয়া পাসওয়ার্ডটি কোনও মান দ্বারা পরিবর্তিত হয়েছিল।

আমি জানি যে এটি সম্পর্কে ইতিমধ্যে কিছু প্রশ্ন রয়েছে তবে আমি আমার পক্ষে উপযুক্ত উত্তর খুঁজে পাইনি। সর্বাধিক সঠিক উত্তরটি ChangeMultipleএখানে মাইকেল জনস্টনের ম্যাচারের মতো বলে মনে হচ্ছে : আরএসপেকের পক্ষে কি দুটি টেবিলের পরিবর্তনের আশা করা সম্ভব? । এর খারাপ দিকটি হ'ল একমাত্র পরিচিত মান থেকে জানা মানগুলিতে সুস্পষ্ট পরিবর্তনগুলি পরীক্ষা করে।

আমি কীভাবে আরও ভাল ম্যাচারের মতো দেখতে পেতাম সে সম্পর্কে আমি কিছু ছদ্ম কোড তৈরি করেছি:

expect {
  click_button 'Save'
}.to change_multiple { @user.reload }.with_expectations(
  name:               {from: 'donald', to: 'gustav'},
  updated_at:         {by: 4},
  great_field:        {by_at_leaset: 23},
  encrypted_password: true,  # Must change
  created_at:         false, # Must not change
  some_other_field:   nil    # Doesn't matter, but want to denote here that this field exists
)

আমি ChangeMultipleম্যাচারের প্রাথমিক কঙ্কালটিও এর মতো তৈরি করেছি:

module RSpec
  module Matchers
    def change_multiple(receiver=nil, message=nil, &block)
      BuiltIn::ChangeMultiple.new(receiver, message, &block)
    end

    module BuiltIn
      class ChangeMultiple < Change
        def with_expectations(expectations)
          # What to do here? How do I add the expectations passed as argument?
        end
      end
    end
  end
end

তবে এখন আমি ইতিমধ্যে এই ত্রুটিটি পাচ্ছি:

 Failure/Error: expect {
   You must pass an argument rather than a block to use the provided matcher (nil), or the matcher must implement `supports_block_expectations?`.
 # ./spec/features/user/registration/edit_spec.rb:20:in `block (2 levels) in <top (required)>'
 # /Users/josh/.rvm/gems/ruby-2.1.0@base/gems/activesupport-4.2.0/lib/active_support/dependencies.rb:268:in `load'
 # /Users/josh/.rvm/gems/ruby-2.1.0@base/gems/activesupport-4.2.0/lib/active_support/dependencies.rb:268:in `block in load'

এই কাস্টম ম্যাচার তৈরিতে যে কোনও সহায়তা প্রশংসিত হয়।

উত্তর:


190

আরএসপেক 3 এ আপনি একবারে একাধিক শর্ত নির্ধারণ করতে পারেন (যাতে একক প্রত্যাশার নিয়ম ভাঙা হয় না)। এটি দেখতে sth মত হবে:

expect {
  click_button 'Save'
  @user.reload
}.to change { @user.name }.from('donald').to('gustav')
 .and change { @user.updated_at }.by(4)
 .and change { @user.great_field }.by_at_least(23}
 .and change { @user.encrypted_password }

যদিও এটি সম্পূর্ণ সমাধান নয় - আমার গবেষণা যতদূর গেছে and_notএখনও করার সহজ কোনও উপায় নেই। আমি আপনার শেষ চেক সম্পর্কেও অনিশ্চিত (যদি এটি বিবেচনা না করে তবে কেন এটি পরীক্ষা করুন?)। স্বাভাবিকভাবেই আপনার কাস্টম ম্যাচারের মধ্যে এটি মোড়ানো করতে সক্ষম হওয়া উচিত ।


7
যদি আপনি আশা একাধিক জিনিস চান না বদলে কেবল ব্যবহার.and change { @something }.by(0)
stevenspiel

4
আপনি সমস্ত প্রথম বন্ধনীর সাথে দ্বিতীয় উদাহরণ যুক্ত করতে পারেন? কোন পদ্ধতিগুলিতে শৃঙ্খলাবদ্ধ তা আমি বুঝতে অসুবিধা
সিরিল ডুচন-ডরিস

আমার উত্তর রুবি ২ এর পক্ষে কাজ করে .should_notএবং যার প্রয়োজনের সাথে কাজ করছে বলে মনে হয়
জ্যাক মরিস

39

আপনি যদি পরীক্ষা করতে চান যে একাধিক রেকর্ড পরিবর্তন করা হয়নি তবে আপনি কোনও ম্যাচার ব্যবহার করে উল্টাতে পারেন RSpec::Matchers.define_negated_matcher। সুতরাং, যোগ করুন

RSpec::Matchers.define_negated_matcher :not_change, :change

আপনার ফাইলের শীর্ষে (বা আপনার rails_helper.rb) এবং তারপরে আপনি ব্যবহার করে চেইন করতে পারেন and:

expect{described_class.reorder}.to not_change{ruleset.reload.position}.
    and not_change{simple_ruleset.reload.position}

2

আরএসপেক সংস্করণ ৩.১.০ সংস্করণে সম্পূর্ণ যৌগিক ম্যাচার সমর্থন change {}যুক্ত করা হয়েছে বলে গৃহীত উত্তরটি 100% সঠিক নয় । আপনি যদি আরএসপেক সংস্করণ ৩.০ সহ স্বীকৃত উত্তরে প্রদত্ত কোডটি চালানোর চেষ্টা করেন তবে আপনি একটি ত্রুটি পাবেন।

সাথে যৌগিক ম্যাচচারগুলি ব্যবহার করার জন্য change {}, দুটি উপায় রয়েছে;

  • প্রথমটি হ'ল, আপনার কমপক্ষে RSpec সংস্করণটি 3.1.0 থাকতে হবে
  • দ্বিতীয় এক, আপনি যোগ আছে def supports_block_expectations?; true; endমধ্যে RSpec::Matchers::BuiltIn::Compoundবর্গ, হয় বানর দ্বারা এটি প্যাচিং অথবা সরাসরি মণি স্থানীয় কপি সম্পাদনা। একটি গুরুত্বপূর্ণ দ্রষ্টব্য: এই উপায়টি প্রথমটির সাথে সম্পূর্ণ সমতুল্য নয়, expect {}ব্লকটি একাধিকবার এই ভাবে চলে!

যৌগ ম্যাথার কার্যকারিতার সম্পূর্ণ সমর্থন যুক্ত করার জন্য অনুরোধটি এখানে পাওয়া যাবে


2

ব্রুইসটসের উত্তরটি সেরা, তবে আপনি যদি আরএসপেক 2 ব্যবহার করেন (বা এর মতো আরও জটিল ম্যাথার রয়েছে .should_not) তবে এই পদ্ধতিটিও কাজ করে:

lambda {
  lambda {
    lambda {
      lambda {
        click_button 'Save'
        @user.reload
      }.should change {@user.name}.from('donald').to('gustav')
    }.should change {@user.updated_at}.by(4)
  }.should change {@user.great_field}.by_at_least(23)
}.should change {@user.encrypted_password}

4
আহ, সুন্দর ধারণা! আপনি সম্ভবত এটি পড়ার কিছুটা সহজ করার জন্য একটি মোড়ক তৈরি করতে পারেন!
ব্রুইসটসে
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.