Screencast: Etwas zu Open-Source beitragen

Open-Source Projekte leben vom Beitrag von Freiwilligen. Github vereinfacht die Möglichkeit einen Teil, seien es auch nur kleine Verbesserungen, zur Verfügung zu stellen. An dem Beispiel von VCR zeigt Ryan diese Woche wie es funktioniert.

 

Downloads in verschiedenen Formaten:

mp4
m4v
webm
ogg

 

Resourcen:

bash

[bash]
git clone git@github.com:ryanb/vcr.git
cd vcr
git branch -r
bundle install
bundle exec rake
git submodule init
git submodule update
git status
git checkout .
git checkout -b readme-contributing-link
git diff
git commit -a -m "adding contributing link to readme"
git push origin readme-contributing-link
[/bash]

Gemfile

[ruby]
gem ‚rb-fsevent‘, ‚0.9.0.pre4‘
[/ruby]

Screencast: Tests mit Spork beschleunigen

Ab einer bestimmten Größe können die Testläufe die Entwicklung „verlangsamen“. Spork ist kann in diesem Fall Abhilfe schaffen, indem es die Ladezeiten verbessert. In Verbindung mit Guard bekommt man so schneller Rückmeldung über den aktuellen Stand. Ryan zeigt in diesem Screencast wie Spork eingesetzt werden kann.

 

Downloads in verschiedenen Formaten:

mp4
m4v
webm
ogg

 

Resourcen:

bash

[bash]
rspec .
time rspec .
bundle
spork –bootstrap
spork
rspec . –drb
guard init spork
[/bash]

Gemfile

[ruby]
group :test do
gem "spork", "> 0.9.0.rc"
gem "guard-spork"
end
[/ruby]

Guardfile

[ruby]
guard ’spork‘, :cucumber_env => { ‚RAILS_ENV‘ => ‚test‘ }, :rspec_env => { ‚RAILS_ENV‘ => ‚test‘ } do
watch(‚config/application.rb‘)
watch(‚config/environment.rb‘)
watch(%r{^config/environments/.+.rb$})
watch(%r{^config/initializers/.+.rb$})
watch(’spec/spec_helper.rb‘)
watch(%r{^spec/support/.+.rb$})
end

guard ‚rspec‘, :version => 2, :cli => "–drb", :all_on_start => false, :all_after_pass => false do
# …
end
[/ruby]

spec/spec_helper.rb

[ruby]
require ‚rubygems‘
require ’spork‘

Spork.prefork do
# …
RSpec.configure do |config|
# …
config.treat_symbols_as_metadata_keys_with_true_values = true
config.filter_run :focus => true
config.run_all_when_everything_filtered = true
end
end

Spork.each_run do
# This code will be run each time you run your specs.
FactoryGirl.reload
end
[/ruby]

Screencast: Zeit und Web-Anfragen testen/messen

Zeitmessungen mit der aktuellen Zeit und Anfragen an ggf. externe Seiten sind nicht ganz einfach. In diesem Screencast zeigt Ryan wie er solche Tests mit Timecop und FakeWeb durchführt.

 

Downloads in verschiedenen Formaten:

source code
mp4
m4v
webm
ogv

 

Resourcen:

Gemfile

[ruby]
group :test do
gem "timecop"
gem "fakeweb"
end
[/ruby]

spec_helper.rb

[ruby]
FakeWeb.allow_net_connect = false RSpec.configure do |config|
config.before(:each) do
Timecop.return FakeWeb.clean_registry
end
end
[/ruby]

user_spec.rb

[ruby]
it "saves the time the password reset was sent" do
Timecop.freeze user.send_password_reset Time.use_zone("Paris") do
user.reload.password_reset_sent_at.should eq(Time.zone.now)
end
end
[/ruby]

web_request_spec.rb

[ruby]
it "fetches the content length" do
FakeWeb.register_uri(:head, "http://example.com/", :content_length => 123) WebRequest.new(:url =>"http://example.com/").content_length.should eq(123)
end
[/ruby]

models/web_request.rb

[ruby]
def content_length uri = URI.parse(url)
response = Net::HTTP.start(uri.host, uri.port) { |http| http.request_head(uri.path) }
response["content-length"].to_i
end
[/ruby]

