[TIP] running away from RSpec

Michael Foord fuzzyman at voidspace.org.uk
Sun Feb 13 05:33:33 PST 2011


On 12/02/2011 19:58, Gary Bernhardt wrote:
> On Sat, Feb 12, 2011 at 10:34 AM, Alfredo Deza<alfredodeza at gmail.com>  wrote:
>> This more of an open question I guess, but why there isn't a project in
>> Python that grabs the best features from RSpec
>> and implements them?
> As you suggest, it's impossible. Mote and PySpec are just fancy ways
> to name your tests: weak implementations of one tiny corner of RSpec.
> Mote uses horrible settrace magic; PySpec adds a bunch of
> domain-irrelevant noise. Neither even supports arbitrary context
> strings. RSpec is more terse, more expressive, removes the noise, and
> is an entirely reasonable thing to build in Ruby.
>
> That last point is important: it's not just that RSpec is possible in
> Ruby; it's actually idiomatic. I think that people don't realize just
> how easy it is to build its syntax. RSpec lets you say things like:
>
>    describe Integer do
>      it "adds numbers" do
>        (1 + 1).should == 2
>      end
>    end
>
> Looks complicated and magical, right? Nope. Here's an implementation
> of describe and it:
>
>    def describe(name)
>      puts name
>      yield
>    end
>
>    def it(name)
>      puts "- #{name}"
>      yield
>    end
>
> This will output the spec output that's become so familiar:
>
>    Integer
>    - adds numbers
>
> I spent a couple days of my life trying to get Python to do this when
> writing Mote and failed completely.
>
> The `2.should == 2` syntax is also simple, but here you can get close
> in Python. Expecter Gadget [1] lets you say `expect(1 + 1) == 2`. I
> still prefer RSpec because the statement reads as "subject,
> relationship, expected value".
>
> There's much more terseness to be had than this, though; the above is
> just the most trivial example. You can say things like:
>
>    describe Dog do
>      it { should have(4).feet }
>      it { should be_thirsty }
>    end
>

You could do the following in Python.

with describe(Dog) as it:
     it.should.have(4).feet
     it.should.be_thirsty

Where "it" collects tests which a runner executes when collection 
completes (or in response to __exit__). You could inject "it" using 
"with hacks" style magic too.

The Integer example *could* become:

with describe(int) as it:
     with it ("adds numbers"):
         assert 1 + 1 == 2

Not that I'm particularly fond of this or going to implement it myself...

Michael

> This is totally stock RSpec (and totally self-contained).
> `have(4).feet` asserts that `Dog.new.feet.size == 4`; `be_thirsty`
> asserts that `Dog.new.thirsty?` returns true.
>
> The most equivalent Python is:
>
>      class DogTest:
>          def setup(self):
>              self.dog = Dog()
>
>          def test_that_it_has_4_feet(self):
>              assert len(self.dog.feet) == 4
>
>          def test_that_it_is_thirsty(self):
>              assert self.dog.is_thirsty()
>
> (Inline the dog construction if you like; that just moves the problem around.)
>
> Some Python programmers will probably turn their noses up at that
> RSpec example because it's fancy (I know I would've). I think that's
> unreasonable. It's significantly more terse *and* more readable than
> the Python: a combination we don't often get.
>
> "More readable" does depend on learning RSpec, but that's easy because
> it's so intuitive. And I bet that you knew exactly what it meant upon
> reading it, even if its mapping onto the Dog class wasn't obvious.
>
> Getting back to the point: you just can't do this stuff in Python.
> I've spent a lot of time over the last couple years thinking about
> this and eventually I just gave up. It's one of the reasons that
> almost all of my programming is now done in Ruby.
>
> [1] https://github.com/garybernhardt/expecter
>


-- 
http://www.voidspace.org.uk/

May you do good and not evil
May you find forgiveness for yourself and forgive others
May you share freely, never taking more than you give.
-- the sqlite blessing http://www.sqlite.org/different.html




More information about the testing-in-python mailing list