36
Testing/Testing In Rails 1 Alan and Saskia Alan and Saskia 2/8/2008

Testing/Testing In Rails 1€¦ · Testing In General (1) • Formal Definition – Testin gg is the process of finding differences between the expected behavior specified by system

  • Upload
    others

  • View
    4

  • Download
    0

Embed Size (px)

Citation preview

Page 1: Testing/Testing In Rails 1€¦ · Testing In General (1) • Formal Definition – Testin gg is the process of finding differences between the expected behavior specified by system

Testing/Testing In Rails 1

Alan and SaskiaAlan and Saskia

2/8/2008

Page 2: Testing/Testing In Rails 1€¦ · Testing In General (1) • Formal Definition – Testin gg is the process of finding differences between the expected behavior specified by system

OutlineOutline

• Testing In General

• Unit Testing and Test First!Unit Testing and Test First!

• Integration Testing

• Functional Testing

• Fixture• Fixture

• Mocking with Mocha

Page 3: Testing/Testing In Rails 1€¦ · Testing In General (1) • Formal Definition – Testin gg is the process of finding differences between the expected behavior specified by system

Testing In General (1)Testing In General (1)

• Formal Definition– Testing is the process of finding differences g p gbetween the expected behavior specified by system models and the observed behavior of the yimplemented system. 

– The goal is to design tests that exercise defects inThe goal is to design tests that exercise defects in the system and to reveal problems

Page 4: Testing/Testing In Rails 1€¦ · Testing In General (1) • Formal Definition – Testin gg is the process of finding differences between the expected behavior specified by system

Testing In General (2)Testing In General (2)

• Alternative Definition– Testing has to demonstrate that faults are not gpresent at all.

• Almost impossible to showAlmost impossible to show

• May lead to the selection of test data that have a low probability of causing the program to failp y g p g

• Even more alternative (Wilson Bilkovich) W iti li ti ith t t t k– Writing applications without tests makes you a bad person, incapable of love.

Page 5: Testing/Testing In Rails 1€¦ · Testing In General (1) • Formal Definition – Testin gg is the process of finding differences between the expected behavior specified by system

Types of Testing (1)Types of Testing (1)

Page 6: Testing/Testing In Rails 1€¦ · Testing In General (1) • Formal Definition – Testin gg is the process of finding differences between the expected behavior specified by system

Types of Testing (2)Types of Testing (2) 

Page 7: Testing/Testing In Rails 1€¦ · Testing In General (1) • Formal Definition – Testin gg is the process of finding differences between the expected behavior specified by system

Unit Testing in RubyUnit Testing in Ruby

• Unit Testing

– Testing small units of codes (normally methods) • Test::Unit

– Ruby’s built‐in testing framework

– xUnit family (Java’s Junit, .NET’s Nunit)

• Concepts

– Assertions: comparison of expected value and result of an expression

– Failure: assertion failure

– Error: exception or runtime error

– Green vs red bar

Page 8: Testing/Testing In Rails 1€¦ · Testing In General (1) • Formal Definition – Testin gg is the process of finding differences between the expected behavior specified by system

Unit Testing in Ruby (2)Unit Testing in Ruby (2)require 'roman'

require 'test/unit'<<Class inclusion

require  test/unit

class TestRoman < Test::Unit::TestCase

def setup

<<super class

<<code to be run before all test methodsp

end

<< i ti

<<code to be run before all test methods

def test_simple

assert_equal("i", Roman.new(1).to_s) assert equal("ix" Roman new(9) to s)

<<naming convention

<<assertionsassert_equal( ix , Roman.new(9).to_s)

end

def teardown

end <<code to be run after all test methods

end

Page 9: Testing/Testing In Rails 1€¦ · Testing In General (1) • Formal Definition – Testin gg is the process of finding differences between the expected behavior specified by system

Assertions (1)Assertions (1)

• assert(boolean, [ message ] )

– Fails if boolean is false or nil.

• assert_nil(obj, [ message ] )

• assert_not_nil(obj, [ message ] ) – Expects obj to be (not) nil.

• assert_equal(expected, actual, [ message ] ) • assert_not_equal(expected, actual, [ message ] )

– Expects obj to equal/not equal expected, using ==.

