Posts Tagged ‘mock’

Using Mocha – A review

Wednesday, August 1st, 2007 by Thilo Utke

For aprox. 3 months we have been using mocha now. And we promised to get back to this subject when we passed our 2000th revision.

In this post I’d like to share some expirence we made while using mocha. But first a short introduction to mocha taken from the rubyforge page.

Mocha is a library for mocking and stubbing using a syntax like that of JMock, and SchMock. One of its main advantages is that it allows you to mock and stub methods on real (non-mock) classes and instances.

We started to use mocha on an existing test suite and changed our test code in place when we wrote a new test or had to update old ones. The transition was mostly painless, there were three things where we stumbled.
(more…)

Wir machen unseren Tests Beine

Friday, March 30th, 2007 by Thilo Utke

Da unsere vielen Tests mittlerweile ein wenig lange brauchen, haben wir uns am heutigen Forschungstag mal wieder mit dem Problem Testing auseinandergesetzt. Das Ergebniss diesmal schon vorne weg: unsere erfolgreichste Entdeckung ist Mocha.
Mit diesem Framework lassen sich Stubs und Mocks mit realen Objekten verwenden. Es folgt ein kleiner Auszug aus unserem bisherigen Testcode.

def create_activated_user(attributes = {})
email = generate_email_address
User.create!({:gender => ‘m’, :first_name => ‘joe’, :last_name => ‘doe’, :email => email,
:password => ‘test’, :password_confirmation => ‘test’, :city => “berlin”, :status => ‘active’
}.merge(attributes))
end

def create_auto(user = nil, attributes = {})
user = create_user unless user
Auto.create!(auto_hash(user).merge(attributes))
end

def test_activity_returns35_for_user_with_picture_and_auto_with_picture
user = create_activated_user :photo => ‘1.gif’
create_auto user, :photo => ‘2.gif’
assert_equal(35, user.activity)
end

Dauer: 795ms

Nach kurzem Studium des Mocha Cheat Sheets haben wir dann den Test wie folgt geändert.

def test_activity_return35_for_user_with_picture_and_auto_with_picture
with_photos = stub :with_photos => [Auto.new(:photo =>'test.gif')]
user = User.new :photo => ‘1.gif’
user.stubs(:autos).returns(with_photos)
assert_equal(35, user.activity)
end

Dauer: 49ms

Na wenn das keine signifikate Verbesserung ist. Auf Mocha gestoßen sind wir über den Testing Rails Blog, auf dem leider nichts Neues mehr zu passieren scheint. Eine kleine Übersicht von Stub-Frameworks mit problemspezifischen Einschätzungen fanden wir auf dem Blog von Jay Fields.

Wir werden Mocha in der nächsten Zeit in unseren Test integrieren, und bei der 2000ten Revision sagen wir euch wie lange unsere Test Suite läuft.

Rails: FileColumn schneller testen durch Mocks

Sunday, March 11th, 2007 by Alexander Lang

FileColumn ist ein wirkliches zauberhaftes Plugin fuer Ruby on Rails. All unsere Bilder-Uploads haben wir bisher damit umgesetzt. FileColumn bietet Helper, um Datei-Uploads zu bauen und kann die hochgeladenen Bilder natuerlich auch wieder anzeigen. Das eigentlich schoene ist aber die Integration mit RMagick, einem Ruby-Binding fuer ImageMagick, wodurch sich Bilder on the fly skalieren sowie beschneiden lassen und die verschiedenen Versionen dann automatisch im Dateisystem landen. Alles, was man dazu braucht, ist eine Zeile Code im Model, z.B.

class User
file_column :photo, :magick => { :versions => {
:normal => “238x”,
:tiny => “26×35!”,
:small => {:crop => “1:1″, :size => “73×73!”, :name => “small”},
}}
end

Dieser Code erzeugt neben der Originalversion 3 Kopien: Eine 238 Pixel breite und entsprechend des Bildformats hohe, eine gestauchte, genau 23 x 35 Pixel grosse und eine genau 73 x 73 Pixel grosse, beschnittene Version.

So weit alles schoen. Das einzige Problem war, dass unsere Unit-Tests durch FileColumn ganz schoen langsam wurden. Bei jedem Testdurchlauf, der irgendwas mit Bilder zu tun hatte, wurden jedes mal mehrere skalierte Versionen erzeugt, was natuerlich Rechenzeit kostete. Die Loesung haben wir letzte Woche dann endlich mal zusammengehackt, und sie sieht so aus: Ein Modul, was von FileColumn installierte Callbacks ausser Gefecht setzt, wird in ein Mock des Models eingebunden, aber der Reihe nach. Hier das Modul, gelegen in test/file_column_mock.rb:

module FileColumnMock

def mock_file_column(attr)
define_method “#{attr}=” do |value|
if value.is_a?(File)
write_attribute attr, value.path
else
write_attribute attr, value
end
end

define_method “#{attr}_after_assign” do
end

define_method “#{attr}_after_save” do
end

define_method “#{attr}_state” do
DummyState.new self.send(:read_attribute, attr)
end

define_method “#{attr}_after_destroy” do
end
end

class DummyState

def initialize(file_name)
@file_name = file_name
end

def has_magick_errors?
false
end

def absolute_path(*args)
@file_name
end
def relative_path(subdir = nil)
@file_name
end

def temp_path
@file_name
end

def assign_temp(temp_path)
nil
end
end
end

In unserem Beispiel wollen wir die Klasse User von ihrer FIleColumn-Last befreien. Dazu legen wir in test/mocks/test eine Datei user.rb an und fuellen sie mit folgendem Inhalt:

require ‘models/user’
require File.dirname(__FILE__) + ‘/../../file_column_mock’

class User
extend FileColumnMock
mock_file_column :photo
end

Der Effekt des ganzen ist, dass die Original User-Klasse aus app/models nochmals geoeffnet und mehrere Methoden, die normalerweise automatisch beim Setzen des photo-Attributs loslaufen, umd die skalierten Versionen zu erzeugen, durch Ueberschreiben ausser Gefecht gesetzt werden.

Das war’s. Und schon fliegen die Tests wieder mit voller Geschwindigkeit.