José Valim - Remarkable 3.0 - KRUG - 07apr2009

Preview:

DESCRIPTION

My presentation about Remarkable 3.0, discussing also about tests in general.

Citation preview

José Valim 2009

José Valimhttp://plataformatec.com.br

http://josevalim.blogspot.comjose.valim@plataformatec.com.br

How do I test my applications?

José Valim 2009

Who am I?

• Brazilian, 22-years-old, Master of Science in Engineering, Italy;

• Started with Ruby and Rails 2 years ago;

• Gems/plugin developer (Remarkable, Inherited Resources, Rails footnotes, Simple form and counting);

• Rails core contributor (11 patches and counting).

José Valim 2009

How do I test my applications?

José Valim 2009

You should ask it everyday during

breakfast.

José Valim 2009

Or at least before each project.

José Valim 2009

You might also want to know why do you test.

José Valim 2009

Or even why you should not test.

José Valim 2009

What I already heard…

José Valim 2009

What I already heard…

José Valim 2009

A few reasons to test

• Ensure that everything works;

• Tests as documentation;

• Leads you to write better code.

José Valim 2009

A few reasons NOT to test

I wrote it, then it works (yes, I heard it!);

Trust other people code. Should I test a has_one or a validates_presence_of in my models?

• Ensure that everything works

José Valim 2009

A few reasons NOT to test

Your code should document itself;

• Tests as documentation

• Leads you to write better code

People spend more time writing tests than writing the code, which is what really matters.

José Valim 2009

Don’t judge.

José Valim 2009

Think.

José Valim 2009

How do I test?

• Waterfall? TDD? BDD?

• Test::Unit? Rspec?

• Isolation? Integration? Cucumber?

• Time? Fast?

José Valim 2009

Test::Unit? Rspec?

• Test::Unit is faster and simpler;

• Rspec code is more readable, not that fast;

• Rspec is great if you want to use your tests as documentation/specification.

José Valim 2009

Integration? Isolation?

• Integration = Rails default approach

Unit test your models and functional tests with your controllers and views.

• Isolation = Rspec default approach

Each MVC layer is tested separately with mocks and stubs. Then use Cucumber to integrate those layers.

José Valim 2009

My experience

• I finish my tasks and tests faster when working in the integration way;

• Mocks and stubs are hard to maintain (does it has to be this way?);

• Not sure if integration runs faster than isolation and vice-versa.

José Valim 2009

Simplifying tests!

José Valim 2009

Simplifying tests (in rspec)!

José Valim 2009

To use the tool, you have to understand the reasons.

José Valim 2009

Why to test Rails validations?

• You have to write the tests first;

• Validations are one liner. Easy to add, easy to remove;

• Documentation/specification;

• I do it.

José Valim 2009

How to test Rails validations?

• Test::Unit way:

class UserTest < Test::Unit

def test_user_not_valid_if_name_is_blank

user = User.create

assert user.invalid?

assert_equal :blank, user.errors[:name]

end

end

José Valim 2009

How to test Rails validations?

• Rspec way:

describe User do

it “should not be valid if name is blank” do

user = User.create

user.should_not be_valid

user.errors[:name].should == :blank

end

end

José Valim 2009

How to test Rails validations?

• Remarkable way:

describe User do it { should validate_presence_of(:name) } end

• Or:

describe User do should_validate_presence_of :name end

José Valim 2009

How to test Rails validations?

• Remarkable way:

describe User do it { should validate_presence_of(:name) } end

• Or:

describe User do should_validate_presence_of :name end

Conversion from matchers to macros happens automatically on Remarkable

José Valim 2009

Remarkable ActiveRecord 2.x

• Matchers for all validations with all options;

• Matchers for all associations, few options supported;

• Named scopes and mass assignment matchers;

• Database matchers;

• Callback, instance and class method matchers.

José Valim 2009

Remarkable ActiveRecord 3.0

• Matchers for all validations with all options;

• Matchers for all associations, almost all options supported;

• Named scopes and mass assignment matchers;

• Database matchers;

• Callback, instance and class method matchers.

