icy-arctic-fox / spectator

Feature-rich testing framework for Crystal inspired by RSpec.
https://gitlab.com/arctic-fox/spectator
MIT License
103 stars 5 forks source link

Allow defining doubles without a block #30

Closed postmodern closed 3 years ago

postmodern commented 3 years ago

When porting RSpec specs to Spectator, often times the doubles lack any body or stubs.

let(:foo) { double(:foo) }

I think it would be useful to support defining doubles without a block:

double :foo
double :bar

let(args) { {double(:foo), double(:bar)} }
icy-arctic-fox commented 3 years ago

Is the goal of doing this to create an anonymous double?

As it is (I'm not sure this is documented), using a String as the double's name will make an anonymous double - without needing a block. The string value is used to label the double.

let(foo) { double("foo") }

it "does a thing" do
  expect(foo).to_not be_nil
end

The string argument is optional, and defaults to "Anonymous". Anonymous doubles can be used like this:

Spectator.describe "GitHub Issue #30" do
  let(dbl) { double }

  it "does a thing" do
    expect(dbl).to_not be_nil
  end
end

I think the original reasoning for this implementation is because Spectator couldn't distinguish the difference between a double definition and it's instantiation, since they both use the double keyword. This should be doable now. Let me know what you think.

postmodern commented 3 years ago

The goal is to create an random Object with a descriptive name/ID, but no other attributes just to pass to a method and track that it was correctly passed to another method or returned.

      let(:stdin) { StringIO.new }
      let(:args) { [double(:arg1), double(:arg2)] }
      let(:ret)  { double(:return_value) }

      subject { command_class.new(stdin: stdin) }

      it "must pass all arguments ot stdin.#{method}" do
        expect(stdin).to receive(method).with(*args).and_return(ret)

        expect(subject.send(method,*args)).to be(ret)
      end

I probably could use Strings or Object.new.

icy-arctic-fox commented 3 years ago

An anonymous double should suit your needs. I'll see about creating a double with a symbol for a name with no block - allowing this syntax:

let(foo) { double(:foo) }

it "works" do
  expect(foo).to_not be_nil
end
icy-arctic-fox commented 3 years ago

Should be possible in v0.9.39 - Can you try it and verify?

postmodern commented 3 years ago

Seems to work. Although, now I'm getting an unrelated compilation error about IO::ARGF#gets being passed the tuple of doubles; which is odd because I am not using ARGF anywhere.

icy-arctic-fox commented 3 years ago

Sounds like something "escaped." Can you send me the full error trace? I've seen issues like this before and I'd rather squash them before they cause even more bizarre and hard to track down issues.

postmodern commented 3 years ago

https://gist.github.com/postmodern/2b11af228de95a92dd1b0389119e0a06

icy-arctic-fox commented 3 years ago

Fixed something that might resolve this in v0.9.40. Can you check again?

If not, I suspect this might happen because ARGF is based on IO, and the IO#gets method is being operated on.