Minitest иногда преждевременно завершается без сообщения о завершении или ошибке

У меня есть тестовый файл 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

Программа, которую я пытаюсь протестировать, - 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 репо всего дерева)

Иногда тест проходит успешно, но гораздо чаще тест не доходит до «Завершено». В этих случаях есть ноль или более точек, представляющих (я полагаю) успешные утверждения. Я предполагаю, что запуск тестов останавливается из-за какого-то тайм-аута где-то в моем пакете, и что это время истекает периодически, потому что входные данные для теста имеют разный размер. Но если это проблема с тайм-аутом, почему нет сообщения об этом? Вот серия тестовых прогонов:

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$

🤔 А знаете ли вы, что...
Ruby - это динамический, интерпретируемый язык программирования.


24
1

Ответ:

Решено

Используйте break вместо exit:

break if error < tolerance

break выходит только из цикла do.

exit сам выходит из программы, не давая minitest возможности провалить тест