#1 ✓resolved
bahuvrihi

Specs are a mess

Reported by bahuvrihi | February 7th, 2009 @ 10:44 AM

Specs are currently a mess for a couple reasons.

  • We found out include has issues
  • The descriptions (it ...) are based on old test names and don't make any literary sense
  • The describe statements are also based on test class names and don't make sense.

I propose:


class SampleSpec < MiniTest::Spec
  include What::Needs::Including

  #
  # describe Sample#class_method
  #

  it "must/should do this" {}

  #
  # describe Sample.instance_method
  #

  it "must/should do that" {}

end

Naturally the description (it ...) statements should read well in the context of the comment-based describe statement. Also, when possible the order of the specs should match the declaration order.

I think the comment describes may be a good way of keeping the describe expression while still allowing includes.

Comments and changes to this ticket

  • bahuvrihi

    bahuvrihi February 7th, 2009 @ 10:53 AM

    • State changed from “new” to “open”
    • Assigned user set to “bahuvrihi”

    (from [d866af0862875abc014428dcd8c60832bd6da137]) cleanup of specs, removing spurious includes and reworking descriptions [#1 responsible:bahuvrihi state:open] http://github.com/bahuvrihi/ms-m...

  • bahuvrihi

    bahuvrihi February 7th, 2009 @ 11:36 AM

    A downside of this system is that it silently allows duplicate definition of methods:

    
    class SampleSpec < MiniTest::Spec
      it "must flunk" { flunk }
      it "must flunk" { pass }
    end
    

    This will pass and it will not notify that the first 'must flunk' is overridden. It would be better if we could wrap each method spec in a describe statement like:

    
    describe "Sample#class_method" do
      it "must/should do this" {}
    end
    
    describe "Sample.instance_method" do
      it "must/should do that" {}
    end
    

    But again, this comes with the include problem. Again, an alternative to using the traditional class definition and include is to use describe and full constant names.

    
    describe "SampleSpec" do
      it "uses a full constant name" do 
        What::Needs::Including
      end
    end
    
  • bahuvrihi

    bahuvrihi February 7th, 2009 @ 12:07 PM

    I've submitted a ticket to MiniTest to raise a warning when methods get duplicated, so hopefully this won't be an issue in the future.

  • jtprince

    jtprince February 10th, 2009 @ 01:26 PM

    The solutions proposed are sound. Still, I think as described they reflect more of a unit test style (which is a good thing) but are not as compatible with more of a behavior/spec style.

    I'm thinking the above style testing should be included in some sort of "unit" spec. (Of course, since specs are supersets of tests, one could always just write unit tests as before...)

    
    class SampleUnitTest < MiniTest::Spec
      include What::Needs::Including
    
      #
      # describe Sample#class_method
      #
    
      it "must/should do this" {}
    
      #
      # describe Sample.instance_method
      #
    
      it "must/should do that" {}
    end
    

    In general, I prefer a more direct statement in 'it' methods:

    
      # I like this:
      it 'does this' {}
      # over this:  
      it 'must do this' {}
      # because the first is more DRY (the 'must' is implied in a spec).
    

    This kind of a unit test/spec is handy for development and to ensure proper behavior from each method.

    A spec is tied much less closely to the implementation and more to one particular context and expected behaviors:

    
    class SampleWithSuperSampleFile < MiniTest::Spec
    
      #
      # describe Sample given a SuperSample file
      #
      
      before do
        @obj = SuperSample.read(file)
      end
    
      it 'tells how big the file is' do
        obj.size.must_equal 7
      end
    
      it 'spits out xml for each section' do
        obj.each_section do |section|
          section.to_xml.must_equal precached_xml
        end
      end
    end
    

    I think it is natural to order these by most critical behavior. The implementation is of secondary importance to what the thing actually does in a certain context. In any case, whatever implementation you choose to accomplish the behavior, the spec is self-documenting. One glance inside the spec tells a person how to do the behavior. With this style, it makes much less sense tie a test method (i.e., the 'it') to a single method. Sometimes, to accomplish the required behavior will take a few different method calls... upper level behavior may span different classes entirely.

  • bahuvrihi

    bahuvrihi February 11th, 2009 @ 10:04 AM

    Really good points. Maybe it's a matter of applying a spec/test style to the right problem? I can see how high level behavior is nicely supported by specs that don't say much of anything of how a thing is implemented, and for low-level things (where you're wondering if this single method actually works) an orderly test style might suit.

    
      # I like this:
      it 'does this' {}
    
      # over this:  
      it 'must do this' {}
      # because the first is more DRY (the 'must' is implied in a spec).
    

    I see what you're talking about here too. English teachers would applaud the active tense... the 'must/should' sounds to me more like a test-style spec while the 'does' is more descriptive of behavior.

  • bahuvrihi

    bahuvrihi February 25th, 2009 @ 11:32 PM

    • State changed from “open” to “resolved”

Please Sign in or create a free account to add a new ticket.

With your very own profile, you can contribute to projects, track your activity, watch tickets, receive and update tickets through your email and much more.

New-ticket Create new ticket

Create your profile

Help contribute to this project by taking a few moments to create your personal profile. Create your profile ยป

Mass Spectrometry Proteomics in Ruby

People watching this ticket

Tags

Referenced by

Pages