Reputation: 79
I am trying to solve the timer problem from TestFirst Ruby.
I got the first two criteria correctly but the third one when tested for time = 12 seconds does not work. It does not look like Ruby is reading the time = 12 secs.
The codes are pretty lazy and not optimized, apparently. Also I did tried out the padded method but the test never worked. I had my padded method defined as
def padded(num)
if num<=9
return "0"<<num.to_s
else
return num.to_s
end
end
It would be great if someone can show me how to set that up correctly since that might have been the problems.
Here are my complete codes:
class Timer
#initialization of seconds
def seconds
return 0
end
#seconds= method
def seconds=(time)
@seconds = time_string(time)
end
#time_string method
def time_string(time=0)
#format of hour:minute:second
#minute must be less than 59 (or 59*60 seconds), otherwise it will convert to hour
minute = time/60 #note that this is integer math, so it will take the minute and not the remainder
hour = minute/60
remainder_seconds = time%60
if time<=9
return "00:00:0" << time.to_s
elsif time>9 && time<=60
return "00:00:" << time.to_s
elsif time>60 && time<=9*60 #9 minutes and greater than 1 min
#ensuring double XX seconds or 0X seconds (this would be easier to use the padded method)
if remainder_seconds >9
remainder_seconds_sd = remainder_seconds.to_s
else
remainder_seconds_sd = "0" << remainder_seconds.to_s
end
return "00:0" << minute.to_s << ":" << remainder_seconds_sd
end
end
end
RSpec below:
require '09_timer'
describe "Timer" do
before(:each) do
@timer = Timer.new
end
it "should initialize to 0 seconds" do
@timer.seconds.should == 0
end
describe 'time_string' do
it "should display 0 seconds as 00:00:00" do
@timer.seconds = 0
@timer.time_string.should == "00:00:00"
end
it "should display 12 seconds as 00:00:12" do
@timer.seconds = 12
@timer.time_string.should == "00:00:12"
end
it "should display 66 seconds as 00:01:06" do
@timer.seconds = 66
@timer.time_string.should == "00:01:06"
end
it "should display 4000 seconds as 01:06:40" do
@timer.seconds = 4000
@timer.time_string.should == "01:06:40"
end
end
# One way to implement the Timer is with a helper method.
# Uncomment these specs if you want to test-drive that
# method, then call that method from inside of time_string.
#
=begin
describe 'padded' do
it 'pads zero' do
@timer.padded(0).should == '00'
end
it 'pads one' do
@timer.padded(1).should == '01'
end
it "doesn't pad a two-digit number" do
@timer.padded(12).should == '12'
end
end
=end
end
Upvotes: 0
Views: 1081
Reputation: 11
A cleaner version:
class Timer
attr_accessor :seconds
def initialize
@seconds = 0
end
def time_string
seconds = @seconds % 60
minutes = (@seconds / 60) % 60
hours = @seconds / (60**2)
"#{padded(hours)}:#{padded(minutes)}:#{padded(seconds)}"
end
def padded(num)
return '0' + num.to_s if num < 10
return num.to_s if num >= 10
end
end
Upvotes: 1
Reputation: 9639
The problem with your tests and Timer
is that, in your tests you are setting the value of @timer.seconds
, but the Timer#time_string
does not rely on the @seconds
variable set. Your time_string
method is implemented the way it accepts the amount of seconds
as an argument, not an attribute of Timer
.
Try changing your tests as follows:
describe "Timer" do
# rest of your code
describe 'time_string' do
it "should display 0 seconds as 00:00:00" do
@timer.time_string(0).should == "00:00:00"
end
it "should display 12 seconds as 00:00:12" do
@timer.time_string(12).should == "00:00:12"
end
it "should display 66 seconds as 00:01:06" do
@timer.time_string(66).should == "00:01:06"
end
it "should display 4000 seconds as 01:06:40" do
@timer.time_string(4000).should == "01:06:40"
end
end
end
You might be wondering okay, but why the first test - 00:00:00 - did work in first place?. Well, this is, because your time_string
method argument defaults to 0:
def time_string(time=0)
# Rest of the code
end
and because you were not passing any other value, the 0 has been used.
If you have any questions - I'm happy to help!
Good luck!
Edit
If you want to make it the other way around - make the class to work for your tests, change your Timer
class:
class Timer
def initialize
@seconds = 0
end
def seconds
@seconds
end
def seconds=(time)
@seconds = time
end
def time_string
#format of hour:minute:second
#minute must be less than 59 (or 59*60 seconds), otherwise it will convert to hour
minute = @seconds/60 #note that this is integer math, so it will take the minute and not the remainder
hour = minute/60
remainder_seconds = @seconds%60
if @seconds<=9
return "00:00:0" << @seconds.to_s
elsif @seconds>9 && @seconds<=60
return "00:00:" << @seconds.to_s
elsif @seconds>60 && @seconds<=9*60 #9 minutes and greater than 1 min
#ensuring double XX seconds or 0X seconds (this would be easier to use the padded method)
if remainder_seconds >9
remainder_seconds_sd = remainder_seconds.to_s
else
remainder_seconds_sd = "0" << remainder_seconds.to_s
end
return "00:0" << minute.to_s << ":" << remainder_seconds_sd
end
end
end
We have added initialize
method, we have changed def seconds=(time)
method, and we have changed all occurrences of time
in your time_string
method.
If that works for you, consider posting the code to https://codereview.stackexchange.com/. There is a lot in the code to improve, and codereview is a great place to ask for help!
Upvotes: 1