José Valim 2009

Why have isolation tests?

• Design option;

• You love cucumber;

• I do it sometimes, sometimes I don’t.

José Valim 2009

How to isolate my controllers?

• Rspec way:

describe TasksController do describe “responding to #POST create” do it "exposes a newly created task as @task" do Task.should_receive(:new).with({'these' => 'params'}). and_return(mock_task(:save => true)) post :create, :task => {:these => 'params'} assigns[:task].should equal(mock_task) end

it "redirects to the created task" do Task.stub!(:new).and_return(mock_task(:save => true)) post :create, :task => {} response.should redirect_to(task_url(mock_task)) end end end

José Valim 2009

How to isolate my controllers?

• Rspec way:

describe TasksController do describe “responding to #POST create” do it "exposes a newly created task as @task" do Task.should_receive(:new).with({'these' => 'params'}). and_return(mock_task(:save => true)) post :create, :task => {:these => 'params'} assigns[:task].should equal(mock_task) end

it "redirects to the created task" do Task.stub!(:new).and_return(mock_task(:save => true)) post :create, :task => {} response.should redirect_to(task_url(mock_task)) end end end

José Valim 2009

Problems with Rspec way

•It’s not readable. I have to read the stubs before reading the action.

it "redirects to the created task" do

Task.stub!(:new).and_return(mock_task(:save => true))

post :create, :task => {}

response.should redirect_to(task_url(mock_task))

end

José Valim 2009

Problems with Rspec way

• It’s not DRY. I have to write expectations (:should_receive) and stubs (:stub!).

Task.should_receive(:new).with({'these' => 'params'}).

and_return(mock_task(:save => true))

Task.stub!(:new).and_return(mock_task(:save => true))

José Valim 2009

How to isolate my controllers?

• Remarkable 3.0 way:

describe TasksController do

describe :post => :create, :task => {:these => 'params'} do

expects :new, :on => Task,

:with => { :these => 'params' },

:returns => mock_task

should_assign_to :task, :with => mock_task

should_redirect_to { task_url(mock_task) }

end

end

José Valim 2009

How to isolate my controllers?

• Remarkable 3.0 way:

describe TasksController do describe :post => :create, :task => {:these => 'params'} do expects :new, :on => Task, :with => { :these => 'params' }, :returns => mock_task

should_assign_to :task, :with => mock_task should_redirect_to { task_url(mock_task) } end end

Perform action using expectations (:should_receive)

José Valim 2009

How to isolate my controllers?

• Remarkable 3.0 way:

describe TasksController do describe :post => :create, :task => {:these => 'params'} do expects :new, :on => Task, :with => { :these => 'params' }, :returns => mock_task

should_assign_to :task, :with => mock_task should_redirect_to { task_url(mock_task) } end end

Perform action using stubs (:stub!)

José Valim 2009

Why to speed up my tests?

José Valim 2009

Why to speed up my tests?

José Valim 2009

How to speed up my tests?• Rspec way (one request per test = slow):

describe TasksController do describe “responding to #POST create” do it "exposes a newly created task as @task" do Task.should_receive(:new).with({'these' => 'params'}). and_return(mock_task(:save => true)) post :create, :task => {:these => 'params'} assigns[:task].should equal(mock_task) end

it "redirects to the created task" do Task.stub!(:new).and_return(mock_task(:save => true)) post :create, :task => {} response.should redirect_to(task_url(mock_task)) end end end

José Valim 2009

How to speed up my tests?

• Terrible way (but fast):

describe TasksController do describe “responding to #POST create” do it “should assign to @task and redirect” do Task.should_receive(:new).with({'these'=>'params'}). and_return(mock_task(:save => true))

post :create, :task => {:these => 'params'}

assigns[:task].should equal(mock_task) response.should redirect_to(task_url(mock_task)) end end end

José Valim 2009

How to speed up my tests?

• Rspec solution?

before(:all) do

# It does not work without tweaking

end

• Test::Unit solution?

José Valim 2009

How to speed up my tests?

• Remarkable 3.0 way:

describe TasksController do

describe :post! => :create do