• assert_in_delta(expected_float, actual_float, delta, [ message ] ) – Expects that the actual floating‐point value is within delta of the expected value.

Page 10: Testing/Testing In Rails 1€¦ · Testing In General (1) • Formal Definition – Testin gg is the process of finding differences between the expected behavior specified by system

Assertions (2)Assertions (2)

( ) { bl k }• assert_raise(Exception, . . . ) { block }

• assert_nothing_raised(Exception, . . . ) { block }

– Expects the block to (not) raise one of the listed exceptionsExpects the block to (not) raise one of the listed exceptions.

• assert_instance_of(klass, obj, [ message ] ) • assert_kind_of(klass, obj, [ message ] )

– Expects obj to be a kind/instance of klass.

• assert_respond_to(obj,message, [ message ] ) ( )– Expects obj to respond to message (a symbol).

• assert_match(regexp, string, [ message ] ) • assert no match(regexp string [ message ] )assert_no_match(regexp, string, [ message ] )

– Expects string to (not) match regexp.

• assert_same(expected, actual, [ message ] ) • assert_not_same(expected, actual, [ message ] )

– Expects expected.equal?(actual).

Page 11: Testing/Testing In Rails 1€¦ · Testing In General (1) • Formal Definition – Testin gg is the process of finding differences between the expected behavior specified by system

Assertions (3)Assertions (3)

( b b [ ] )• assert_operator(obj1, operator, obj2, [ message ] )

– Expects the result of sending the message operator to obj1 with parameter obj2 to be true.p j

• assert_throws(expected_symbol, [ message ] ) { block }

– Expects the block to throw the given symbol.

• assert_send(send_array, [ message ] ) – Sends the message in send_array[1] to the receiver in send_array[0], 

passing the rest of send array as arguments Expects the return valuepassing the rest of send_array as arguments. Expects the return value to be true.

• flunk(message="Flunked") – Always fail.

Page 12: Testing/Testing In Rails 1€¦ · Testing In General (1) • Formal Definition – Testin gg is the process of finding differences between the expected behavior specified by system

Test First!Test First!

• What is it about?– Write the test cases first. Then write minimal codes to pass the tests

– Write more tests Write more minimal codes toWrite more tests. Write more minimal codes to pass the tests

Iterate the process till all functional requirements– Iterate the process till all functional requirements are satisfied ☺

Page 13: Testing/Testing In Rails 1€¦ · Testing In General (1) • Formal Definition – Testin gg is the process of finding differences between the expected behavior specified by system

Test First GuidelinesTest First Guidelines

h f h h ld d b h f h d• The name of the test should describe the requirement of the code

• There should be at least one test for each requirement of the code. Each possible path through of the code is a different requirementp p g q

• Only write the simplest possible code to get the test to pass, if you know this code to be incomplete, write another test that demonstrates what else the code needs to doelse the code needs to do

• A test should be similar to sample code, in that it should be clear to someone unfamiliar with the code as to how the code is intended to be used

• If a test seems too large, see if you can break it down into smaller tests

• If you seem to be writing a lot of code for one little test see if there are• If you seem to be writing a lot of code for one little test, see if there are other related tests you could write first, that would not require as much code

• More at http://www.xprogramming.com/xpmag/testFirstGuidelines.htm

Page 14: Testing/Testing In Rails 1€¦ · Testing In General (1) • Formal Definition – Testin gg is the process of finding differences between the expected behavior specified by system

Test First DemoTest First Demo

Page 15: Testing/Testing In Rails 1€¦ · Testing In General (1) • Formal Definition – Testin gg is the process of finding differences between the expected behavior specified by system

Unit Testing in RailsUnit Testing in Rails

• In rails, unit testing is geared towards testing of individual functions created in a model

• For each model generated, a test file is automatically created in tests/unit directoryautomatically created in tests/unit directory

• script/generate model product name:string description:string

exists app/models/exists  app/models/

exists  test/unit/

exists  test/fixtures/

create  app/models/product.rb

create  test/unit/product_test.rb

….

Page 16: Testing/Testing In Rails 1€¦ · Testing In General (1) • Formal Definition – Testin gg is the process of finding differences between the expected behavior specified by system

Testing/Testing In Rails 1 Saskia

Outline

• Testing In General

U it T ti d T t Fi t!• Unit Testing and Test First!

