Slide 56
Slide 56 text
Refactoring
More Functional Core More Functional Core Tests
!
describe Core::UsageReport do
let(:ref_time) { Time.new(2014, 6, 21, 10) }
let(:users_with_sessions) {
[Core::User.new(“Joe”)
.add_session(ref_time - 2.hours, ref_time - 1.hour)
.add_session(ref_time - 30.minutes, ref_time),
Core::User.new(“Jane”)
.add_session(ref_time - 2.hours, ref_time - 1.hour)]
}
!
describe “.build” do
it do
rows = subject.build(users_with_sessions)
expect(rows.first.last).to eq(2700.0)
expect(rows.last.last).to eq(3600.0)
end
end
end
class Core::User
def initialize(name, sessions = [])
@name = name
@sessions = sessions
end
!
attr_reader :name, :sessions
!
def add_session(started_at, ended_at)
User.new(name, sessions +
[UserSession.new(started_at, ended_at)])
end
end
!
module Core::UsageReport
def self.build(users_with_sessions)
users_with_sessions.map { |user|
[user.name,
SessionStats.average_time_on_site(user.sessions)]
}
end
end
and
We do the same for User and the UsageReport itself. Again, we can skip mocking.
It’s interesting to notice how much the widespread use of DI in Ruby is about isolating boundaries for testing. In that sense, DHH has a point (although I
disagree viscerally about the usefulness of TDD). It’s a useful tool for when your design may need customization or extension, but here we show that we
can have fast tests and ted without resorting to DI or test doubles.