config/application.rb

[ruby]
require ’net/http‘
[/ruby]

Screencast: Testen von Password-Reset und Erinnerung

In der letzten Woche zeigte Ryan wie man selber eine Funktion zum Zurücksetzen von Passwörter bauen kann. In dieser Woche zeigt er wie er diese Funktion mit RSpec, Capybara, Factory Girl und Guard testet.

 

Downloads in verschiedenen Formaten:

source code
mp4
m4v
webm
ogv

 

Resourcen:

bash

[bash]
bundle rails g rspec:install mkdir spec/support spec/models spec/routing guard init rspec gem install rb-fsevent rails g integration_test password_reset rails g controller password_resets new –no-test-framework rails g mailer user_mailer password_reset rails g migration add_password_reset_to_users password_reset_token:string password_reset_sent_at:datetime rake db:migrate
[/bash]

Gemfile

[ruby]
gem "rspec-rails", :group => [:test, :development] group :test do gem "factory_girl_rails" gem "capybara" gem "guard-rspec" end
[/ruby]

spec_helper.rb

[ruby]
require ‚capybara/rspec‘ RSpec.configure do |config| # … config.include(MailerMacros) config.before(:each) { reset_email } end
[/ruby]

spec/support/mailer_macros.rb

[ruby]
module MailerMacros def last_email ActionMailer::Base.deliveries.last end def reset_email ActionMailer::Base.deliveries = [] end end
[/ruby]

config/environments/test.rb

[ruby]
config.action_mailer.default_url_options = { :host => "www.example.com" }
[/ruby]

spec/requests/password_resets_spec.rb

[ruby]
describe "PasswordResets" do it "emails user when requesting password reset" do user = Factory(:user) visit login_path click_link "password" fill_in "Email", :with => user.email click_button "Reset Password" current_path.should eq(root_path) page.should have_content("Email sent") last_email.to.should include(user.email) end it "does not email invalid user when requesting password reset" do visit login_path click_link "password" fill_in "Email", :with => "nobody@example.com" click_button "Reset Password" current_path.should eq(root_path) page.should have_content("Email sent") last_email.should be_nil end it "updates the user password when confirmation matches" do user = Factory(:user, :password_reset_token => "something", :password_reset_sent_at => 1.hour.ago) visit edit_password_reset_path(user.password_reset_token) fill_in "Password", :with => "foobar" click_button "Update Password" page.should have_content("Password doesn’t match confirmation") fill_in "Password", :with => "foobar" fill_in "Password confirmation", :with => "foobar" click_button "Update Password" page.should have_content("Password has been reset") end it "reports when password token has expired" do user = Factory(:user, :password_reset_token => "something", :password_reset_sent_at => 5.hour.ago) visit edit_password_reset_path(user.password_reset_token) fill_in "Password", :with => "foobar" fill_in "Password confirmation", :with => "foobar" click_button "Update Password" page.should have_content("Password reset has expired") end it "raises record not found when password token is invalid" do lambda { visit edit_password_reset_path("invalid") }.should raise_exception(ActiveRecord::RecordNotFound) end end
[/ruby]

spec/models/user_spec.rb

[ruby]
describe User do describe "#send_password_reset" do let(:user) { Factory(:user) } it "generates a unique password_reset_token each time" do user.send_password_reset last_token = user.password_reset_token user.send_password_reset user.password_reset_token.should_not eq(last_token) end it "saves the time the password reset was sent" do user.send_password_reset user.reload.password_reset_sent_at.should be_present end it "delivers email to user" do user.send_password_reset last_email.to.should include(user.email) end end end
[/ruby]

spec/mailers/user_mailer_spec.rb

[ruby]
describe UserMailer do describe "password_reset" do let(:user) { Factory(:user, :password_reset_token => "anything") } let(:mail) { UserMailer.password_reset(user) } it "send user password reset url" do mail.subject.should eq("Password Reset") mail.to.should eq([user.email]) mail.from.should eq(["from@example.com"]) mail.body.encoded.should match(edit_password_reset_path(user.password_reset_token)) end end end
[/ruby]