• Integration Testingg g

• Functional Testing

i• Fixture

• Mocking with Mochag

Page 17: Testing/Testing In Rails 1€¦ · Testing In General (1) • Formal Definition – Testin gg is the process of finding differences between the expected behavior specified by system

Types of Testing (1)Types of Testing (1)

Page 18: Testing/Testing In Rails 1€¦ · Testing In General (1) • Formal Definition – Testin gg is the process of finding differences between the expected behavior specified by system

Integration Testing in RoRIntegration Testing in RoR

i i• Integration Testing

– story‐level, tests interactions & interfaces of various actions t d b th li ti ll t llsupported by the application, across all controllers

– Find bugs with session management and routing, triggered by certain cruft accumulating in a user’s sessionby certain cruft accumulating in a user s session

• In 't t/i t ti ':• In 'test/integration':

– Create test file with 'script/generate integration_test stories_test'

Cl I t ti T t i h it f T t U it– Class IntegrationTest inherits from Test::Unit 

Page 19: Testing/Testing In Rails 1€¦ · Testing In General (1) • Formal Definition – Testin gg is the process of finding differences between the expected behavior specified by system

Integration Testing in RoRIntegration Testing in RoR

• Story set describes how the application ought to function

I t f h f i ht d t– Interfaces: exchange of right data 

– Interaction: employment of right components

l l l• Example: signing up, getting account, multiple users

• Testing time grows with number of integrated units

– Bottom‐Up: Integrate tested Units to subsystems as new components 

Page 20: Testing/Testing In Rails 1€¦ · Testing In General (1) • Formal Definition – Testin gg is the process of finding differences between the expected behavior specified by system

Integration Testing in RoRg g

i "#{Fil di ( FILE )}/ /t t h l " l i l i

File 'stories_test.rb' in 'test/integration':require "#{File.dirname(__FILE__)}/../test_helper"

class StoriesTest < ActionController::IntegrationTest

fixtures :users, :accounts

<<class inclusion

<<Integration Test Classfixtures :users, :accounts

def test_stories

get "/signup"<<naming convention

assert_response :success

assert_template "signup/index"

"/ i " "B b" "b b"

<<assertions

post "/signup", :name => "Bob", :user_name => "bob",

:password => "secret"

assert response :redirectassert_response :redirect

follow_redirect!

assert_response :success

assert_template "account/index"

end

Page 21: Testing/Testing In Rails 1€¦ · Testing In General (1) • Formal Definition – Testin gg is the process of finding differences between the expected behavior specified by system

Integration Testing in Ruby (2)g g y ( )Run by: rake test_integration or ruby stories_test.rbO t tStarted

.F..E <<Each spot represents a test, sorted alphabetically,

Output:

Finished in 0.01 seconds.

p p p y3 values: . means successful test (pass)

F means failed testE means an error occurred

1) Failure:

where/which test

what went wrong <<Listing of failures & errors:what went wrong

2) Error:

where/which test

<<Listing of failures & errors:Details on where and whatMoves on with first wrong assertion.

/

error_type

what went wrong

5 tests, 9 assertions, 1 failure, 1 error.

Page 22: Testing/Testing In Rails 1€¦ · Testing In General (1) • Formal Definition – Testin gg is the process of finding differences between the expected behavior specified by system

Types of Testing (1)Types of Testing (1)

Page 23: Testing/Testing In Rails 1€¦ · Testing In General (1) • Formal Definition – Testin gg is the process of finding differences between the expected behavior specified by system

Functional Testing in RubyFunctional Testing in Ruby

• Functional Testingsingle controllers and interactions between the– single controllers and interactions between the models it employs

• In directory 'test/function':

– 'functional controller test rb' stubs for each 'script/generate– functional_controller_test.rb stubs for each script/generate controller'

Page 24: Testing/Testing In Rails 1€¦ · Testing In General (1) • Formal Definition – Testin gg is the process of finding differences between the expected behavior specified by system

Functional Testing in RoRFunctional Testing in RoRrequire File.dirname(__FILE__) + '/../test_helper'

require 'home controller' << grab HomeController for testingrequire  home_controller

class HomeControllerTest < Test::Unit::TestCase

def setup

<< grab HomeController for testing

