and... scalability problems
Tanks to Amazon EC2 :)
Podcaster
Ruby NoName Podcast
only in russian... sorry.
3rd place in the rpod.ru TOP-20
(biggest russian podcast aggregator)
But, it all doesn't
matter...
I'm a BDD Freak!
$ rake stats (on my last 3 projects)
Code to Test Ratio: 1:1.9
Code to Test Ratio: 1:2.9
Code to Test Ratio: 1:3.5
Why!?!
• so many fucking code in u specs!!!
• so many time to write specs!!!
• My code is working without them just fine.
Coz....
• I don't believe my code is working, I need proof.
• I don't believe my code didn't break anything.
• I will forget what my code does in 2 days.
• I want to sleep well at night. At least when I sleep
alone.
BDD == TDD ?
BDD != TDD
Don’t write tests.
Explain what your code
should do!
describe 'BDD "why and how?" talk' do
before(:each) do
@presentation = Presentation.new(:subject => :bdd)
end
it "should be less then 15 minutes" do
@presentation.length.should_be < 15.minutes
end
it "should include RSpec topic" do
@presentation.topics.should include("RSpec")
end
it "should include Cucumber topic" do
@presentation.topics.should include("Cucumber")
end
end
tell a story
Feature: Podcasts list
In order to be tuned
As a podcast listener
I want to see the podcasts list
Scenario: Podcasts list
Given I have podcast titled "Pilot Release"
And I have podcast titled "Second One"
And I have podcast titled "Third as Expected"
When I go to the podcasts list
Then I should see "Pilot Release"
And I should see "Second One"
And I should see "Third as Expected"
Scenario: Podcasts list null screen
Given I have no podcasts
When I go to the podcasts list
Then I should see nice podcasts list null screen
Scenario: Podcasts should be numbered
Given I have a couple of podcasts
When I go to the podcasts list
Then I should see podcasts are numbered
in any language
תכונה: חיבור Функционал: Сложение чисел
כדי למנוע טעויות טפשיות Чтобы не складывать в уме
בתור בור מתמטי Все, у кого с этим туго
אני רוצה שיגידו לי את הסכום של שני מספרים Хотят автоматическое сложение целых чисел
תבנית תרחיש: חבר שני מספרים Сценарий: Сложение двух целых чисел
בהינתן שהזנתי >קלט_1< למחשבון Допустим я ввожу число 50
וגם שהזנתי >קלט_2< למחשבון И затем ввожу число 70
< כאשר אני לוחץ על >כפתור Если я нажимаю "+"
< אז התוצאה על המסך צריכה להיות >פלט То результатом должно быть число 120
ﺧﺎﺻﻴﺔ: ﺍﳉﻤﻊ
Feature: Addition
ﻣﻦ ﺍﺟﻞ ﲡﻨﺐ ﺍﻷﺧﻄﺎﺀ ﺍﻟﺴﺨﻴﻔﺔ
In order to avoid silly mistakes
ﻛﺸﺨﺺ ﻏﺒﻲ ﻓﻲ ﺍﻟﺮﻳﺎﺿﻴﺎﺕ
As a math idiot
ﺍﺭﻳﺪ ﻣﻌﺮﻓﺔ ﻧﺎﰋ ﺟﻤﻊ ﻋﺪﺩﻳﻦ
I want to be told the sum of two numbers
ﺳﻴﻨﺎﺭﻳﻮ ﻣﺨﻄﻂ: ﺟﻤﻊ ﻋﺪﺩﻳﻦ
Scenario Outline: Add two numbers
< ﻓﻲ ﺍﻵﻟﺔ ﺍﳊﺎﺳﺒﺔinput_1> ﺑﻔﺮﺽ ﻛﺘﺎﺑﺔ
Given I have entered <input_1> into the calculator
< ﻓﻲ ﺍﻵﻟﺔ ﺍﳊﺎﺳﺒﺔinput_2> ﻭ ﻛﺘﺎﺑﺔ
And I have entered <input_2> into the calculator
<button> ﻣﺘﻰ ﻳﺘﻢ ﺍﻟﻀﻐﻂ ﻋﻠﻰ
When I press <button>
< ﻋﻠﻰ ﺍﻟﺸﺎﺷﺔoutput> ﺍﺫﺍً ﻳﻈﻬﺮ
Then the result should be <output> on the screen
now is magic time!
$ rake features
ok, ok no magic
here.
U need to do some work to get this
work.
Just old good regexp
Given I have podcast titled "Pilot Release" Given /^I have podcast titled "([^"]*)"$/ do |title|
Factory(:podcast, :title => title)
end
When I go to the podcasts list When /^I go to (.+)$/ do |page_name|
visit path_to(page_name)
end
module NavigationHelpers
def path_to(page_name)
case page_name
when /the homepage/
'/'
when /the podcasts list/
podcasts_path
else
raise "Can't find mapping from "#{page_name}" to a path.n" +
"Now, go and add a mapping in #{__FILE__}"
end
end
end
and RSpec assertions
Then I should see "Pilot Release" Then /^I should see "([^"]*)"$/ do |text|
response.should contain(text)
end
Then I should see nice Then /^I should see nice podcasts list null screen$/ do
podcasts list null screen response.should have_tag('.null_content')
end
Work not only with rails
• Pure Ruby
• Merb
• Sinatra
• more....
not only for pure html
• AJAX
• FLEX
• more....
Learn more:
• http://cukes.info/
• http://onrails.org/articles/category/flex
• google it!
Describe your code with RSpec
and a little bit shoulda
Cucumber - user’s point of view
RSpec - developer’s point of view
Models
describe Podcast do
describe "performing operations requiring its number to be updated" do
before do
@last_podcast_number = 5
Podcast.delete_all
@last_podcast_number.times do |idx|
Factory(:podcast, :title => "Podcast Numbered #{idx + 1}")
end
end
it "should automatically set number" do
podcast = Factory(:podcast)
podcast.number.should == @last_podcast_number + 1
end
it "should set correct number if any other podcast has been removed before" do
broken_podcast = Factory(:podcast)
broken_podcast.destroy
podcast = Factory(:podcast)
podcast.number.should == @last_podcast_number + 1
end
it "should correct podcast numbers on delete" do
podcast = Factory(:podcast)
lambda {
Podcast.find(:first, :offset => @last_podcast_number/2).destroy # remove in around a middle
podcast.reload
}.should change(podcast, :number).by(-1)
end
end
end
Shoulda matchers.
Why?
— shorter
describe Podcast do
VS describe Podcast do
it { should validate_presence_of(:title) } describe "validations" do
it { should validate_presence_of(:asset_link) } it "should be invalid without title" do
end podcast = Factory.build(:podcast, :title => nil)
podcast.should_not be_valid
podcast.should have(1).error_on(:title)
end
it "should be invalid without asset link" do
podcast = Factory.build(:podcast, :asset_link => nil)
podcast.should_not be_valid
podcast.should have(1).error_on(:asset_link)
end
end
end
Controllers
describe PodcastsController do
describe "handling GET /podcasts" do
before do
@podcast = mock_model(Podcast)
Podcast.stub!(:find).and_return([@podcast])
end
it "should be successful" do
get :index
response.should be_success
end
it "should render index template" do
get :index
response.should render_template('index')
end
it "should find all podcasts" do
Podcast.should_receive(:find).with(:all).and_return([@podcast])
get :index
end
it "should assign the found podcasts for the view" do
get :index
assigns[:podcasts].should == [@podcast]
end
end
end
Mocks vs Stubs
describe PodcastsController do
describe "handling GET /podcasts" do
before do
@podcast = mock_model(Podcast)
Stub
Podcast.stub!(:find).and_return([@podcast])
end
it "should be successful" do
get :index
response.should be_success
end
it "should render index template" do
Mock
get :index
response.should render_template('index')
end
it "should find all podcasts" do
Podcast.should_receive(:find).with(:all).and_return([@podcast])
get :index
end
it "should assign the found podcasts for the view" do
get :index
assigns[:podcasts].should == [@podcast]
end
end
end
Views
The question is...
Views
The question is...
Should I test views?
to test or not to test?
Only important things
Some tips
• Don’t forget about MVC
• don’t DRY too hard
• Try writing specs first
• Test behavior, not implementation
Life
AutoSpec
Should work on windows (not promise anything)
0 comments
Post a comment