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
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