Screencast: Dateiüberwachung mit Guard

Guard ist ein Tool für die Konsole, mit dem Veränderungen (FSEvent / Inotify / Polling) an Dateien überwacht werden können. Eine solche Funktion kann zum Beispiel für automatisierte Tests, Neustarts von Servern und viele andere Bereiche, in denen eine „Folgeaktion“ erforderlich ist, nützlich sein. In diesem Screencast gibt es eine kleine Einführung in Guard und wie es konfiguriert wird.

 

Download:

Download(13.8 MB, 8:44)
Alternativer Download für iPod & Apple TV(16 MB, 8:44)

 

Resourcen:

 

Quellcode:

[bash]
bundle
guard init rspec
guard init livereload
guard
[/bash]

[ruby]
# Gemfile
group :development, :test do
# …
gem ‚rb-fsevent‘, :require => false if RUBY_PLATFORM =~ /darwin/i
gem ‚guard-rspec‘
gem ‚guard-livereload‘
end

# Guardfile
guard ‚livereload‘ do
watch(%r{app/.+.(erb|haml)})
watch(%r{app/helpers/.+.rb})
watch(%r{public/.+.(css|js|html)})
watch(%r{config/locales/.+.yml})
end

guard ‚rspec‘, :version => 2 do
watch(%r{^spec/.+_spec.rb})
watch(%r{^lib/(.+).rb}) { |m| "spec/lib/#{m[1]}_spec.rb" }
watch(’spec/spec_helper.rb‘) { "spec" }

# Rails example
watch(’spec/spec_helper.rb‘) { "spec" }
watch(‚config/routes.rb‘) { "spec/routing" }
watch(‚app/controllers/application_controller.rb‘) { "spec/controllers" }
watch(%r{^spec/.+_spec.rb})
watch(%r{^app/(.+).rb}) { |m| "spec/#{m[1]}_spec.rb" }
watch(%r{^lib/(.+).rb}) { |m| "spec/lib/#{m[1]}_spec.rb" }
watch(%r{^app/controllers/(.+)_(controller).rb}) { |m| ["spec/routing/#{m[1]}_routing_spec.rb", "spec/#{m[2]}s/#{m[1]}_#{m[2]}_spec.rb", "spec/requests/#{m[1]}_spec.rb"] }
watch(%r{^app/views/(.+)/}) { |m| "spec/requests/#{m[1]}_spec.rb" }
end
[/ruby]

Screencast: JavaScript mit Jasmine testen

Jasmine ist ein BDD-Testframework um JavaScript zu testen. Es ist für die Tests nicht auf DOM angewiesen und hat auch keine Abhängigkeiten zu anderen Frameworks. Ryan zeigt wie es in Kombination mit Rails eingesetzt werden kann.

 

Download:

Download(24.8 MB, 15:20)
Alternativer Download für iPod & Apple TV(25.3 MB, 15:20)

 

Resourcen:

 

Quellcode:

[bash]
bundle
rails g jasmine:install
rake jasmine
rake jasmine:ci
curl http://cloud.github.com/downloads/velesin/jasmine-jquery/jasmine-jquery-1.2.0.js > spec/javascripts/helpers/jasmine_jquery-1.2.0.js
[/bash]

[ruby]
# Gemfile
gem ‚jasmine‘, :group => [:development, :test]
[/ruby]

[javascript]
/* credit_card_spec.js */

describe("CreditCard", function() {
it("cleans number by removing spaces and dashes", function() {
expect(CreditCard.cleanNumber("123 4-5")).toEqual("12345");
});

it("validates based on mod 10", function() {
expect(CreditCard.validNumber("4111 1111-11111111")).toBeTruthy();
expect(CreditCard.validNumber("4111111111111121")).toBeFalsy();
});

it("validates when text field loses focus", function() {
loadFixtures("order_form.html");
$("#card_number").validateCreditCardNumber();
$("#card_number").val("123");
$("#card_number").blur();
expect($("#card_number_error")).toHaveText("Invalid credit card number.");
$("#card_number").val("4111 1111-11111111");
$("#card_number").blur();
expect($("#card_number_error")).toHaveText("");
});
});

