espec icon indicating copy to clipboard operation
espec copied to clipboard

More readable syntax?

Open AlexMcConnell opened this issue 3 years ago • 7 comments

I don't understand why you chose to use this for your syntax:

expect actual |> to(eq expected)

rather than this:

expect(actual).to.eq.(expected)

The second seems far more readable to me. Like, obviously the pipe operator is a core part of Elixir to the point that everyone programming in Elixir is going to understand it, but simple English is still more readable, and that goes doubly so when the more English syntax ends up being almost exactly the same as Ruby and close to the same as JavaScript, and triply so when the basic point of this library is to make more readable tests than ExUnit, in a style more like RSpec.

AlexMcConnell avatar Aug 14 '20 03:08 AlexMcConnell

Hi! I'm just poking around here, looking into this project and was wondering the same thing. There is some insight here: https://github.com/antonmi/espec/issues/272

sodapopcan avatar Aug 17 '20 13:08 sodapopcan

That's disappointing that the even better rspec syntax got broken, but the syntax I mentioned above can be achieved by returning maps with anonymous functions attached to them.

AlexMcConnell avatar Aug 17 '20 15:08 AlexMcConnell

Hey @AlexMcConnell ! Sorry for the late response.

A couple of years ago ESpec had syntax like:

expect(actual).to eq(expected)

And, actually, that was an initial idea behind ESpec - mimic RSpec syntax. But, as @sodapopcan mentioned, I had to get rid of it because of changes in OTP 21.

Your idea looks interesting. Could you please implement a simple proof-of-concept? So we can discuss this in details.

antonmi avatar Nov 15 '20 15:11 antonmi

Hi,

I think we could easily implement this syntax by returning a map with an anonymous function as value to :to (as @AlexMcConnell says)

expect(actual).to.(eq(expected))

And we might get away with having it along the current one (so as not to break backwards compatibility). I vaguely remember discussing this with @antonmi (might be wrong) and deciding not to have it for fear they will change the dot special form behaviour again. They don't say anything about accessing map fields in the doc.

We could go ahead and implement the very thing

expect(actual).to.eq.(expected)

but we might not be able to maintain backwards compatibility. And I don't think we can have assertions with different arities. For example we could not have both of these

expect(1).to.be.(1)
expect(2).to.be.(:>, 1)

as anonymous functions cannot have multiple arities. But since there are not that many assertions with multiple arities we could change their syntax. For the example above it could be

expect(1).to.be.(1)
expect(2).to.be.({:>, 1})

However, this would be a big change to the end user and we should consider the risks and implications before implementing it. And maybe other syntax ideas.

andrei-mihaila avatar Nov 20 '20 16:11 andrei-mihaila

Sounds great @andrei-mihaila ! But I have to check this in detail. It's been a while since this functionality was built. :)

antonmi avatar Nov 20 '20 16:11 antonmi

Hey @antonmi Also sorry for the late response. 😁

Just in case it wasn't clear, this was all I did:

  def xpected(actual) do
    %{
      :to => %{
        :eq => fn (expected) -> expect actual |> to(eq expected) end
      }
    }
  end

I didn't explore it in any sort of depth though, as my knowledge of Elixir is pretty limited.

Also not really thrilled with the eq.( part of that, but what can you do? 😐

AlexMcConnell avatar Feb 28 '21 17:02 AlexMcConnell

For what it's worth, I actually like the current |> syntax. I think it's easy to reason about, and it matches what the rest of my Elixir code looks like.

LandonSchropp avatar Jul 12 '21 01:07 LandonSchropp