[rspec-users] [rspec-devel] Specification Reuse to avoid Combinatorial Explosions

Brandon Keepers bkeepers at gmail.com
Tue Nov 21 15:51:56 EST 2006


One of the things I've often wished for is nested contexts.  This  
could help eliminate some duplication.

context "A Widthdrawal" do
   context "where an Account is in credit" do
     context "and the card is valid"
         context "and the dispenser contains cash" do

           specify "should debit the account" do
           end
           specify "should dispense cash" do
           end
           specify "should return the card" do
           end

         end

         context "and the dispenser does not contain cash" do

           specify "should inform the user" do
           end

         end
     end
   end
end

Brandon

On Nov 21, 2006, at 8:48 AM, David Chelimsky wrote:

> On 11/21/06, Brian Takita <brian.takita at gmail.com> wrote:
>> Hello,
>>
>> While reading Dan North's BDD tutorial, I tried to implement his  
>> ATM example
>> as spec stubs.
>> When I first implemented it creating a context for each of his  
>> scenarios, I
>> noticed that there is duplication and a combinatorial explosion of  
>> the
>> specs.
>>
>> I attached the full files to this email. For brevity, I will use  
>> scenario 1
>> in the body of this email. For the purpose of this exercise, one  
>> should
>> imagine that each specification is at least 5 lines.
>>
>> Here is how I implemented scenario 1:
>>
>> context %{A Withdrawal where an Account is in credit
>>         AND the card is valid
>>         AND the dispenser contains cash
>>          AND the customer requests cash} do
>>
>>   specify "should debit the account" do
>>   end
>>   specify "should dispense cash" do
>>   end
>>   specify "should return the card" do
>>   end
>> end
>>
>> That got me experimenting on reusing specifications by using a  
>> module to
>> create the specs. This is in
>> customer_withdraws_cash_spec.rb:
>>
>> module CustomerWithdrawsCashSpec
>>    def should_debit_the_account
>>     specify "should debit the account" do
>>     end
>>   end
>>   ...
>> end
>> ...
>> context %{A Withdrawal where an Account is in credit
>>          AND the card is valid
>>         AND the dispenser contains cash
>>         AND the customer requests cash} do
>>
>>    extend CustomerWithdrawsCashSpec
>>   should_debit_the_account
>>   should_dispense_cash
>>    should_return_the_card
>> end
>>
>> This is currently possible with rspec 0.7.2.
>> Whats interesting about putting all of the specifications into a  
>> module is
>> that you can reduce the context to a few lines.
>> This makes each context (scenario readable) making it more  
>> feasible to have
>> multiple contexts in a single file such as this group of scenarios
>> represented as contexts.
>>
>> I also played with a more DSL-like syntax for this, which does not  
>> work for
>> rspec 0.7.2. This is in
>> customer_withdraws_cash_alternative_spec.rb::
>>
>> CustomerWithdrawsCashSpec = context_module do
>>    specify "should debit the account" do
>>   end
>>    ...
>> end
>>
>>  context %{A Withdrawal where an Account is in credit
>>         AND the card is valid
>>         AND the dispenser contains cash
>>          AND the customer requests cash} do
>>
>>   extend CustomerWithdrawsCashSpec
>>   specify "should debit the account"
>>    specify "should dispense cash"
>>   specify "should return the card"
>>  end
>>
>> As well as:
>>
>> context %{A Withdrawal where an Account is in credit
>>          AND the card is valid
>>          AND the dispenser contains cash
>>          AND the customer requests cash} do
>>
>>    specify "should debit the account", CustomerWithdrawsCashSpec
>>    specify "should dispense cash", CustomerWithdrawsCashSpec
>>    specify "should return the card", CustomerWithdrawsCashSpec
>>  end
>>
>> Or just keep the underscore syntax:
>>
>> context %{A Withdrawal where an Account is in credit
>>          AND the card is valid
>>         AND the dispenser contains cash
>>         AND the customer requests cash} do
>>
>>    extend CustomerWithdrawsCashSpec
>>   should_debit_the_account
>>   should_dispense_cash
>>    should_return_the_card
>> end
>
> Interesting ideas. If we pursue this, I'd like to find an approach
> that aligns w/ RSpecs current lack of constructs like classes and
> modules. So rather than
>
> CustomerWithdrawsCashSpec = context_module do ...
>
> context "..." do
>   extend CustomerWithdrawsCashSpec
>
> I'd like something like
>
> context_module :customer_withdraws_cash do
>
> context "...", :customer_withdraws_cash do
>
> That's not exactly right, but you get the idea.
>
> Also - I think it would be really helpful for this discussion if you
> *would* post the full specs so we can see what this stuff really looks
> like in context.
>
> Thanks Brian.
>
> David
> _______________________________________________
> rspec-devel mailing list
> rspec-devel at rubyforge.org
> http://rubyforge.org/mailman/listinfo/rspec-devel



More information about the rspec-users mailing list