Рубиновые отрезные многострочные струны - программирование
Подтвердить что ты не робот

Рубиновые отрезные многострочные струны

Это лучший практический вопрос. Есть очевидные способы сделать это, но ни один из них не кажется совершенно правильным.

Довольно часто мне нужно проверить, что создается несколько многострочных строк. Обычно это прерывает отступы, и все выглядит как беспорядок:

class TestHelloWorld < Test::Unit::TestCase
  def test_hello
    assert_equal <<EOS, hello_world
Hello, world!
  World greets you
EOS
  end
end

С <<- я могу отступать здесь маркер doc, но он не разделяет отступы внутри heredoc, он по-прежнему выглядит ужасно.

class TestHelloWorld < Test::Unit::TestCase
  def test_hello
    assert_equal <<-EOS, hello_world
Hello, world!
  World greets you
    EOS
  end
end

Это позволяет мне отступать, но читаемость тестовой строки страдает. Этот gsub действительно не чувствует себя здесь.

class TestHelloWorld < Test::Unit::TestCase
  def test_hello
    assert_equal <<-EOS.gsub(/^ {6}/, ""), hello_world
      Hello, world!
        World greets you
    EOS
  end
end

Есть ли способ проверить такие многострочные строки, которые действительно читаемы?

4b9b3361

Ответ 1

Лично я считаю, что рудники с отступом heredocs бесполезны, и они должны больше работать как Bash с отступом heredocs, а также отбрасывать пробелы внутри строки & hellip;

Во всяком случае, есть несколько библиотек, которые пытаются справиться с этой ситуацией. Существует множество библиотек, которые пытаются решить эту проблему:

Ответ 2

Если вы создаете приложение Rails, попробуйте использовать strip_heredoc, если вы не всегда можете требовать расширения активной_подписки.

Ваш пример может выглядеть так:

require 'active_support/core_ext'

class TestHelloWorld < Test::Unit::TestCase
  def test_hello
    assert_equal <<-EOS.strip_heredoc, hello_world
      Hello, world!
        World greets you
    EOS
  end
end

Если вы действительно не хотите включать их, следующий код будет скопирован из active_support как и пример того, как вы могли бы обрабатывать форматирование.

class String
  def try(*a, &b)
    if a.empty? && block_given?
      yield self
    else
      __send__(*a, &b)
    end
  end

  def strip_heredoc
    indent = scan(/^[ \t]*(?=\S)/).min.try(:size) || 0
    gsub(/^[ \t]{#{indent}}/, '')
  end
end

Ответ 3

Я не уверен, что любой из них можно назвать "Лучшей практикой", но здесь есть четыре возможности

class Hello

  def self.world
"Hello, world!
  World greets you
"
  end
end

require 'test/unit'

class TestHelloWorld < Test::Unit::TestCase

#Define a constant array of multiline strings and test against the array
# see test_hello_4 
# Alternatively store the multi-line strings in a Yaml fixture file and load 
# them into a constant Hash or Array within a setup method
MLINE = [
"Hello, world!
  World greets you
",
"Another multi line string",
  ]

  # Create a method to return the string
  def test_hello_1
    assert_equal Hello.world, hello_world_string()
  end

  # Create the string using embedded newlines
  def test_hello_2
    assert_equal Hello.world, "Hello, world!\n  World greets you\n"
  end

  # if you only have 1 in the test then put it in a DATA section
  def test_hello_3
    assert_equal Hello.world, DATA.read
  end

  def test_hello_4
    assert_equal Hello.world, MLINE[0]
  end

  def hello_world_string
"Hello, world!
  World greets you
"
  end
end

__END__
Hello, world!
  World greets you

Все прохождение

Loaded suite test_hello_world
Started
....
Finished in 0.00083 seconds.

4 tests, 4 assertions, 0 failures, 0 errors

Я лично предпочел бы строку со встроенными новыми строками (метод 2), если строка не была очень длинной, и в этом случае я бы пошел в раздел DATA.

Ответ 4

Это тест о форматировании или о содержании?

Если это тест по форматированию, возможно, ваш тест слишком высокий, и вы должны протестировать класс "Formatter", и вы, вероятно, найдете способ протестировать класс таким образом, чтобы сделать многострочное текстовое сравнение бесполезным. И тогда вы сможете издеваться над классом Formatter, чтобы проверить, получит ли он весь контент, который ему нужен. Например, Formatter может быть классом, который имеет метод add_line, который добавляет "\n" после каждого аргумента, который он задает, и formatted_string, который возвращает многострочную строку. После того, как вы протестировали класс Formatter, вам просто нужно проверить, что он вызывается правильно. Таким образом, вы отделяете тесты для контента от тестов для формата.

Если это тест на контент, возможно, вам нужно просто разделить hello_world по строке, а затем проверить, что первая строка содержит "Hello, world", а вторая содержит "World greets you".

Я не думаю, что это хорошая практика для тестирования всего многострочного блока текста.