Hi I'm completely new to Ruby. I'm trying to run Minitests, it use to work fine until I added a constructor to my CountDown class.
Here is the code:
require 'benchmark'
require 'minitest/autorun'
#! /usr/bin/env ruby
#This is our countdown class
# :reek:DuplicateMethodCall
# :reek:TooManyStatements
class CountDown
def initialize(time)
#time = time
end
def count()
wait_time = #time.to_i
print wait_time.to_s + " seconds left\n"
sleep 1
wait_time = wait_time - 1
wait_time.downto(1).each do |time_left|
sleep 1
print time_left.to_s + " seconds left\n" if (time_left % 60) == 0
end
print "\a"
end
end
#This class is responsible for our test cases
class CountDownTest < Minitest::Test
def setup
#count_down = CountDown.new(10)
end
def testing_lowerbound
time = Benchmark.measure{
#count_down.count
}
assert time.real.to_i == 10
end
end
This my my output:
teamcity[enteredTheMatrix timestamp = '2017-09-28T15:10:11.470-0700']
teamcity[testCount count = '0' timestamp = '2017-09-28T15:10:11.471-0700'] Finished in 0.00038s 0 tests, 0
assertions, 0 failures, 0 errors, 0 skips
Process finished with exit code 0
Any idea what's wrong? It looks fine to me.
Tests should start with the prefix test_ not testing_. Using the wrong prefix makes MiniTest assume they're doing something other than running a test, so it ignores them.
Related
I have a test file, ipca_test.rb:
require "test_helper"
require "matrix" # Does needing to include this here mean I'm doing something wrong?
class IpcaTest < Minitest::Test
def test_that_it_has_a_version_number
refute_nil ::Ipca::VERSION
end
def test_it_does_something_useful
refute false
end
def test_on_a_random_matrix
p = rand(3..10)
n = rand(20..50)
m = Matrix.build(n, p) {|_, _| rand(-10.0..10.0)}
pca = Ipca::Pca.new(m)
eigenvalue, r = pca.first_principal_component
puts "eigenvalue: #{eigenvalue}, r: #{r}"
assert eigenvalue.kind_of? Numeric
assert_equal Vector, r.class
end
end
The program I'm trying to test is ipca.rb:
require "ipca/version"
module Ipca
class Error < StandardError; end
class Pca
def initialize data
#data = data.class == Matrix ? data : Matrix.rows(data)
end
# see https://en.wikipedia.org/wiki/Principal_component_analysis#Iterative_computation
def first_principal_component(c = 100, tolerance = 0.001) # not sure whether defaults are apropos
p = #data.column_vectors.count
r = Vector.elements(Array.new(p) {|_| rand}).normalize
eigenvalue = nil
c.times do
s = Vector.zero(p)
#data.row_vectors.each do |x|
s += x.dot(r)*x
end
eigenvalue = r.dot(s) # ?
error = (eigenvalue*r-s).norm
r = s.normalize
exit if error < tolerance
end
return [eigenvalue, r]
end
end
end
(Git repo of entire tree)
Sometimes the test is successful, but much more often the test never gets to "Finished". In these cases there are zero or more dots representing (I assume) successful assertions. I'm guessing that the tests runs are being halted by some kind of timeout somewhere in my bundle, and that this times out intermittently because the input data for the test is of varying size. But if it's a timeout issue why is there not a message to that effect? Here is a series of test runs:
josie#josie-Inspiron-580:/var/www/html/ruby/ipca$ ruby -Itest
test/ipca_test.rb Run options: --seed 44059
# Running:
..josie#josie-Inspiron-580:/var/www/html/ruby/ipca$ ruby -Itest
test/ipca_test.rb Run options: --seed 57681
# Running:
.josie#josie-Inspiron-580:/var/www/html/ruby/ipca$ ruby -Itest
test/ipca_test.rb Run options: --seed 57222
# Running:
..josie#josie-Inspiron-580:/var/www/html/ruby/ipca$ ruby -Itest
test/ipca_test.rb Run options: --seed 7474
# Running:
..josie#josie-Inspiron-580:/var/www/html/ruby/ipca$ ruby -Itest
test/ipca_test.rb Run options: --seed 1938
# Running:
..josie#josie-Inspiron-580:/var/www/html/ruby/ipca$ ruby -Itest
test/ipca_test.rb Run options: --seed 61325
# Running:
..eigenvalue: 2027.687580111128, r: Vector[0.03288542301229099,
-0.09533529249551115, 0.3033273986606458, 0.07951734565050736, 0.3575555246291426, 0.41614419068773545, 0.4928822662304588, 0.28785088479078025, 0.5144766379975693] .
Finished in 0.037173s, 80.7047 runs/s, 107.6063 assertions/s.
3 runs, 4 assertions, 0 failures, 0 errors, 0 skips
josie#josie-Inspiron-580:/var/www/html/ruby/ipca$
Use break instead of exit:
break if error < tolerance
break exits just the do loop.
exit exits the program itself not giving a chance for minitest to fail the test
I had this code passing ALL the specs the other day, so I moved it into another folder (for completed assignments). When I tried to run the specs again on it from there, I couldn't get the file to load despite typing the path exactly (several times) as I saw it. Hmmmm. Is there some special way to run rspecs from a subfolder?? Anyways, So I moved it back to the main directory it was in, and tried from there, and suddenly it would't pass!! I must have accidentally deleted something. But for the life of me after almost two days...I just DON'T SEE IT. I've gone through it a million times and it seems like it should be working, and when I take the methods out of the class they return as expected. I need fresh eyes. Why is this code suddenly not passing?
class :: Timer
attr_accessor :seconds, :padded, :time_string
def initialize(seconds = 0)
#seconds = seconds
end
def padded(num)
num = num.to_s
num.length == 1 ? "0#{num}" : "#{num}"
end
def time_string=(seconds)
#seconds = seconds
mins = 0
hours = 0
if seconds == 0
return "00:00:00"
elsif seconds < 60
return "00:00:#{padded(seconds)}"
end
while seconds > 59
mins += 1
seconds -= 60
if mins > 59
hours += 1
mins -= 60
end
end#while
return "#{padded(hours)}:#{padded(mins)}:#{padded(seconds)}"
end
end#class
Here are the specs:
require_relative '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.
#
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
class :: Timer
attr_accessor :seconds
def initialize(seconds = 0)
#seconds = seconds
end
def padded(num)
num = num.to_s
num.length == 1 ? "0#{num}" : "#{num}"
end
def time_string
seconds = #seconds
mins = 0
hours = 0
if seconds == 0
return "00:00:00"
elsif seconds < 60
return "00:00:#{padded(seconds)}"
end
while seconds > 59
mins += 1
seconds -= 60
if mins > 59
hours += 1
mins -= 60
end
end#while
return "#{padded(hours)}:#{padded(mins)}:#{padded(seconds)}"
end
end#class
Specs
require_relative '09_timer'
describe "Timer" do
before(:each) do
#timer = Timer.new
end
it "should initialize to 0 seconds" do
expect(#timer.seconds).to eq 0
end
describe 'time_string' do
it "should display 0 seconds as 00:00:00" do
#timer.seconds = 0
expect(#timer.time_string).to eq "00:00:00"
end
it "should display 12 seconds as 00:00:12" do
#timer.seconds = 12
expect(#timer.time_string).to eq "00:00:12"
end
it "should display 66 seconds as 00:01:06" do
#timer.seconds = 66
expect(#timer.time_string).to eq "00:01:06"
end
it "should display 4000 seconds as 01:06:40" do
#timer.seconds = 4000
expect(#timer.time_string).to eq "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.
#
describe 'padded' do
it 'pads zero' do
expect(#timer.padded(0)).to eq '00'
end
it 'pads one' do
expect(#timer.padded(1)).to eq '01'
end
it "doesn't pad a two-digit number" do
expect(#timer.padded(12)).to eq '12'
end
end
end
I don't really know how your code got messed up, but the time_string method isn't taking any arguments in your specs, and I don't see why it would just from a logical perspective. Therefore I took out the =(seconds) part from its method signature.
You were also setting the instance variable #seconds to the passed argument, but really we want to use a local seconds variable that starts out as the instance variable, so that just gets flipped around to seconds = #seconds.
Lastly, I changed your specs to use the new expect syntax instead of should which is now deprecated.
I'm starting the 06_performance_monitor exercise in TestFirst Ruby and the failure it lists is in the Rspec that was provided in the materials for TestFirst Ruby tutorial (where it says undefined method 'measure'). From what I've been able to find online, it seems this tutorial was written for Rspec 2 and Ruby 1.9. I currently have Rspec 2.99.0, Ruby 1.9.3, and Rake 0.9.22 installed. I guess my question is, what am I doing wrong/do I need different versions? I don't understand why the provided Rspec doesn't seem to work as it should. This happened in one other exercise for this tutorial but it was only a minor error message that didn't interfere with my testing.
caitlyns-mbp:06_performance_monitor caitlynyu$ rake
(in /Users/caitlynyu/Desktop/learn_ruby)
Run options: include {:focus=>true}
All examples were filtered out; ignoring {:focus=>true}
Performance Monitor
runs a block N times (FAILED - 1)
Failures:
1) Performance Monitor runs a block N times
Failure/Error: measure(4) do
NoMethodError:
undefined method `measure' for #<RSpec::Core::ExampleGroup::Nested_1:0x007fcdc11b8578>
# ./06_performance_monitor/performance_monitor_spec.rb:53:in `block (2 levels) in <top (required)>'
Finished in 0.00081 seconds
1 example, 1 failure
Failed examples:
rspec ./06_performance_monitor/performance_monitor_spec.rb:51 # Performance Monitor runs a block N times
Randomized with seed 2933
/Users/caitlynyu/.rvm/rubies/ruby-1.9.3-p547/bin/ruby -S rspec /Users/caitlynyu/Desktop/learn_ruby/06_performance_monitor/performance_monitor_spec.rb -I/Users/caitlynyu/Desktop/learn_ruby/06_performance_monitor -I/Users/caitlynyu/Desktop/learn_ruby/06_performance_monitor/solution -f documentation -r ./rspec_config failed
caitlyns-mbp:06_performance_monitor caitlynyu$
UPDATE
My code below (I know it doesn't pass any of the tests below, I was just playing around with this first):
def performance_monitor
start = Time.now
yield
return "#{Time.now - start}"
end
I've never used a method called 'measure' that shows up in the Rspec which is below:
# # Topics
#
# * stubs
# * blocks
# * yield
#
# # Performance Monitor
#
# This is (a stripped down version of) an actual useful concept: a
# function that runs a block of code and then tells you how long it
# took to run.
require "performance_monitor"
require "time" # loads up the Time.parse method -- do NOT create time.rb!
describe "Performance Monitor" do
before do
#eleven_am = Time.parse("2011-1-2 11:00:00")
end
it "takes about 0 seconds to run an empty block" do
elapsed_time = measure do
end
elapsed_time.should be_within(0.1).of(0)
end
it "takes exactly 0 seconds to run an empty block (with stubs)" do
Time.stub(:now) { #eleven_am }
elapsed_time = measure do
end
elapsed_time.should == 0
end
it "takes about 1 second to run a block that sleeps for 1 second" do
elapsed_time = measure do
sleep 1
end
elapsed_time.should be_within(0.1).of(1)
end
it "takes exactly 1 second to run a block that sleeps for 1 second (with stubs)" do
fake_time = #eleven_am
Time.stub(:now) { fake_time }
elapsed_time = measure do
fake_time += 60 # adds one minute to fake_time
end
elapsed_time.should == 60
end
it "runs a block N times" do
n = 0
measure(4) do
n += 1
end
n.should == 4
end
it "returns the average time, not the total time, when running multiple times" do
run_times = [8,6,5,7]
fake_time = #eleven_am
Time.stub(:now) { fake_time }
average_time = measure(4) do
fake_time += run_times.pop
end
average_time.should == 6.5
end
it "returns the average time when running a random number of times for random lengths of time" do
fake_time = #eleven_am
Time.stub(:now) { fake_time }
number_of_times = rand(10) + 2
average_time = measure(number_of_times) do
delay = rand(10)
fake_time += delay
end
average_time.should == (fake_time - #eleven_am).to_f/number_of_times
end
end
Ruby Mongo Driver question:
How do I output 5_000 document batches from the collection at a time until I read the last document in the collection without dumping the entire database into memory first?
This is really bad method for me:
mongo = MongoClient.new('localhost', 27017)['sampledb']['samplecoll']
#whois.find.to_a....
Mongo::Collection#find returns a Mongo::Cursor that is Enumerable. For batch processing Enumerable#each_slice is your friend and well worth adding to your toolkit.
Hope that you like this.
find_each_slice_test.rb
require 'mongo'
require 'test/unit'
class FindEachSliceTest < Test::Unit::TestCase
def setup
#samplecoll = Mongo::MongoClient.new('localhost', 27017)['sampledb']['samplecoll']
#samplecoll.remove
end
def test_find_each_slice
12345.times{|i| #samplecoll.insert( { i: i } ) }
slice__max_size = 5000
#samplecoll.find.each_slice(slice__max_size) do |slice|
puts "slice.size: #{slice.size}"
assert(slice__max_size >= slice.size)
end
end
end
ruby find_each_slice_test.rb
Run options:
# Running tests:
slice.size: 5000
slice.size: 5000
slice.size: 2345
.
Finished tests in 6.979301s, 0.1433 tests/s, 0.4298 assertions/s.
1 tests, 3 assertions, 0 failures, 0 errors, 0 skips
This question sounds stupid, but I never found an answer online to do this.
Assume you have a test suite like this page:
http://en.wikibooks.org/wiki/Ruby_Programming/Unit_testing
or code:
require "simpleNumber"
require "test/unit"
class TestSimpleNumber < Test::Unit::TestCase
def test_simple
assert_equal(4, SimpleNumber.new(2).add(2) )
assert_equal(4, SimpleNumber.new(2).multiply(2) )
end
def test_typecheck
assert_raise( RuntimeError ) { SimpleNumber.new('a') }
end
def test_failure
assert_equal(3, SimpleNumber.new(2).add(2), "Adding doesn't work" )
end
end
Running the code:
>> ruby tc_simpleNumber2.rb
Loaded suite tc_simpleNumber2
Started
F..
Finished in 0.038617 seconds.
1) Failure:
test_failure(TestSimpleNumber) [tc_simpleNumber2.rb:16]:
Adding doesn't work.
<3> expected but was
<4>.
3 tests, 4 assertions, 1 failures, 0 errors
Now, how to use a variable (what kind?) to save the testing results?
e.g., an array like this:
[{:name => 'test_simple', :status => :pass},
{:name => 'test_typecheck', :status => :pass},
{:name => 'test_failure', :status => :fail},]
I am new to testing, but desperate to know the answer...
you need to execute your test script file, that's it, the result will display pass or fails.
Suppose you save file test_unit_to_rspec.rb, after that execute below command
ruby test_unit_to_rspec.rb
Solved the problem with setting a high verbose level, in a test runner call.
http://ruby-doc.org/stdlib-1.8.7/libdoc/test/unit/rdoc/Test/Unit/UI/Console/TestRunner.html
require 'test/unit'
require 'test/unit/ui/console/testrunner'
class MySuperSuite < Test::Unit::TestSuite
def self.suite
suites = self.new("My Super Test Suite")
suites << TestSimpleNumber1
suites << TestSimpleNumber2
return suites
end
end
#run the suite
# Pass an io object
#new(suite, output_level=NORMAL, io=STDOUT)
runner = Test::Unit::UI::Console::TestRunner.new(MySuperSuite, 3, io)
results will be saved in the io stream in a nice format fo each test case.
What about using '-v' (verbose):
ruby test_unit_to_rspec.rb -v
This should show you a lot more information
You can check out another of Nat's posts for a way to capture the results. The short answer to your question is that there is no variable for capturing the results. All you get is:
Loaded suite My Special Tests
Started
..
Finished in 1.000935 seconds.
2 tests, 2 assertions, 0 failures, 0 errors
Which is not very helpful if you want to report to someone else what happened. Nat's other post shows how to wrap the Test::Unit in rspec to get a better result and more flexibility.
class Test::Unit::TestCase
def setup
#id = self.class.to_s()
end
def teardown
#test_result = "pass"
if(#_result.failure_count > 0 || #_result.error_count > 0)
#test_result = "fail"
# making sure no errors/failures exist before the next test case runs.
i = 0
while(i < #_result.failures.length) do
#_result.failures.delete_at(i)
i = i + 1
end
while(i < #_result.errors.length) do
#_result.errors.delete_at(i)
i = i + 1
end
#test_result = "fail"
end # if block ended
puts"#{#id}: #{#test_result}"
end # teardown definition ended
end # class Test::Unit::TestCase ended
Example Output :
test1: Pass
test2: fail
so on....