Académique Documents
Professionnel Documents
Culture Documents
(behavior driven
design) Passing (green) RSpec test
• RSpec tests
individual
Passing (green)
modules that Cucumber step
contribute to
those behaviors 6
Testing stacks revisited
Capybara RSpec
Selenium Rack::Test
Rack
browse
r
Rails app
web
server
SaaS Integration Unit & Funct.
app
Tests tests
Which are true about BDD & TDD:
a) requirements drive the
implementation
b) they can be used only in Agile
development
c)☐they
Onlyembrace
(a) & deal with change
8
END
9
FIRST, TDD, and Getting
Started With RSpec
(Engineering Software as a
Service §8.2)
Armando Fox
• Independent
• Repeatable
• Self-checking
• Timely
Unit tests should be
FIRST
• Fast: run (subset of) tests quickly
(since you’ll be running them all the
time)
• Independent: no tests depend on
others, so can run any subset in
any order
• Repeatable: run N times, get same
result (to help isolate bugs and
enable automation)
• Self-checking: test can
RSpec, a Domain-
Specific Language for
testing
• DSL: small programming language
that simpifies one task at expense
of generality
– examples so far: migrations, regexes,
SQL
• RSpec tests are called specs or
examples
expect(x.odd?).to be_true
expect(x).to be_odd
expect(hash['key']).to be_truthy
describe "BookInStock" do
it "should be defined" do
expect { BookInStock }.not_to raise_error
end
expect
{ lambda }.to(assertion)
expect(expression).to(assertio
Which kinds of code can be tested
Repeatably and Independently?
a) Code that relies on randomness (e.g.
shuffling a deck of cards)
b) Code that relies on time of day (e.g.
run backups every Sunday at midnight)
☐ Only (a)
☐ Only (b)
17
END
18
RSpec on Rails
(Engineering Software as a
Service §8.2)
Armando Fox
☐ A helper method
23
cut
24
RSpec-Rails & TDD Cycle:
Red–Green–Refactor
(Engineering Software as a Service
§8.2-8.3)
Armando Fox
☐ A helper method
29
How to test something “in
isolation” if it has
dependencies that would
affect test?
The Code You Wish You
Had
What should the controller method
do that receives the search form?
1. call a method that will search
TMDb for specified movie
2. if match found: select (new)
“Search Results” view to display
match
3. If no match found: redirect to
home page with message
http://pastebin.com/LcejGjYs
require 'rails_helper'
describe MoviesController do
describe 'searching TMDb' do
it 'calls the model method that performs TMDb search'
it 'selects the Search Results template for rendering'
it 'makes the TMDb search results available to that
template'
end
end
TDD for the Controller
action: Setup
• Add a route to config/routes.rb
# Route that posts 'Search TMDb' form
post '/movies/search_tmdb'
– Convention over configuration will map
this to MoviesController#search_tmdb
• Create an empty view:
touch app/views/movies/search_tmdb.html.haml
• Replace fake “hardwired” method in
movies_controller.rb with empty
method:
def search_tmdb
What model method?
• Calling TMDb is responsibility of the
model... but no model method exists to
do this yet!
• No problem...we’ll "fake" the call to the
code we wish we had (“CWWWH”),
Movie.find_in_tmdb
• Game plan:
– Simulate POSTing search form to controller
action.
– Check that controller action tries to call
Movie.find_in_tmdb with data from submitted
form. http://pastebin.com/kGXbxVq9
– The test will fail (red), because the (empty)
require 'rails_helper'
describe MoviesController do
describe 'searching TMDb' do
it 'calls the model method that performs TMDb search' do
expect(Movie).to
receive(:find_in_tmdb).with('hardware')
post :search_tmdb, {:search_terms => 'hardware'}
end
it 'selects the Search Results template for rendering'
it 'makes the TMDb search results available to that
template'
end
end
Which is FALSE about
expect(...).to_receive?
Optional!
Eventually we will have to write a
real find_in_tmdb. When that
happens, we should:
☐ expect(result).to_not be_empty
describe MoviesController do
describe 'searching TMDb' do
it 'calls the model method that performs TMDb search' do
fake_results = [mock('movie1'), mock('movie2')]
expect(Movie).to receive(:find_in_tmdb).with('hardware').
and_return(fake_results)
post :search_tmdb, {:search_terms => 'hardware'}
end
it 'selects the Search Results template for rendering' do
fake_results = [mock('Movie'), mock('Movie')]
Movie.stub(:find_in_tmdb).and_return(fake_results)
post :search_tmdb, {:search_terms => 'hardware'}
expect(response).to render_template('search_tmdb')
end
it 'makes the TMDb search results available to that template'
end
end
Note that this view has to exist!
post :search_tmdb will try to do whole MVC
flow, including rendering functional (not
Test techniques we
know
expect(obj).to_receive(a).with(b)
Optional!
Test techniques we
know
expect(obj).to_receive(a).with(b)
expect(obj).to match-condition
response()
render_template()
to_receive combines _____ and
_____,
whereas stub is only _____.
A mock and an expectation;
☐ a mock
☐ A mock and an expectation;
an expectation
☐ A seam and an expectation;
an expectation
☐ A seam and an expectation;
a seam
57
cut
58
Mocks & Doubles
(Engineering Software as a
Service §8.4)
expect(obj).to match-condition
66
cut
67
Fixtures and Factories
(Engineering Software as a
Service §8.5)
Armando Fox
fixtures :movies
it 'finds movie by title' do
movie = movies(:milk_movie)
# etc.
end
end
Factories
• Set up “helpers” to quickly create
objects with default attributes, as
needed per-test
• Pros/uses:
– Keep tests Independent: unaffected by
presence of objects they don’t care
about
• Cons/reasons not to use:
– Complex relationships may be hard to
set up (but may indicate too-tight
coupling in code!)
Example: FactoryGirl
gem
# in spec/factories/movie.rb
FactoryGirl.define do
factory :movie do
title 'A Fake Title' # default values
rating 'PG'
release_date { 10.years.ago }
end
or create
end
# in your specs
it 'should include rating and year' do
movie = FactoryGirl.build(:movie, :title => 'Milk')
# etc.
end
Which of the following kinds
of data, if any, should not be
set up as fixtures?
75
cut
76
TDD for the Model
& Stubbing the Internet
(Engineering Software as a
Service §8.6–8.7)
Armando Fox
80
You’re integrating Stripe payments
with your SaaS app. They have a
“sandbox” server that sends canned
replies to specific requests. Which
kind(s) of tests should you create?
☐ Integration tests that can be run
against their sandbox server
☐ Integration tests that use Webmock
or similar to “stub out” the Internet
☐ Functional and/or unit tests that stub
81
cut
82
Coverage, Unit vs.
Integration Tests
(Engineering Software as a
Service §8.8)
Armando Fox
• Functional or eg,con-
troller
module (a few specs
methods/classes)
100
cut
101
Plan-And-Document
Perspective on Software
Testing
(Engineering Software as a Service §8.10)
David Patterson
107
QA Team Testing
• Next QA Team does System Test
– Full app should work
– Test non-functional requirements
(performance) + functional
requirements (features in SRS)
• When P&D System Testing Done?
– Organization policy
• Eg, test coverage level (all statements)
• Eg, all inputs tested with good and bad
data
• Final step: Customer or User 108
Limits of Testing
• Program testing can be used to
show the presence of bugs, but
never to show their absence!
– Edsger W. Dijkstra
109
Formal Methods
• Start with formal specification
& prove program behavior
follows spec.
1. Human does proof
2. Computer via automatic
theorem proving
– Uses inference + logical axioms
to produce proofs from scratch
3. Computer via model checking
– Verifies selected properties by
exhaustive search of all possible 110
Formal Methods
• Computationally expensive, so
use
– Small, fixed function
– Expensive to repair, very hard to
test
– Eg. Network protocols, safety
critical SW
• Biggest: OS kernel
10K LOC @ $500/LOC
– NASA SW $80/LOC
• This course: rapidly changing 111
SW Testing: P&D vs.
Agile
(Fig. 8.26)
112
Which statement regarding testing is
FALSE?