Имате ново предизвикателство със срок до сряда на обяд. Вече знаете къде да търсите примерния тест, въпроси по условието отправяйте тук.
Осмо предизвикателство
До колкото разбирам условието ето малко по-подробен пример какво трябва да прави Spy:
s = Spy.new 'Spy' s.length # => 3 s.swapcase # => 'sPY' s.length # => 3 s.calls # => [:length, :swapcase, :length] s.unknown_method # хвърля Spy::Error: Spy::Error s[1] # => 'p' s.calls # => [:length, :swapcase, :length, :[]] # s = Spy.new [1, 2, 3, 4] # s.map { |item| item + 1 } # => [2, 3, 4, 5]
само че имам няколко въпроса: 1. В масива върнат от
Spy#calls
има ли повтарящи се методи и съответно пази ли се реда на извикване на методите(както по-горе)? 2. Ако може примерен тест за въпросното изключение което трябва да се хвърли. 3. Ако подадения обект на Spy има вече метод calls какво се случва?Какъв е очакваният резултат от
s = Spy.new(Spy.new 'Call the pyro')
s.length
Както иs = Spy.new TestClass.new
s.method_missing :unknown_method
s.send :method_missing, :unknown_method
къдетоTestClass
дефинира или не дефинира публиченmethod_missing
@Иван:
- В масива
Spy#calls
се записва всяко извикване на метод, тъй че да, има повтарящи се методи и да, редът трябва да се пази. - Не може. :-) След 2 задачи и 7 предизвикателства се предполага, че можете да сами да си напишете някакви прости тестове с RSpec.
- Ако подаденият обект вече има метод
calls
, то няма да можем да го достъпим, понежеSpy#calls
ще го „скрие“. Тъпо или не, стори ни се по-уместно от това да измислим някакво „уникално“ име за метода, което да не застъпва евентуално съществуващи имена на методи.
@Никола:
s = Spy.new(Spy.new 'Call the pyro'); s.length # => 13
За другото виж този слайд, прочети малко тук и ако си отговориш сам на въпросите (и споделиш отговорите тук), ще получиш звездичка. :-)- В масива
Ще се повторя, за да може всеки, видял темата да го види със сигурност -> цък (Hint, hint.)
Ако предположим, че
Spy.new(TestClass.new)
трябва да се държи по същия начин, по койтоTestClass.new
що се отнася до викане наmethod_missing :unknown_method
, иTestClass
има публиченmethod_missing
ще се вика той с параметър:unknown_method
и*args = []
. Иначе ще се вика с параметър:method_missing
и*args = [:unknown_method]
(ако го няма предефиниран иprivate / protected
съответно ще викаmethod_missing
на суперкласа, който хвърляNoMethodError
). Ако се вика съсsend
ще е все едно е бил дефиниранpublic
. Въпросът ми беше действително ли трябва да се държи така?@Никола, не съм сигурен, че те разбирам какво точно питаш и имам смътното усещане, че търсиш под вола теле. Не ми стана ясно кога кой дефиниран къде
method_missing
с какви аргументи ще се вика... :) Предлагам ти да не дълбаеш толкова в тази посока. Все пак, ако държиш, може да ни пишеш с повече детайли и примерен код на имейла.Съжалявам, не съм спал достатъчно от известно време и съзнанието ми е на спагети. Накратко имаме клас
Test
, който дефинира публиченmethod_missing
, принтиращ"Some text"
. Ще се очаква лиSpy.new(Test.new).method_missing :ignore_me
да принтира също"Some text"
. Това беше един от случаите, за които питах, надявам се да е по-ясно.@Никола, накратко, няма да има такъв тест:
Spy.new(Test.new).method_missing ...
Перфектно, мерси. Бях приел прекалено буквално, че викането на който и да е метод върху обект и същия обект, обгърнат от
Spy
, трябва да дава еднакви резултати (с изключение наcalls
).А в
Spy#calls
записва ли сеunknown_method
? Все пак викаме и него, нищо, че хвърляSpy::Error
.@Мария, "Разликата е, че инстанциите на
Spy
имат методSpy#calls
, който връща масив от имената на всички извикани върху него методи, на които съответства метод в подадената инстанция."@Никола
Накратко имаме клас
Test
, който дефинира публиченmethod_missing
, принтиращ"Some text"
. Ще се очаква лиSpy.new(Test.new).method_missing :ignore_me
да принтира също"Some text"
.Не виждам причина да не го прави =]
@Никола, мерси. Усетих се, след като го написах.
@Георги, първоначално имах по-mindfuck тестове, това е опростена версия. Ще спра със спама и ще изчакам решенията да станат публични, после ако имам още въпроси ще говоря с колектива довечера, накрая ако остане нещо интересно ще го напиша.
При писане на тестове, къде трябва да се дефинира инстанция като
spied_thing
? Така както е в момента се повтаря твърде мого. Ако я дефинирам извънit "" do
не се вижда в техния скоуп, а ако я направя константа, не би следвало да я променям отString
наArray
. Как е най-добре да се структурира?describe "Spy" do STRING = 'Why so shy, Spy?' LIST = [-5, 5, 1, 0, 99] LAMBDA = lambda { |n| n } it "uses the correct methods" do spied_thing = Spy.new STRING spied_thing.length.should eq STRING.length end it "passes method argument" do spied_thing = Spy.new STRING spied_thing.count('y').should eq STRING.count('y') end it "uses subscription" do spied_thing = Spy.new STRING spied_thing[2].should eq STRING[2] end it "tracks calls" do spied_thing = Spy.new STRING spied_thing.length spied_thing.count('y') spied_thing[2] spied_thing.calls.should eq [:length, :count, :[]] end it "takes multiple arguments" do spied_thing = Spy.new LIST spied_thing.insert(2,"3").should eq LIST.insert(2,"3") end it "takes keyword argument" do spied_thing = Spy.new LIST spied_thing.join(separator="x").should eq LIST.join(separator="x") end it "takes block" do class Lazy def foo(arg, &block) block.call("!#{arg}!") end end LAZINESS = Lazy.new spied_thing = Spy.new LAZINESS spied_thing.foo(STRING, &LAMBDA).should eq LAZINESS.foo(STRING, &LAMBDA) end it "gives Spy::Error when method is missing" do spied_thing = Spy.new LIST expect { spied_thing.no_such_thing }.to raise_error Spy::Error end it "tracks only successful calls" do spied_thing = Spy.new LIST spied_thing.insert(2,"3") spied_thing.join(separator="x") begin spied_thing.no_such_thing rescue Spy::Error => e end spied_thing.calls.should eq [:insert, :join] end end
@Илиян, в
let
. Както каза и Мислав на лекцията във ФМИ, четенето на код помага много – може да прочетеш spec-овете на сайта на курса, например. Другият вариант е да прочетеш малко за RSpec, RTFM, както се казва :)Следния тест който съм си написал явно не минава при вас
expect { spied_string.sdfsunknown_method }.to raise_error(::Spy::Error)
@Валентин:
Следния тест който съм си написал явно не минава при вас
Както обича да казва един прочут български програмист, „елаборирай“ :-)
Трябва да сте влезли в системата, за да може да отговаряте на теми.