जवाबों:
दी राधा रास्ता =>
let(:dummy_class) { Class.new { include ModuleToBeTested } }
वैकल्पिक रूप से आप अपने मॉड्यूल के साथ परीक्षण वर्ग का विस्तार कर सकते हैं:
let(:dummy_class) { Class.new { extend ModuleToBeTested } }
'लेट' का उपयोग करने से पहले डमी क्लास को परिभाषित करने के लिए एक इंस्टेंस वेरिएबल का उपयोग करने से बेहतर है: (प्रत्येक)
let(:dummy_class) { Class.new { include ModuleToBeTested } }
let(:class_instance) { (Class.new { include Super::Duper::Module }).new }
इस तरह से मुझे उदाहरण चर मिलता है जो किसी भी तरह से परीक्षण के लिए सबसे अधिक उपयोग किया जाता है।
include
मेरे लिए काम नहीं करता है लेकिन extend
करता हैlet(:dummy_class) { Class.new { extend ModuleToBeTested } }
subject(:instance) { Class.new.include(described_class).new }
माइक ने क्या कहा। यहाँ एक तुच्छ उदाहरण दिया गया है:
मॉड्यूल कोड ...
module Say
def hello
"hello"
end
end
कल्पना का टुकड़ा ...
class DummyClass
end
before(:each) do
@dummy_class = DummyClass.new
@dummy_class.extend(Say)
end
it "get hello string" do
expect(@dummy_class.hello).to eq "hello"
end
include Say
कॉल करने के बजाय डमीक्लास घोषणा के अंदर नहीं किया extend
?
extend
कक्षा के उदाहरण में आईएनजी है, अर्थात बाद new
में बुलाया गया है। यदि आप ऐसा new
कर रहे हैं तो पहले बुलाया जाता है तो आप सही हैं आप उपयोग करेंगेinclude
DummyClass
स्थिरांक को क्यों परिभाषित करेंगे ? सिर्फ क्यों नहीं @dummy_class = Class.new
? अब आपका परीक्षण वातावरण को एक अनावश्यक वर्ग परिभाषा के साथ प्रदूषित कर रहा है। यह डमीक्लास आपके प्रत्येक चश्मे के लिए परिभाषित है और अगले चश्मे में जहां आप एक ही दृष्टिकोण का उपयोग करने का निर्णय लेते हैं और डमीक्लास की परिभाषा को फिर से खोलते हैं, इसमें पहले से ही कुछ हो सकता है (हालांकि इस तुच्छ उदाहरण में परिभाषा वास्तविक जीवन में सख्ती से खाली है। ऐसे मामलों का उपयोग करें जिनकी संभावना है कि कुछ बिंदु पर कुछ जोड़ा जाता है और फिर यह दृष्टिकोण खतरनाक हो जाता है।)
उन मॉड्यूलों के लिए जिनका अलगाव में परीक्षण किया जा सकता है या कक्षा का मजाक उड़ाया जा सकता है, मुझे इसकी कुछ पंक्तियाँ पसंद हैं:
मापांक:
module MyModule
def hallo
"hallo"
end
end
कल्पना:
describe MyModule do
include MyModule
it { hallo.should == "hallo" }
end
यह नेस्टेड उदाहरण समूहों को अपहृत करने के लिए गलत लग सकता है, लेकिन मुझे मरोड़ पसंद है। कोई विचार?
let
@metakungfu द्वारा बताई गई विधि का उपयोग करना बेहतर है।
मुझे rspec होमपेज में एक बेहतर समाधान मिला। जाहिर तौर पर यह साझा उदाहरण समूहों का समर्थन करता है। से https://www.relishapp.com/rspec/rspec-core/v/2-13/docs/example-groups/shared-examples !
साझा किए गए उदाहरण समूह
आप साझा उदाहरण समूह बना सकते हैं और उन समूहों को अन्य समूहों में शामिल कर सकते हैं।
मान लें कि आपके पास कुछ व्यवहार है जो आपके उत्पाद के सभी संस्करणों पर लागू होता है, दोनों बड़े और छोटे।
सबसे पहले, "साझा" व्यवहार बाहर कारक:
shared_examples_for "all editions" do
it "should behave like all editions" do
end
end
फिर जब आपको बड़े और छोटे संस्करणों के लिए व्यवहार को परिभाषित करने की आवश्यकता होती है, तो it_should_behave_like () पद्धति का उपयोग करके साझा व्यवहार को देखें।
describe "SmallEdition" do
it_should_behave_like "all editions"
it "should also behave like a small edition" do
end
end
मेरे सिर के ऊपर से, क्या आप अपनी टेस्ट स्क्रिप्ट में एक डमी क्लास बना सकते हैं और उसमें मॉड्यूल शामिल कर सकते हैं? फिर परीक्षण करें कि डमी वर्ग का व्यवहार आपके द्वारा अपेक्षित तरीके से किया गया है।
संपादित करें: यदि, जैसा कि टिप्पणियों में बताया गया है, मॉड्यूल को उम्मीद है कि कुछ व्यवहार उस कक्षा में मौजूद होंगे जिसमें इसे मिलाया जाता है, तो मैं उन व्यवहारों की डमी को लागू करने का प्रयास करूंगा। बस अपने कर्तव्यों को निभाने के लिए मॉड्यूल को खुश करने के लिए पर्याप्त है।
उस ने कहा, मैं अपने डिज़ाइन के बारे में थोड़ा घबराया हुआ हूं जब एक मॉड्यूल अपने मेजबान से पूरी उम्मीद करता है (क्या हम "मेजबान" कहते हैं?) वर्ग - अगर मैं पहले से ही एक आधार वर्ग से विरासत में नहीं मिला या इंजेक्शन नहीं लगा सकता विरासत पेड़ में नई कार्यक्षमता तो मुझे लगता है कि मैं ऐसी किसी भी अपेक्षा को कम करने की कोशिश करूंगा जो एक मॉड्यूल हो सकता है। मेरी चिंता यह है कि मेरा डिजाइन अप्रिय अनैच्छिकता के कुछ क्षेत्रों को विकसित करना शुरू कर देगा।
स्वीकृत उत्तर वह सही उत्तर है जो मुझे लगता है, हालाँकि मैं एक उदाहरण जोड़ना चाहता था कि rpsecs shared_examples_for
और it_behaves_like
विधियों का उपयोग कैसे करें । मैं कोड स्निपेट में कुछ तरकीबों का उल्लेख करता हूं, लेकिन अधिक जानकारी के लिए यह relishapp-rspec-guide देखें ।
इसके साथ आप अपने मॉड्यूल को किसी भी वर्ग में परीक्षण कर सकते हैं जिसमें यह शामिल है। तो आप वास्तव में परीक्षण कर रहे हैं कि आप अपने आवेदन में क्या उपयोग करते हैं।
आइए एक उदाहरण देखें:
# Lets assume a Movable module
module Movable
def self.movable_class?
true
end
def has_feets?
true
end
end
# Include Movable into Person and Animal
class Person < ActiveRecord::Base
include Movable
end
class Animal < ActiveRecord::Base
include Movable
end
अब हमारे मॉड्यूल के लिए कल्पना बनाएं: movable_spec.rb
shared_examples_for Movable do
context 'with an instance' do
before(:each) do
# described_class points on the class, if you need an instance of it:
@obj = described_class.new
# or you can use a parameter see below Animal test
@obj = obj if obj.present?
end
it 'should have feets' do
@obj.has_feets?.should be_true
end
end
context 'class methods' do
it 'should be a movable class' do
described_class.movable_class?.should be_true
end
end
end
# Now list every model in your app to test them properly
describe Person do
it_behaves_like Movable
end
describe Animal do
it_behaves_like Movable do
let(:obj) { Animal.new({ :name => 'capybara' }) }
end
end
व्हाट अबाउट:
describe MyModule do
subject { Object.new.extend(MyModule) }
it "does stuff" do
expect(subject.does_stuff?).to be_true
end
end
मेरा सुझाव है कि बड़े और ज्यादा इस्तेमाल किए जाने वाले मॉड्यूल के लिए "साझा उदाहरण समूहों" के लिए विकल्प चुनना चाहिए जैसा कि यहाँ @Andrius द्वारा सुझाया गया है । साधारण सामान जिसके लिए आप कई फाइलें आदि की परेशानी से नहीं गुजरना चाहते हैं, यहां बताया गया है कि अपने डमी सामान की दृश्यता पर अधिकतम नियंत्रण कैसे सुनिश्चित करें (rspec 2.14.6 के साथ परीक्षण किया गया है, बस कॉपी करें और कोड को एक में पेस्ट करें युक्ति फ़ाइल और इसे चलाएं):
module YourCoolModule
def your_cool_module_method
end
end
describe YourCoolModule do
context "cntxt1" do
let(:dummy_class) do
Class.new do
include YourCoolModule
#Say, how your module works might depend on the return value of to_s for
#the extending instances and you want to test this. You could of course
#just mock/stub, but since you so conveniently have the class def here
#you might be tempted to use it?
def to_s
"dummy"
end
#In case your module would happen to depend on the class having a name
#you can simulate that behaviour easily.
def self.name
"DummyClass"
end
end
end
context "instances" do
subject { dummy_class.new }
it { subject.should be_an_instance_of(dummy_class) }
it { should respond_to(:your_cool_module_method)}
it { should be_a(YourCoolModule) }
its (:to_s) { should eq("dummy") }
end
context "classes" do
subject { dummy_class }
it { should be_an_instance_of(Class) }
it { defined?(DummyClass).should be_nil }
its (:name) { should eq("DummyClass") }
end
end
context "cntxt2" do
it "should not be possible to access let methods from anohter context" do
defined?(dummy_class).should be_nil
end
end
it "should not be possible to access let methods from a child context" do
defined?(dummy_class).should be_nil
end
end
#You could also try to benefit from implicit subject using the descbie
#method in conjunction with local variables. You may want to scope your local
#variables. You can't use context here, because that can only be done inside
#a describe block, however you can use Porc.new and call it immediately or a
#describe blocks inside a describe block.
#Proc.new do
describe "YourCoolModule" do #But you mustn't refer to the module by the
#constant itself, because if you do, it seems you can't reset what your
#describing in inner scopes, so don't forget the quotes.
dummy_class = Class.new { include YourCoolModule }
#Now we can benefit from the implicit subject (being an instance of the
#class whenever we are describing a class) and just..
describe dummy_class do
it { should respond_to(:your_cool_module_method) }
it { should_not be_an_instance_of(Class) }
it { should be_an_instance_of(dummy_class) }
it { should be_a(YourCoolModule) }
end
describe Object do
it { should_not respond_to(:your_cool_module_method) }
it { should_not be_an_instance_of(Class) }
it { should_not be_an_instance_of(dummy_class) }
it { should be_an_instance_of(Object) }
it { should_not be_a(YourCoolModule) }
end
#end.call
end
#In this simple case there's necessarily no need for a variable at all..
describe Class.new { include YourCoolModule } do
it { should respond_to(:your_cool_module_method) }
it { should_not be_a(Class) }
it { should be_a(YourCoolModule) }
end
describe "dummy_class not defined" do
it { defined?(dummy_class).should be_nil }
end
subject { dummy_class.new }
काम कर रहा है। subject { dummy_class }
मेरे साथ काम नहीं कर रहा है।
मेरे हाल के काम, यथासंभव कम हार्ड-वायरिंग का उपयोग करना
require 'spec_helper'
describe Module::UnderTest do
subject {Object.new.extend(described_class)}
context '.module_method' do
it {is_expected.to respond_to(:module_method)}
# etc etc
end
end
मैं चाहता हूँ
subject {Class.new{include described_class}.new}
काम किया है, लेकिन यह रूबी एमआरआई 2.2.3 और RSpec :: Core 3.3.0 के अनुसार नहीं है
Failure/Error: subject {Class.new{include described_class}.new}
NameError:
undefined local variable or method `described_class' for #<Class:0x000000063a6708>
स्पष्ट रूप से वर्णित_क्लॉस उस दायरे में दिखाई नहीं देता है।
अपने मॉड्यूल का परीक्षण करने के लिए, उपयोग करें:
describe MyCoolModule do
subject(:my_instance) { Class.new.extend(described_class) }
# examples
end
कई चीजों का उपयोग करें जिन्हें आप कई चश्मे में इस्तेमाल करते हैं, आप एक साझा संदर्भ का उपयोग कर सकते हैं:
RSpec.shared_context 'some shared context' do
let(:reused_thing) { create :the_thing }
let(:reused_other_thing) { create :the_thing }
shared_examples_for 'the stuff' do
it { ... }
it { ... }
end
end
require 'some_shared_context'
describe MyCoolClass do
include_context 'some shared context'
it_behaves_like 'the stuff'
it_behaves_like 'the stuff' do
let(:reused_thing) { create :overrides_the_thing_in_shared_context }
end
end
संसाधन:
आप सहायक प्रकार का भी उपयोग कर सकते हैं
# api_helper.rb
module Api
def my_meth
10
end
end
# spec/api_spec.rb
require "api_helper"
RSpec.describe Api, :type => :helper do
describe "#my_meth" do
it { expect( helper.my_meth ).to eq 10 }
end
end
यहाँ प्रलेखन है: https://www.relishapp.com/rspec/rspec-rails/v/3-3/docs/helper-specs/helper-spec
आपको बस अपने मॉड्यूल को अपनी कल्पना फ़ाइल
mudule Test
module MyModule
def test
'test'
end
end
end
में अपनी कल्पना फ़ाइल में शामिल करना होगा
RSpec.describe Test::MyModule do
include Test::MyModule #you can call directly the method *test*
it 'returns test' do
expect(test).to eql('test')
end
end
मॉड्यूल विधि के परीक्षण के लिए एक संभव समाधान जो वर्ग में स्वतंत्र हैं जो उन्हें शामिल करेंगे
module moduleToTest
def method_to_test
'value'
end
end
और इसके लिए कल्पना करें
describe moduleToTest do
let(:dummy_class) { Class.new { include moduleToTest } }
let(:subject) { dummy_class.new }
describe '#method_to_test' do
it 'returns value' do
expect(subject.method_to_test).to eq('value')
end
end
end
और यदि आप उन्हें परीक्षण करना चाहते हैं, तो साझा किया गया है
subject(:module_to_test_instance) { Class.new.include(described_class) }
। अन्यथा मैं वास्तव में आपके उत्तर में कुछ भी गलत नहीं देखता।
यह एक आवर्तक पैटर्न है क्योंकि आपको एक से अधिक मॉड्यूल का परीक्षण करने की आवश्यकता होती है। उस कारण से, यह इसके लिए एक सहायक बनाने के लिए वांछनीय से अधिक है।
मुझे यह पोस्ट मिली जो बताती है कि यह कैसे करना है लेकिन मैं यहाँ पर नकल कर रहा हूँ क्योंकि साइट को किसी बिंदु पर नीचे ले जाया जा सकता है।
यह ऑब्जेक्ट इंस्टेंसेस से बचने के लिए है इंस्टेंस विधि को लागू न करें:allow
तरीकों पर प्रयास करते समय आपको जो भी त्रुटि मिलती हैdummy
क्लास में ।
में spec/support/helpers/dummy_class_helpers.rb
module DummyClassHelpers
def dummy_class(name, &block)
let(name.to_s.underscore) do
klass = Class.new(&block)
self.class.const_set name.to_s.classify, klass
end
end
end
में spec/spec_helper.rb
# skip this if you want to manually require
Dir[File.expand_path("../support/**/*.rb", __FILE__)].each {|f| require f}
RSpec.configure do |config|
config.extend DummyClassHelpers
end
आपके चश्मे में:
require 'spec_helper'
RSpec.shared_examples "JsonSerializerConcern" do
dummy_class(:dummy)
dummy_class(:dummy_serializer) do
def self.represent(object)
end
end
describe "#serialize_collection" do
it "wraps a record in a serializer" do
expect(dummy_serializer).to receive(:represent).with(an_instance_of(dummy)).exactly(3).times
subject.serialize_collection [dummy.new, dummy.new, dummy.new]
end
end
end