<< setup of 3 typical funtional Test objects:p

@controller = HomeController.new

@request = ActionController::TestRequest.new

setup of 3 typical funtional Test objects:* controller to be tested

* TestRequest tosimulate web request

@response = ActionController::TestResponse.new

end

def test index

q* TestResponse to provide

information about test request

def test_index

get :index

assert response :success

<< test of main index page<< get method simulates request on action called index . << assertion assures that request successful_ p

end

end

assertion assures that request successful

5 request types supported as methods in Rails:get, post, put, head, delete

Page 25: Testing/Testing In Rails 1€¦ · Testing In General (1) • Formal Definition – Testin gg is the process of finding differences between the expected behavior specified by system

Fixtures in RoRFixtures in RoR• Fixtures: automatically created sample data• Fixtures: automatically created sample data

– To fill testing database with predefined data before tests run

d t b i d d t– database independent

– Require explicit loading with fixtures method within test class

• In directory 'test/fixtures':

– fixture stubs for each 'script/generate model'

• Formats

– YAML: good readability, file extension '.yml' 

– CSV: comma‐separated value file format, '.csv', easy reuse of / /existing data in spreadsheet/database (save/export as CSV)

Page 26: Testing/Testing In Rails 1€¦ · Testing In General (1) • Formal Definition – Testin gg is the process of finding differences between the expected behavior specified by system

YAML‐FixturesFile 'persons.yml' of YAML-Fixtures in 'text/fixtures':# This is a YAML comment!

david:

id: 1<< name1

id: 1 

name: David Dwarf 

birthday: 0010‐01‐01 << list of values

profession: slingshoter

goliath: << name2<< fixture-records separated by blank line

id: 2

name: Goliath Giant

bi thd 0000 02 22

each fixture: * 'fixture-name'birthday: 0000‐02‐22

profession: terrorizer* list of colon-separated key/value pairs

Page 27: Testing/Testing In Rails 1€¦ · Testing In General (1) • Formal Definition – Testin gg is the process of finding differences between the expected behavior specified by system

CSV‐FixturesS tu esFile 'users.csv' of CSV-Fixtures in 'text/fixtures':id, username, password, intelligent, comments

1, dhow, imstupid, false, I laugh ""Ha! Ho! Hu!"" 

2 admin ihatedhows true What a mess! << list of value-records

<< header: first line, comma-separated list of fields

2, admin, ihatedhows, true, What a mess!

3, nobody, ilovetomock, true, "Nobody mocks you" 

4, nulpe,, false, 

<< list of value records,one record per line

format:* each cell stripped of outward facing spaces each cell stripped of outward facing spaces* comma as data: cell must be encased in

quotes* quote as data: must escape it with 2nd quote

CSV fixture names automatically generated: “model‐name”‐”counter”

q p q* no blank lines* nulls achived by placing comma

y gusers‐1

users‐2

... 

Page 28: Testing/Testing In Rails 1€¦ · Testing In General (1) • Formal Definition – Testin gg is the process of finding differences between the expected behavior specified by system

Fixtures in ActionFixtures in Action# allow this test to hook into the Rails framework# allow this test to hook into the Rails framework

require File.dirname(__FILE__) + '/../test_helper'

# need to include a User for testing

require 'user'

class UserTest < Test::Unit::TestCase

fixtures :users

def test_count_fixtures

<< fixture-load method: * destroys any data in users table* loads fixture data into users table

assert_equal 5, User.count

end

* dumps the data into a variable for direct access

t ti l d f th fi t t th t t f h t t th dend automatic load of the fixtures at the start of each test method

Page 29: Testing/Testing In Rails 1€¦ · Testing In General (1) • Formal Definition – Testin gg is the process of finding differences between the expected behavior specified by system

Hashes with FixturesHashes with FixturesFixtures are basically Hash objects:

direct access via generated local variable of the test case- direct access via generated local variable of the test caseFixtures can get form of the original class:- access to methods only available to that class...

fixtures :users, :person

def test user

access to methods only available to that class

<< load multiple fixtures separated by commasdef test_user

users(:nobody) users(:nobody).id

<< returns Hash for fixture named david << returns id-property of david( y)

end

def test_person

p p y

david = users(:david).find

email( david.girlfriend.email, david.illegitimate_children ) d

