It's a best-practice question. There are obvious ways to do that, none of them just seem quite right.
Quite often I need to test that some multi-line string gets produced. This normally breaks indentation making everything look like a mess:
class TestHelloWorld < Test::Unit::TestCase
def test_hello
assert_equal <<EOS, hello_world
Hello, world!
World greets you
EOS
end
end
With <<-
I can indent here doc marker, but it doesn't strip indentation inside heredoc, it still looks horrible.
class TestHelloWorld < Test::Unit::TestCase
def test_hello
assert_equal <<-EOS, hello_world
Hello, world!
World greets you
EOS
end
end
This lets me indent but readability of test line suffers. This gsub
really doesn't feel right here.
class TestHelloWorld < Test::Unit::TestCase
def test_hello
assert_equal <<-EOS.gsub(/^ {6}/, ""), hello_world
Hello, world!
World greets you
EOS
end
end
Is there any way to test such multi-line strings that's really readable?
Personally, I think that Ruby's indented heredocs are useless and they should work more like Bash indented heredocs and also strip whitespace inside the string …
Anyway, there are a couple of libraries that try to deal with this situation. There is a wide array of libraries that try to fix this problem:
String#margin
Is it a test about formatting or about the content ?
If it's a test about formatting, maybe your test is too high level, and you should test a "Formatter" class and you'll probably find a way to test the class in a way that makes the multiline text comparison useless. And then, you would be able to mock the Formatter class to check that it will receive all the content it needs. For example, the Formatter could be a class that have a add_line method which adds a "\n" after each argument it is given and a formatted_string that will return the multiline string. Once you've tested the Formatter class, you'll just have to check it is called correctly. This way, you separate the tests for the content from the tests for the format.
If it's a test about the content, maybe you should just split the hello_world by line, and then check that the first line contains "Hello, world" and the second one contains "World greets you".
I don't think it's a good practice at all to test a whole multiline block of text.
If you're building a Rails application, try using
strip_heredoc
, if not you could always require active_support core extensions.Your Example might look like this:
If you really don't want to include them, the following code is copied from active_support as and example of how you might handle the formatting.
I'm not sure any of these could be called "Best Practice" but here are four possibilities
All passing
I would personally prefer the string with embedded newlines (Method 2) unless the string was very long in which case I would go with the DATA section.