What is this ?
A tool that generates an API documentation using RSpec and some DSL magic. If successful I might use it for my own project (neo4j.rb) This is an early experiment !
How ?
Instead of writing specs like this:
describe Account do
context "transfering money" do
it "deposits transfer amount to the other account" do
source = Account.new(50, :USD)
target = mock('target account')
target.should_receive(:deposit).with(Money.new(5, :USD))
source.transfer(5, :USD).to(target)
end
it "reduces its balance by the transfer amount" do
source = Account.new(50, :USD)
target = stub('target account')
source.transfer(5, :USD).to(target)
source.balance.should == Money.new(45, :USD)
end
end
end
Which generates the following output
$ spec ./spec/account_spec.rb --format nested
Account
transfering money
deposits transfer amount to the other account
reduces its balance by the transfer amount
2 examples, 0 failures
I (also) want to generate a detailed API documentation something like this from a RSpec Macro DSL:
Account
Public Static Methods
#new ()
Given
no arguments
Then
Return Account with 0 USD
has #balance == 0
has #currency == 'USD
#new (amount,currency)
Scenario account and currency has valid values
Given
arguments 50, USD
Then
Return an Account with given amount and currency
should == 50
should == "USD"
Public Instance Methods
#transfer (amount,currency)
Scenario transfer amount and currency have valid values
Given
arguments 5, USD
Then
should not change subject
Return A transfer of 5 USD from Account with 50 USD
should be a kind of TransferDSL
Finished in 0.00412 seconds
9 examples, 0 failures
TransferDSL
Public Static Methods
#new (source_account,amount,currency)
Given
arguments Account balance: 50 USD, 5, USD
Then
Return An TransferDSL instance with initialized source account, amount and currency
should == 50
Public Instance Methods
#to (target_account)
Given
arguments Account balance: 10 USD
Then it should add money on the target account
should add money to the target account
Finished in 0.00225 seconds
4 examples, 0 failures
The above is generated from the following RSpec file:
describe Account do
static_methods do
new do
Return("Account with 0 USD") do
# it_behaves_like "Account with 0 USD" can also be used
it("has #balance == 0") { subject.balance.should == 0 }
it("has #currency == 'USD") { subject.currency.should == 'USD' }
end
end
new(arg(:amount), arg(:currency)) do
Scenario 'account and currency has valid values' do
Given do
arg.amount = 50
arg.currency = 'USD'
end
Return "an Account with given amount and currency" do
it { subject.balance.should == 50 } #given.amount }
it { subject.currency.should == 'USD' } # given.currency }
end
end
end
end
instance_methods do
transfer(arg(:amount), arg(:currency)) do
# Description 'bla bla bla'
Scenario 'transfer amount and currency have valid values' do
subject { Account.new(50, 'USD') }
Given do
arg.amount = 5
arg.currency = 'USD'
end
Return "A transfer of 5 USD from Account with 50 USD" do
it { should be_kind_of(TransferDSL) }
end
Then do
it "should not change subject" do
given.subject.balance.should == subject.balance
end
end
end
end
end
end
describe TransferDSL do
static_methods do
new(arg(:source_account) do
Given do
arg.source_account = Account.new(50, 'USD')
end
Returns("A Transfer DSL with the given source account") do
it {subject.source_account.should == given.source_account}
end
end
instance_methods do
to(arg(:target_account, arg(:amount), arg(:currency)) do
Scenario 'source account has enough money' do
Given do
arg.target_account = Account.new(50, 'USD')
arg.amount = 5
arg.currency = 'USD'
subject{TransferDSL.new(Account.new(50, 'USD')}
end
# the following line describes the subject's source_account method
Then "it added money to the target account" do
it { subject.target_account.amount.should == given.arg.source_account.amount + given.arg.amount }
end
end
Scenario 'source account does NOT have enough money' do
Given do
arg.target_account = Account.new(50, 'USD')
arg.amount = 100
arg.currency = 'USD'
subject{TransferDSL.new(Account.new(10, 'USD')}
end
Throws(Error)
end
end
end
TODO: I will implement a new RSpec HTML formatter which will generate something similar to RDoc. I want to write specification in my rspec code instead of using RDoc.
Example
gem install rspec --prerelease (2.0.0.beta.19)
rspec -f d -c spec