<< using find method to grab "real" david as Person

<<now: access to methods only available to a Person classend

...

methods only available to a Person class

Page 30: Testing/Testing In Rails 1€¦ · Testing In General (1) • Formal Definition – Testin gg is the process of finding differences between the expected behavior specified by system

Mocking with MochaMocking with Mocha

• Problem with Fixtures• Problem with Fixtures– Fixtures makes testing slow (engage the actual DB) – Fixtures allow invalid data

– Maintainability Challengesy g

– Fixtures are brittle

Th t’ h d M h• That’s why we need Mocha (http://mocha.rubyforge.org/) – It provides stubs and mocks to simulate data, especially data in the databasep y

Page 31: Testing/Testing In Rails 1€¦ · Testing In General (1) • Formal Definition – Testin gg is the process of finding differences between the expected behavior specified by system

Installing MochaInstalling Mocha

• sudo gem install mocha

• In rails, include in test/test helper.rbIn rails, include in test/test_helper.rb

require ‘mocha’

Page 32: Testing/Testing In Rails 1€¦ · Testing In General (1) • Formal Definition – Testin gg is the process of finding differences between the expected behavior specified by system

Do Not Mock My StubDo Not Mock My Stub

• Stubbing (State Verification)

– Stubbing a method is all about replacing the method with d th t t ifi d lt ( h icode that returns a specified result (or perhaps raises a 

specified exception).

• Mocking (Behavior Verification)• Mocking (Behavior Verification)

– Mocking a method is all about asserting that a method has been called (perhaps with particular parameters)been called (perhaps with particular parameters).

• it’s difficult (or impossible?) to do mocking without stubbing ‐you need to return from the mocked method, so that theyou need to return from the mocked method, so that the code under test can complete execution

• http://www.martinfowler.com/articles/mocksArentStubs.htmlp // / /

Page 33: Testing/Testing In Rails 1€¦ · Testing In General (1) • Formal Definition – Testin gg is the process of finding differences between the expected behavior specified by system

Stubbing example (stub)Stubbing example (stub)

' / 'require 'test/unit'

require 'rubygems'

require 'mocha'require mocha

class TestProduct < Test::Unit::TestCase

def test_product

product = stub('ipod_product', :manufacturer => 'ipod', :price => 100) assert_equal 'ipod', product.manufacturer

assert_equal 100, product.price

endend

end

Page 34: Testing/Testing In Rails 1€¦ · Testing In General (1) • Formal Definition – Testin gg is the process of finding differences between the expected behavior specified by system

More stubbing example (stubs)More stubbing example (stubs)class View

attr :document

def initialize(document) require 'test/unit'require 'rubygems'req ire 'mocha'@document = document

end

def print()

require 'mocha'

class ViewTest < Test::Unit::TestCasedef print() if document.print

puts "Excellent!"

def test_should_return_false_for_failed_printdocument = stub("my document") document stubs(:print) returns(true)p

true

else

document.stubs(:print).returns(true)

ui = View.new(document) assert ui.print

puts "Bummer."

false

end

assert ui.printend

endend

end

end

Page 35: Testing/Testing In Rails 1€¦ · Testing In General (1) • Formal Definition – Testin gg is the process of finding differences between the expected behavior specified by system

Mocking example (expects)Mocking example (expects)l E i i 't t/ it'class Enterprise

def initialize(dilithium)

require 'test/unit'require 'rubygems'require 'mocha'

@dilithium = dilithium

endclass EnterpriseTest < Test::Unit::TestCase

def test_should_boldly_godilithi k()def go(warp_factor)

warp_factor.times 

{ @dilithium.nuke(:anti_matter) }

dilithium = mock()dilithium.expects(:nuke).with(:anti_matter).at_least_onceenterprise = Enterprise.new(dilithium) enterprise.go(2)

end

end

p g ( )end

end

Page 36: Testing/Testing In Rails 1€¦ · Testing In General (1) • Formal Definition – Testin gg is the process of finding differences between the expected behavior specified by system

Expects More MockingExpects More Mocking

• Methods in expects:– at least, at least once, at most, at most once,   _ , _ _ , _ , _ _ ,in_sequence, multiple_yields, never, once, raises,   returns, then, times, when, with, yields , , , , , y