/* credit_card.js */
var CreditCard = {
cleanNumber: function(number) {
return number.replace(/[- ]/g, "");
},

validNumber: function(number) {
var total = 0;
number = this.cleanNumber(number);
for (var i=number.length-1; i >= 0; i–) {
var n = parseInt(number[i]);
if ((i+number.length) % 2 == 0) {
n = n*2 > 9 ? n*2 – 9 : n*2;
}
total += n;
};
return total % 10 == 0;
}
};

(function($){
$.fn.validateCreditCardNumber = function() {
return this.each(function() {
$(this).blur(function() {
if (!CreditCard.validNumber(this.value)) {
$("#" + this.id + "_error").text("Invalid credit card number.");
} else {
$("#" + this.id + "_error").text("");
}
});
});
};
})(jQuery);

/* applicaiton.js */
$(function() {
$("#order_credit_card_number").validateCreditCardNumber();
});
[/javascript]

[html]
<!– orders/_form.html.erb –>
<%= f.text_field :credit_card_number %>
<span id="order_credit_card_number_error"></span>
[/html]

Request Specs und Capybara

Request specs in RSpec sind einge großartige Möglichkeit den kompletten Applikation-Stack zu testen. Ryan zeigt diese Woche wie dies und capybara in Verbindung mit Selenium eingesetzt werden kann.

 

Download:

Download(20.3 MB, 13:16)
Alternativer Download für iPod & Apple TV(20.6 MB, 13:16)

 

Resourcen:

 

Quellcode:

[bash]
bundle
rails g rspec:install
rails g integration_test task
rake spec:requests
[/bash]

[ruby]
# Gemfile
group :development, :test do
gem ‚rspec-rails‘
gem ‚capybara‘, :git => ‚git://github.com/jnicklas/capybara.git‘
gem ‚launchy‘
gem ‚database_cleaner‘
end

# spec/requests/tasks_spec
describe "Tasks" do
describe "GET /tasks" do
it "displays tasks" do
Task.create!(:name => "paint fence")
visit tasks_path
page.should have_content("paint fence")
end

it "supports js", :js => true do
visit tasks_path
click_link "test js"
page.should have_content("js works")
end
end

describe "POST /tasks" do
it "creates task" do
visit tasks_path
fill_in "New Task", :with => "mow lawn"
click_button "Add"
page.should have_content("Successfully added task.")
page.should have_content("mow lawn")
end
end
end

# spec_helper.rb
require ‚capybara/rspec‘

RSpec.configure do |config|
# …
config.use_transactional_fixtures = false

config.before(:suite) do
DatabaseCleaner.strategy = :truncation
end

config.before(:each) do
DatabaseCleaner.start
end

config.after(:each) do
DatabaseCleaner.clean
end
end
[/ruby]

[html]
<!– tasks/index.html.erb –>
<%= link_to_function "test js", ‚$(this).html("js works")‘ %>
[/html]

7 Videos von der WindyCityRails 2009

All diejenigen die nicht bei der WindyCityRails-Konferenz in Chicago sein konnten, haben nun die Möglichkeit sich zumindest sieben Vorträge als Video anzuschauen.

Die Videos sind auf den Seiten von windycityrails.org zu finden:

Better Ruby through Functional Programming von Dean Wampler – Dean Wampler führt in seinem Vortrag in die Konzepte der Funktionalen Programmierung ein.

Super-easy PDF Generation with Prawn and Prawnto von John McCaffrey – John zeigt wie einfach PDF Generierung sein kann.

Comics Is Hard: On Domains and Databases von Ben Scofield – Alernativen zu SQL-getriebenen Applikationen.

UI Fundamentals for Programmers von Ryan Singer – Ryan zeigt Arbeitsweisen von 37Signals.

How To Test Absolutely Anything (in Rails) von Noel Rappin – Noel zeigt wie man alle Schichten einer Rails-Applikation testen kann.

Optimizing Perceived Performance von David Eisinger – David zeigt an einem Beispiel wie Rails und JQuery zusammenarbeiten.

Rails 3 Update von Yehuda Katz – Yehuda gibt einen Einblick in Rails 3 und was uns mit diesem Release erwartet.