expects :new, :on => Task, :returns => mock_task

should_assign_to :task, :with => mock_task

should_redirect_to { task_url(mock_task) }

end

end

José Valim 2009

How to speed up my tests?

• Remarkable 3.0 way:

describe TasksController do

describe :post! => :create do

expects :new, :on => Task, :returns => mock_task

should_assign_to :task, :with => mock_task

should_redirect_to { task_url(mock_task) }

end

end

BANG!

José Valim 2009

How to speed up my tests?

• Remarkable 3.0 way:

describe TasksController do

describe :post! => :create, :task => {} do

should_assign_to :task, :with => mock_task

should_redirect_to { task_url(mock_task) }

end

endWorks without stubs and mocks too.

José Valim 2009

How to speed up my tests?

• Remarkable 3.0 BANG way:

Experimental. But if you have any problem, just remove the bang!

Its core might be ported back to rspec.

José Valim 2009

And for those who use tests as specification…

José Valim 2009

And for those who use tests as specification…

• example/specs.rb

describe User do

should_validate_presence_of :name, :email

xshould_validate_presence_of :age

should_validate_length_of :name, :within => 3..40

should_validate_uniqueness_of :email, :case_sensitive => false

should_validate_numericality_of :age, :only_integer => true,

:greather_than_or_equal_to => 18, :allow_blank => true

end

José Valim 2009

And for those who use tests as specification…

• ruby example/specs.rb –cfs en

Example disabled: require age to be set

User- should require name and email to be set- should ensure length of name is within 3..40 characters- should require unique values for email case insensitive- should ensure numericality of age allowing only integer values

and allowing blank values

Finished in 0.262418 seconds

José Valim 2009

And for those who use tests as specification…

• ruby example/specs.rb –cfs pl

Przykład niepełnosprawny: wymagać podania wiek

Użytkownik

- powinien wymagać podania imię i e-mail

- powinien upewnienia co do ilości znaków imię pomiędzy 3..40

- powinien wymagać niepowtarzalnych wartości dla e-mail z brakiem

znaczenia wielkości liter

- powinien upewnienia o numeryczności wiek zezwalając tylko na całe

wartości i zezwalając pustą wartość

Finished in 0.255462 seconds

José Valim 2009

And for those who use tests as specification…

• ruby example/specs.rb –cfs pl

Przykład niepełnosprawny: wymagać podania wiek

Użytkownik

- powinien wymagać podania imię i e-mail

- powinien upewnienia co do ilości znaków imię pomiędzy 3..40

- powinien wymagać niepowtarzalnych wartości dla e-mail z brakiem

znaczenia wielkości liter

- powinien upewnienia o numeryczności wiek zezwalając tylko na całe

wartości i zezwalając pustą wartość

Finished in 0.255462 seconds REMARKABLE 3.0

SPECS WITH I18N

José Valim 2009

So Remarkable is…

• A framework for rspec matchers which provides automatic conversion to macros;

• Decouple matcher logic from content, using .yml files and providing I18n;

• Has a DSL and provides common helpers .

José Valim 2009

So Remarkable is…

• Remarkable 3.0 is composed of:

Remarkable Remarkable ActiveRecord

Matchers and some I18n tweaks Remarkable Rails

Controller matchers Macro Stubs (:expects DSL)

José Valim 2009

So Remarkable is…

• Remarkable 3.x will be composed of:

Remarkable Remarkable ActiveRecord Remarkable Rails Remarkable Datamapper? Remarkable Sequel?

José Valim 2009

So Remarkable is…

• Remarkable 3.x will be composed of:

Remarkable Remarkable ActiveRecord Remarkable Rails Remarkable Datamapper? Remarkable Sequel?

VOLUNTEERS?

José Valim 2009

When? Where?

• Remarkable 3.0 beta will be released mid April;

• Got get it on Github:http://github.com/carlosbrando/remarkable

• Follow my blog:http://josevalim.blogspot.com/

José Valim 2009

José Valimhttp://plataformatec.com.br

http://josevalim.blogspot.comjose.valim@plataformatec.com.br

?!